Skip to main content

Architecture Overview

Route Groups

The app is organized into four route groups under src/app/:

Route GroupPurpose
(app)/Main user-facing app — wrapped in session, Google Maps, tRPC, search, and location providers
admin/Admin dashboard — separate layout, role-guarded
studio/Sanity Studio — embedded CMS
api/API routes — tRPC HTTP handler, NextAuth handlers, Sanity draft mode

Data Layer

Database Schema

Schema files live in src/db/schema/:

  • auth-schema.ts — users, accounts, sessions (NextAuth tables)
  • core-schema.ts — places, reviews, photos, types, self-reported reviews, promoted/verified places
  • relations.ts — Drizzle relation definitions
  • views.ts — materialized views (e.g., placeSummary)

The DB client is a singleton in src/db/index.ts, cached in development to prevent connection exhaustion.

Migrations are generated by drizzle-kit and stored in src/db/migrations/.

tRPC Structure

tRPC provides type-safe API calls between client and server:

  • Router definition: src/lib/api/server/index.ts — merges sub-routers: place, category, user, role, analytics, geolocation
  • Procedures: src/lib/api/server/trpc.ts — defines access levels:
    • publicProcedure — no auth required
    • privateProcedure — requires authenticated session
    • adminProcedure — requires ADMIN or SUPERADMIN role
    • superadminProcedure — requires SUPERADMIN role
  • Client hook: src/lib/api/client.ts — exports api (tRPC React Query hooks)
  • Provider: src/lib/api/provider.tsx — wraps the app with tRPC + React Query

Server Actions

Mutations are handled through Next.js server actions, colocated with their pages in _actions.ts files:

  • src/app/(app)/(auth)/login/_actions.ts — Google sign-in, Resend magic link
  • src/app/(app)/(auth)/onboarding/_actions.ts — user onboarding
  • src/app/(app)/map/place/[id]/_actions.ts — post review, fetch reviews/photos
  • src/app/(app)/profile/_actions.ts — profile reviews, delete/update review
  • src/app/(app)/profile/edit/_actions.ts — update profile, delete account
  • src/app/admin/submit/_actions.ts — self-report venue submission

Authentication

Auth is handled by NextAuth v5 (beta), configured in src/lib/auth.ts:

  • Providers: Google OAuth + Resend (magic link email)
  • Adapter: Drizzle adapter connecting to PostgreSQL
  • Session strategy: JWT with role injection in the JWT callback

Roles

Three roles defined in src/lib/roleUtils.ts:

RoleAccess
USERDefault role, can leave reviews
ADMINAccess to admin dashboard
SUPERADMINFull access including user management

Guard components live in src/components/auth/ for both client and server-side protection.

Key Conventions

  • Server actions live in _actions.ts files colocated with their page
  • Form schemas (Zod) live in _form-schema.ts files colocated with their page
  • UI components: Customized shadcn/ui in src/components/ui/ — CSS variables define the theme (primary = dark green, secondary = light yellow). New shadcn imports need manual styling adjustments per the Figma design.
  • Path alias: @/ maps to src/
  • SVG imports: Handled as React components via @svgr/webpack