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

Code Patterns & Conventions

Proven patterns and conventions for building maintainable, scalable features

Introduction

This section covers the code patterns and conventions used throughout this project. Following these patterns ensures consistency, maintainability, and reduces the cognitive load when navigating the codebase.

These patterns have been refined over multiple projects and embody best practices for type-safe, feature-based development with Next.js, tRPC, and Drizzle ORM.

Why Patterns Matter

Consistency

When all features follow the same structure, developers can:

  • Find code quickly - Know exactly where to look for schemas, hooks, or functions
  • Onboard faster - Learn once, apply everywhere
  • Review efficiently - Spot deviations from established patterns
  • Refactor confidently - Consistent structure makes changes predictable

Scalability

Patterns help the codebase scale by:

  • Isolating concerns - Each file has a single, clear responsibility
  • Enabling parallel development - Multiple developers can work on different features without conflicts
  • Supporting incremental growth - Add features without restructuring existing code
  • Facilitating testing - Clear boundaries make unit and integration tests straightforward

Maintainability

Well-defined patterns lead to:

  • Fewer bugs - Type safety and validation catch errors early
  • Easier debugging - Clear data flow and separation of concerns
  • Better documentation - Code structure is self-documenting
  • Lower technical debt - Consistent patterns prevent anti-patterns from spreading

Pattern Categories

1. Feature Modules

The 5-file pattern for organizing feature-specific code:

  • schema.ts - Zod schemas and TypeScript types
  • functions.ts - Server-side operations using Drizzle ORM
  • hooks.ts - Client-side tRPC hooks for data fetching
  • fields.tsx - Reusable form field components
  • prompts.tsx - Dialog wrappers for create/update/delete operations

Learn more about Feature Modules →

2. Error Handling

Robust error handling patterns:

  • Using CustomError with scoped error codes
  • Returning ActionResponse in tRPC procedures
  • Throwing CustomError only in helper functions
  • Translating errors for i18n
  • Toast notifications and error boundaries

Learn more about Error Handling →

3. Type Safety

Type-safe development practices:

  • Always use type instead of interface
  • Zod schemas for runtime validation and type inference
  • Apply .refine() only on final schemas (not base schemas)
  • Custom error messages via .message() instead of hardcoded strings
  • End-to-end type safety with tRPC

Learn more about Type Safety →

Core Principles

All patterns in this guide follow these principles:

  1. Type safety first - Leverage TypeScript and Zod for compile-time and runtime safety
  2. Server-first architecture - Keep sensitive logic and data on the server
  3. Separation of concerns - Each file has a single, clear responsibility
  4. Declarative over imperative - Use declarative APIs when possible
  5. Convention over configuration - Minimize boilerplate through conventions
  6. Progressive enhancement - Start simple, add complexity only when needed

Quick Reference

PatternKey FilesPrimary Use Case
Feature Modulesschema.ts, functions.ts, hooks.tsBuilding complete features with CRUD operations
Custom Errorscustom-error.ts, customErrors.jsonApplication-specific error handling
Action ResponsetRPC proceduresGraceful error handling with toast notifications
Drizzle Operationsfunctions.tsType-safe database CRUD
Form Fieldsfields.tsxReusable, styled form inputs
Prompt Dialogsprompts.tsxConfirmation dialogs with usePrompt()

Getting Started

If you're new to this codebase:

  1. Read the Feature Modules guide - Understand the 5-file pattern
  2. Study existing features - Look at src/features/api-keys as a reference
  3. Follow the templates - Use /docs/templates/new-feature for step-by-step instructions
  4. Practice type safety - Review Type Safety patterns
  5. Handle errors properly - Learn the Error Handling approach

Next Steps

Feature Modules

Learn the 5-file pattern for building features

Error Handling

Master robust error handling patterns

Type Safety

Embrace end-to-end type safety conventions

Templates

Step-by-step guides for common tasks

On this page

Introduction
Why Patterns Matter
Consistency
Scalability
Maintainability
Pattern Categories
1. Feature Modules
2. Error Handling
3. Type Safety
Core Principles
Quick Reference
Getting Started
Next Steps