Architecture
Folder Structure
Kit is a Turborepo monorepo with clear separation between applications and shared packages. Apps consume packages; packages never depend on apps.
Overview
kit/
├── apps/
│ ├── web/ # Next.js 16 web app
│ ├── mobile/ # Expo mobile app
│ ├── extension/ # Chrome extension (WXT)
│ └── desktop/ # Electron desktop app
├── packages/
│ ├── api/ # tRPC router + better-auth
│ ├── db/ # Drizzle schema + Supabase config
│ └── ui/ # Shared React components
├── scripts/ # bootstrap.ts (starter trimming)
├── package.json # Root workspace scripts
├── turbo.json # Turborepo pipeline + env
└── pnpm-workspace.yaml # Workspaces + version catalogApplications (apps/)
Web App (apps/web/)
Next.js 16 with the App Router:
apps/web/
├── content/
│ └── docs/ # These docs (fumadocs MDX)
├── src/
│ ├── app/
│ │ ├── (auth)/ # Login, register, password reset
│ │ ├── (dashboard)/ # Protected dashboard
│ │ │ └── dashboard/
│ │ │ ├── [slug]/ # Org pages: todos, members, settings, billing
│ │ │ └── account/ # User account settings
│ │ ├── (docs)/ # Docs routes (fumadocs)
│ │ ├── (marketing)/ # Public landing page
│ │ └── api/
│ │ ├── auth/[...all]/ # better-auth handler
│ │ ├── trpc/[trpc]/ # tRPC endpoint
│ │ ├── chat/ # AI chat endpoint
│ │ ├── health/ # Liveness check
│ │ └── search/ # Docs search
│ ├── components/ # App-level components (header, nav, theme)
│ ├── lib/ # auth-client, site-config, fumadocs source
│ ├── trpc/ # tRPC client setup (react, server, query-client)
│ └── proxy.ts # Markdown content negotiation for agents
├── next.config.js
└── package.jsonRoute Conventions
(auth)/,(dashboard)/,(marketing)/,(docs)/- route groups[slug]/- dynamic org routes_components/- colocated components, not routes
Mobile App (apps/mobile/)
Expo + React Native with NativeWind:
apps/mobile/
├── src/
│ ├── app/ # Expo Router (_layout.tsx, index.tsx)
│ ├── utils/ # auth (SecureStore), api (tRPC), base-url
│ └── styles.css
├── app.config.ts
└── package.jsonChrome Extension (apps/extension/)
Built with WXT:
apps/extension/
├── src/
│ ├── entrypoints/ # background, popup, options
│ ├── assets/
│ └── lib/
└── wxt.config.tsDesktop App (apps/desktop/)
Electron via electron-vite:
apps/desktop/
├── src/
│ ├── main/ # Main process
│ ├── preload/ # Preload scripts
│ └── renderer/ # UI
├── electron.vite.config.ts
└── electron-builder.ymlShared Packages (packages/)
API Package (packages/api/)
tRPC router and better-auth config:
packages/api/src/
├── auth/ # auth.ts (better-auth), auth-schema.ts, utils
├── organization/ # organization-router.ts, -schema.ts, -test
├── todo/ # Example CRUD router
├── waitlist/ # Waitlist router
├── root-router.ts # Router composition
├── trpc.ts # Context + procedures
├── test-utils.ts # Vitest helpers
└── index.ts # Exports: appRouter, RouterInputs/OutputsConvention per feature: *-router.ts (procedures), *-schema.ts (Zod), *.test.ts (tests).
Database Package (packages/db/)
packages/db/
├── src/
│ ├── drizzle-schema.ts # App tables (waitlist, todo)
│ ├── drizzle-schema-auth.ts # better-auth generated tables
│ ├── drizzle-client.ts # postgres.js + Drizzle client
│ └── index.ts # Re-exports drizzle-orm operators
├── supabase/
│ └── config.toml # Local Supabase (auth + data API off, storage on)
├── drizzle.config.ts
└── package.json # db scripts (start, push, reset, studio)UI Package (packages/ui/)
shadcn-style components on Base UI (base-vega registry):
packages/ui/
├── src/
│ ├── components/ # Flat primitives + ai-elements/
│ ├── hooks/
│ ├── lib/utils.ts # cn()
│ └── styles/globals.css
├── components.json # shadcn config (style: base-vega)
└── postcss.config.mjsApps import explicit paths:
@repo/ui/components/<name>@repo/ui/lib/utils@repo/ui/globals.css
Add components from the registry:
cd packages/ui && pnpm dlx shadcn@latest add <component>Documentation
No separate docs package - these pages are MDX files in apps/web/content/docs/, rendered by fumadocs (apps/web/src/lib/source.ts).
Configuration Files
package.json- Workspace scripts (dev:web,db:push, ...)turbo.json- Pipeline +globalEnvallow-list for env varspnpm-workspace.yaml- Workspaces and the shared version catalog.oxlintrc.json- Linting (oxlint); formatting is oxfmt
Key Design Principles
- Separation of concerns - Apps own UX; packages own logic, data, and primitives
- Code sharing - One tRPC router, one auth config, one schema for every platform
- Type safety - Types flow from schema through API to UI, no codegen
- Explicit imports -
@repo/ui/components/button, not barrel files
Adding New Features
New API Routes
- Add
packages/api/src/<feature>/with router + schema - Register in
packages/api/src/root-router.ts - Consume with full types via
useTRPC()
New UI Components
- Add to
packages/ui/src/components/(orpnpm dlx shadcn@latest add) - Import as
@repo/ui/components/<name>
New Database Tables
- Define in
packages/db/src/drizzle-schema.tswith.enableRLS() - Run
pnpm db:push - Types flow everywhere automatically