Documentation
Documentation
Introduction

Getting Started

Getting started
Getting StartedInstallationQuick StartProject Structure

Configuration

Configuration
ConfigurationEnvironment ConfigurationEdge ConfigDatabaseAuth SecretStripeFirebaseStorageGoogle Maps And Cloud Service AccountOAuth ProvidersEmail DeliverySentryFeature Flags

Architecture

Architecture
Architecture OverviewTech StackoRPC MiddlewareDesign Principles

Patterns

Patterns
Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

Database
DatabaseSetupSchema DefinitionDatabase OperationsMigrationsCaching
Data Tables

API

oRPCProceduresRoutersoRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

Storage
StorageConfigurationUsageBuckets
Stripe Billing

Extra

Caching

Templates

Templates
Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate oRPC RouterAdd Translations

Development

Development
DevelopmentCommandsAI AgentsBest Practices
Pulling Updates

Architecture Overview

Understanding the high-level system design and feature-based architecture

Introduction

This project is built on a modern, type-safe stack designed for scalability, performance, and developer experience. The architecture follows a feature-based approach where related code is grouped together by domain, making the codebase easier to navigate and maintain.

High-Level System Design

The application is structured around these core principles:

  • Type-safe API layer - Using oRPC for end-to-end type safety
  • Server-first architecture - Leveraging Next.js App Router for server-side rendering and data fetching
  • Feature modules - Organizing code by business domain rather than technical layer
  • Database abstraction - Using Drizzle ORM with reusable CRUD operations
  • Component-driven UI - Building with Shadcn UI and Tailwind CSS

Project Structure

src/
├── app/            # Next.js App Router (pages, layouts, API routes)
├── components/     # Shared UI components (atoms, molecules)
├── config/         # App-wide configuration (colors, site settings)
├── db/             # Database schema, migrations, and operations
├── emails/         # Email templates (React Email)
├── features/       # Feature-specific logic (domain modules)
├── forms/          # Form-related abstractions and components
├── hooks/          # Shared React hooks
├── i18n/           # Internationalization setup
├── layouts/        # Page layout components
├── lib/            # Utilities and 3rd-party library configs
├── messages/       # Translation files
├── providers/      # React context providers
├── routes/         # Declarative routing configuration
├── store/          # Client-side state stores (Zustand)
├── trpc/           # oRPC routers and server configuration
└── types/          # Global type definitions

Feature-Based Architecture

Each major domain of the application (e.g., auth, organizations, subscriptions) is encapsulated in its own feature folder within src/features/. This approach:

  • Keeps related code together - All logic for a feature lives in one place
  • Reduces cognitive load - Developers can focus on one domain at a time
  • Improves maintainability - Changes are localized to specific features
  • Enables team scaling - Different teams can own different features

Standard Feature Structure

A typical feature folder follows the 5-file pattern:

src/features/organizations/
├── schema.ts       # Zod schemas for validation and types
├── functions.ts    # Server-side logic and database operations
├── hooks.ts        # Client-side oRPC hooks
├── fields.tsx      # Reusable form field components
├── prompts.tsx     # Dialog/modal wrappers
└── components/     # Feature-specific UI components

See the Features guide for detailed information on creating feature modules.

Key Architectural Concepts

Database Access

We use Drizzle ORM for all database interactions:

  • Type-safe queries - Full TypeScript support with autocomplete
  • Schema definitions - Tables defined in src/db/tables/
  • Reusable operations - Standard CRUD via createDrizzleOperations

Example database operation:

import { userOperations } from "@/db/tables/users.ts";

// Get a user by ID
const user = await userOperations.getById(userId);

// Create a new user
const newUser = await userOperations.create({
  name: "John Doe",
  email: "john@example.com",
});

Learn more in the Database guide.

API & Data Fetching

oRPC provides end-to-end type safety between client and server:

  • Type inference - Client automatically knows the shape of server responses
  • No code generation - Types are inferred directly from implementations
  • Unified error handling - Consistent error formatting and translation
  • Automatic serialization - Using SuperJSON for dates, Sets, Maps, etc.

Example oRPC usage:

// Server-side procedure
export const userRouter = createRPCRouter({
  getById: publicProcedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input }) => {
      return await userOperations.getById(input.id);
    }),
});

// Client-side hook
const { data: user } = api.users.getById.useQuery({ id: "123" });

Learn more in the oRPC guide and API guide.

Authentication

Better-Auth handles all authentication flows:

  • Multi-provider support - Email, OAuth (Google, GitHub), Magic Links
  • Server-side access - Via getAuth() in Server Components
  • Client-side access - Via useAuth() hook in Client Components
  • Secure session management - HTTP-only cookies, CSRF protection

Example authentication check:

// Server Component
import { getAuth } from "@/lib/auth/server";

export default async function ProfilePage() {
  const auth = await getAuth();
  
  if (!auth.user) {
    redirect("/login");
  }
  
  return <div>Welcome, {auth.user.name}</div>;
}

// Client Component
"use client";
import { useAuth } from "@/lib/auth/client";

export function UserMenu() {
  const { user, signOut } = useAuth();
  
  return <button onClick={signOut}>Sign Out</button>;
}

Learn more in the Authentication guide.

Routing

We use Declarative Routing for type-safe navigation:

  • Type-safe routes - Compile-time checking of route parameters
  • Automatic breadcrumbs - Generated from route definitions
  • i18n integration - Automatic locale prefix handling
  • SEO optimization - Metadata generation from route config

Example route usage:

import { PageProfile } from "@/routes";

// Generate a URL
const url = PageProfile({ userId: "123" });
// Result: "/en/profile/123"

// Generate a link component
<PageProfile.Link userId="123">View Profile</PageProfile.Link>

Learn more in the Routing guide.

Middleware Chain

The oRPC middleware stack processes every request in a specific order. This ensures consistent behavior across all API endpoints.

See the Middleware guide for detailed information on each middleware.

Error Handling

Errors are handled consistently across the application:

  • Custom error classes - NotFoundError, ValidationError, UnauthorizedError
  • Automatic translation - Based on user's locale
  • Structured responses - Including Zod validation details for forms
  • Sentry integration - Automatic error tracking and alerting

Learn more in the Errors guide.

Design Principles

The architecture is guided by these core principles:

  • Type Safety - TypeScript and Zod everywhere
  • Separation of Concerns - UI, logic, and data access are separate
  • Reusability - Small, composable components and functions
  • Performance - Server-side rendering and strategic caching
  • Modularity - Feature-based organization for scalability
  • DRY Principle - Abstractions to avoid repetition

Learn more in the Design Principles guide.

Next Steps

Core Concepts

  • Tech Stack
  • Middleware
  • Design Principles

Implementation Guides

  • Features
  • Database
  • oRPC API
  • Authentication
  • Routing

On this page

Introduction
High-Level System Design
Project Structure
Feature-Based Architecture
Standard Feature Structure
Key Architectural Concepts
Database Access
API & Data Fetching
Authentication
Routing
Middleware Chain
Error Handling
Design Principles
Next Steps
Core Concepts
Implementation Guides