Circle V2 API Docs
    Preparing search index...

    Introduction

    Circle V2 is a ground-up rebuild of the CircleHealth application. The legacy app is sometimes referred to as "legacy" and this codebase as "v2". The goal is a clean, maintainable codebase that follows strong conventions and makes it easy for developers to do the right thing by default.

    Layer Technology Version
    Monorepo Turborepo latest
    Package manager pnpm 10.23.0
    Language TypeScript 5.9
    Framework Next.js (App Router) 16
    UI library React 19
    Component system Chakra UI v3
    Database PostgreSQL (Supabase) --
    Schema management Drizzle ORM latest
    Query builder Kysely latest
    API layer tRPC v11
    Validation Zod 4
    Server data TanStack React Query latest
    Linting/formatting Biome latest
    Runtime Node.js >= 20

    The codebase is organized as a monorepo with two apps (web and storybook) consuming a set of shared @repo/* packages.

    %%{init:{"theme":"dark"}}%% graph TD subgraph apps [Apps] Web["apps/web (Next.js)"] Storybook["apps/storybook"] end

    subgraph packages [Packages] UI["@repo/ui"] TRPC["@repo/trpc"] Auth["@repo/auth + auth-next"] DB["@repo/db"] Services["@repo/services"] Shared["@repo/errors, safe, logger, utils"] end

    subgraph infra [Infrastructure] Supabase["Supabase (Postgres + Auth)"] end

    Web --> UI Web --> TRPC Web --> Auth Storybook --> UI

    TRPC --> Services TRPC --> DB TRPC --> Auth Services --> DB Auth --> DB DB --> Supabase

    Shared -.-> UI Shared -.-> TRPC Shared -.-> DB Shared -.-> Auth

    %%{init:{"theme":"default"}}%% graph TD subgraph apps [Apps] Web["apps/web (Next.js)"] Storybook["apps/storybook"] end

    subgraph packages [Packages] UI["@repo/ui"] TRPC["@repo/trpc"] Auth["@repo/auth + auth-next"] DB["@repo/db"] Services["@repo/services"] Shared["@repo/errors, safe, logger, utils"] end

    subgraph infra [Infrastructure] Supabase["Supabase (Postgres + Auth)"] end

    Web --> UI Web --> TRPC Web --> Auth Storybook --> UI

    TRPC --> Services TRPC --> DB TRPC --> Auth Services --> DB Auth --> DB DB --> Supabase

    Shared -.-> UI Shared -.-> TRPC Shared -.-> DB Shared -.-> Auth

    graph TD
    subgraph apps [Apps]
    Web["apps/web (Next.js)"]
    Storybook["apps/storybook"]
    end

    subgraph packages [Packages] UI["@repo/ui"] TRPC["@repo/trpc"] Auth["@repo/auth + auth-next"] DB["@repo/db"] Services["@repo/services"] Shared["@repo/errors, safe, logger, utils"] end

    subgraph infra [Infrastructure] Supabase["Supabase (Postgres + Auth)"] end

    Web --> UI Web --> TRPC Web --> Auth Storybook --> UI

    TRPC --> Services TRPC --> DB TRPC --> Auth Services --> DB Auth --> DB DB --> Supabase

    Shared -.-> UI Shared -.-> TRPC Shared -.-> DB Shared -.-> Auth

    A typical data request flows through the following layers:

    %%{init:{"theme":"dark"}}%% sequenceDiagram participant Browser participant NextApp as Next.js App Router participant TRPCRouter as tRPC Router participant Middleware as Auth Middleware participant Repo as DB Repository participant PG as PostgreSQL

    Browser->>NextApp: HTTP request NextApp->>TRPCRouter: /api/trpc/[procedure] TRPCRouter->>Middleware: authenticatedProcedure Middleware->>TRPCRouter: ctx with user TRPCRouter->>Repo: repo.method() Repo->>PG: Kysely query PG-->>Repo: rows Repo-->>TRPCRouter: Safe result TRPCRouter-->>NextApp: JSON response NextApp-->>Browser: rendered page / data

    %%{init:{"theme":"default"}}%% sequenceDiagram participant Browser participant NextApp as Next.js App Router participant TRPCRouter as tRPC Router participant Middleware as Auth Middleware participant Repo as DB Repository participant PG as PostgreSQL

    Browser->>NextApp: HTTP request NextApp->>TRPCRouter: /api/trpc/[procedure] TRPCRouter->>Middleware: authenticatedProcedure Middleware->>TRPCRouter: ctx with user TRPCRouter->>Repo: repo.method() Repo->>PG: Kysely query PG-->>Repo: rows Repo-->>TRPCRouter: Safe result TRPCRouter-->>NextApp: JSON response NextApp-->>Browser: rendered page / data

    sequenceDiagram
    participant Browser
    participant NextApp as Next.js App Router
    participant TRPCRouter as tRPC Router
    participant Middleware as Auth Middleware
    participant Repo as DB Repository
    participant PG as PostgreSQL

    Browser->>NextApp: HTTP request NextApp->>TRPCRouter: /api/trpc/[procedure] TRPCRouter->>Middleware: authenticatedProcedure Middleware->>TRPCRouter: ctx with user TRPCRouter->>Repo: repo.method() Repo->>PG: Kysely query PG-->>Repo: rows Repo-->>TRPCRouter: Safe result TRPCRouter-->>NextApp: JSON response NextApp-->>Browser: rendered page / data

    • Drizzle for schema, Kysely for queries: Drizzle manages the schema and migrations. Kysely is the runtime query builder, giving full control over SQL with type safety.
    • Repository pattern: All database access goes through repos in @repo/db, which return Safe<T> results instead of throwing.
    • Safe<T> over try/catch: A Go-inspired result type used throughout the stack for explicit error handling.
    • @repo/* packages: All shared code lives in monorepo packages, consumed by apps via the @repo/ scope.
    • Server-side auth in layouts: Authentication is enforced at the Next.js layout level, not via Edge middleware.

    Next: Getting Started