Documentation
Documentation
Introduction

Getting Started

Getting StartedInstallationQuick StartProject Structure

Architecture

Architecture OverviewTech StacktRPC MiddlewareDesign Principles

Patterns

Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

DatabaseSchema DefinitionDatabase OperationsMigrationsCaching

API

tRPCProceduresRouterstRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

StorageConfigurationUsageBuckets

Configuration

ConfigurationEnvironment VariablesFeature Flags

Templates

Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate tRPC RouterAdd Translations

Development

DevelopmentCommandsAI AgentsBest Practices

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 tRPC 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/           # tRPC 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 tRPC 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

tRPC 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 tRPC usage:

// Server-side procedure
export const userRouter = createTRPCRouter({
  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 tRPC 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 tRPC 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
  • tRPC 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