Bridge Training
Setup

API Setup

Setting up the Hono BFF API server

Overview

The API (apps/api) is a Hono-based BFF (Backend For Frontend) server that sits between the app and the database. It handles authentication, business logic, and data access via Drizzle ORM.

Prerequisites

  • Node.js 24+
  • pnpm 10+
  • Local Supabase running (for Postgres) or a remote database
  • Clerk account (for authentication)

Environment Variables

Create apps/api/.env from the example:

cp apps/api/.env.example apps/api/.env
VariableRequiredDefaultDescription
PORTNo3002Server port
DATABASE_URLYesPostgreSQL connection string
SUPABASE_URLYesSupabase project URL (for auth integration)
SUPABASE_SERVICE_ROLE_KEYYesSupabase service role key
CLERK_SECRET_KEYYesClerk secret key for JWT verification
CLERK_WEBHOOK_SECRETNoClerk webhook signing secret. When not set, webhook routes are disabled.
RESEND_API_KEYNoResend API key for transactional emails
API_KEYYesAPI key for server-to-server routes (deals endpoint)

Local development values

PORT=3002
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres
SUPABASE_URL=http://127.0.0.1:54321
SUPABASE_SERVICE_ROLE_KEY=<from supabase status>
CLERK_SECRET_KEY=sk_test_<from Clerk dashboard>
API_KEY=dev-api-key

Running

# Start the API server (with hot reload)
pnpm dev:api

# Or from the api directory
cd apps/api && pnpm dev

The API runs on http://localhost:3002 with:

  • API routes at /api/*
  • OpenAPI spec at /doc
  • Swagger UI at /swagger
  • Health check at /health

Architecture

Middleware chain

Request → dependencies (db) → authMiddleware → createApi (repos with userId) → handler

All protected routes go through authMiddleware (JWT verification) then createApi (creates repositories with the authenticated user context). Every repository receives the userId for permissions and scoping.

Event bus

The API uses a domain event bus for decoupled side effects:

// Events emitted by AccountsService
"account:created" → onboarding subscriber (seeds default boards)
"account:updated" → (future subscribers)

Subscribers are registered at startup in src/index.ts.

Webhook routes

Webhook routes (/api/webhooks/*) have their own WebhookEnv context — separate from the main Api. They are only registered when CLERK_WEBHOOK_SECRET is configured.

On this page