Skip to main content

Developer setup

This page gets the monorepo running on your machine: the API, the web app, the workers and a local database with demo data.

Prerequisites​

ToolVersion
Node.js22 (see .nvmrc)
pnpm9 (pinned in package.json packageManager)
DockerDocker Compose v2, for PostgreSQL
psqlOn your PATH; the database scripts use it

Install​

pnpm install

The install also generates the Prisma client and builds the shared observability package.

Environment​

Create a .env file in the repository root. The API, the web dev server, the workers and the database scripts all read it. The variables you need for local development:

VariableUsed byNotes
DATABASE_URLAPI, dbConnection string for the local booking database on port 5432. Use the schema-owner role that packages/db/scripts/bootstrap-dev-db.sql creates.
JWT_SECRETAPIAny string locally. Has a development default.
APP_URLAPIFrontend URL used in emails. Defaults to http://localhost:3000.
TENANT_BASE_DOMAINAPIBase domain for tenant subdomains. Defaults to localhost.
REDIS_ENABLEDAPIfalse by default. Set true with REDIS_HOST / REDIS_PORT to use Redis.
NEXT_PUBLIC_API_URLWebSet to http://localhost:3001 by pnpm dev.

Optional provider settings, only needed when you work on those features:

  • Payments: STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, PAYTRAIL_MERCHANT_ID, PAYTRAIL_SECRET_KEY.
  • Email: BREVO_API_KEY, BREVO_SENDER_EMAIL, BREVO_SENDER_NAME.
  • Error reporting: SENTRY_DSN.

The full list, with defaults, is in apps/api/src/common/config/env.schema.ts. Never commit .env.

Database​

Start PostgreSQL, then bootstrap the dev database:

docker compose up -d postgres
pnpm db:dev:bootstrap

pnpm db:dev:bootstrap takes a fresh database volume to a working dev database in one command. It is idempotent, so you can re-run it any time. It:

  1. creates the database roles, extensions and schema (packages/db/scripts/bootstrap-dev-db.sql)
  2. syncs the Prisma schema and applies the custom SQL (pnpm migrate:dev)
  3. loads the demo data (packages/db/seeds/seed_demo.sql) and the role and permission reference data

The demo data is tenant t_demo with site s_demo and product p_demo, plus a demo admin user. The script prints the admin login when it finishes.

After you change packages/db/prisma/schema.prisma, run pnpm migrate:dev again. See Database.

Run the stack​

pnpm dev

pnpm dev starts four processes side by side:

ProcessCommandPort / notes
apipnpm dev:apihttp://localhost:3001
webpnpm dev:webhttp://localhost:3000
workerpnpm dev:workerHold expiry and scheduled jobs
outboxpnpm dev:outboxDelivers queued emails, webhooks and events

Two things are not started by pnpm dev:

  • Slot generation: run pnpm dev:slot-worker when you change schedules and need new slots.
  • Docs: run pnpm dev:docs to serve this site at http://localhost:3002.

Check it works​

  • Storefront: http://localhost:3000/en. In development the web app uses the t_demo tenant.
  • Admin: http://localhost:3000/en/admin. Sign in with the demo admin.
  • API docs (Swagger UI): http://localhost:3001/api-docs. See Contracts.
  • API calls from the command line need the tenant header, for example curl -H 'x-tenant-id: t_demo' 'http://localhost:3001/api/v1/availability/sites'.

Everyday commands​

TaskCommand
Typecheck API, web, workerpnpm typecheck
Lintpnpm lint
Check formattingpnpm format:check
API unit testspnpm test:api:unit
Regenerate OpenAPI and typespnpm contracts:regen
Rebuild shared packagespnpm build:packages

See Testing and Quality gates.

Troubleshooting​

  • The API cannot connect to the database. Check docker compose ps shows postgres healthy, and that DATABASE_URL points at port 5432 and the booking database.
  • Prisma client errors after pulling. Run pnpm -F @booking/db exec prisma generate.
  • A change in packages/contracts is not picked up. Other workspaces import its built output. Run pnpm -F @booking/contracts build (or pnpm build:packages).
  • Columns or tables are missing. Run pnpm migrate:dev. If the database is badly out of date, remove the postgres volume and run pnpm db:dev:bootstrap again.