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
| Tool | Version |
|---|---|
| Node.js | 22 (see .nvmrc) |
| pnpm | 9 (pinned in package.json packageManager) |
| Docker | Docker Compose v2, for PostgreSQL |
psql | On 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:
| Variable | Used by | Notes |
|---|---|---|
DATABASE_URL | API, db | Connection string for the local booking database on port 5432. Use the schema-owner role that packages/db/scripts/bootstrap-dev-db.sql creates. |
JWT_SECRET | API | Any string locally. Has a development default. |
APP_URL | API | Frontend URL used in emails. Defaults to http://localhost:3000. |
TENANT_BASE_DOMAIN | API | Base domain for tenant subdomains. Defaults to localhost. |
REDIS_ENABLED | API | false by default. Set true with REDIS_HOST / REDIS_PORT to use Redis. |
NEXT_PUBLIC_API_URL | Web | Set 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:
- creates the database roles, extensions and schema (
packages/db/scripts/bootstrap-dev-db.sql) - syncs the Prisma schema and applies the custom SQL (
pnpm migrate:dev) - 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:
| Process | Command | Port / notes |
|---|---|---|
api | pnpm dev:api | http://localhost:3001 |
web | pnpm dev:web | http://localhost:3000 |
worker | pnpm dev:worker | Hold expiry and scheduled jobs |
outbox | pnpm dev:outbox | Delivers queued emails, webhooks and events |
Two things are not started by pnpm dev:
- Slot generation: run
pnpm dev:slot-workerwhen you change schedules and need new slots. - Docs: run
pnpm dev:docsto serve this site athttp://localhost:3002.
Check it works
- Storefront:
http://localhost:3000/en. In development the web app uses thet_demotenant. - 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
| Task | Command |
|---|---|
| Typecheck API, web, worker | pnpm typecheck |
| Lint | pnpm lint |
| Check formatting | pnpm format:check |
| API unit tests | pnpm test:api:unit |
| Regenerate OpenAPI and types | pnpm contracts:regen |
| Rebuild shared packages | pnpm build:packages |
See Testing and Quality gates.
Troubleshooting
- The API cannot connect to the database. Check
docker compose psshowspostgreshealthy, and thatDATABASE_URLpoints at port 5432 and thebookingdatabase. - Prisma client errors after pulling. Run
pnpm -F @booking/db exec prisma generate. - A change in
packages/contractsis not picked up. Other workspaces import its built output. Runpnpm -F @booking/contracts build(orpnpm build:packages). - Columns or tables are missing. Run
pnpm migrate:dev. If the database is badly out of date, remove thepostgresvolume and runpnpm db:dev:bootstrapagain.