- Node.js 22 or later
- npm
- Docker Desktop or another Docker Compose-compatible runtime
- Git
- Azure CLI only for optional keyless Azure OpenAI testing
cp .env.example .env
npm ci
docker compose up -d
npm run db:generate
npm run db:migrate:deploy
npm run db:seed:all
npm run devOpen:
- application: http://localhost:3000
- MailHog: http://localhost:8025
Run the queue worker in another terminal:
npm run worker| Service | Image | Port | Purpose |
|---|---|---|---|
| PostgreSQL | postgres:16-alpine |
5432 | Application and policy data |
| Redis | redis:7-alpine |
6379 | BullMQ queues |
| Azurite | Microsoft Azurite | 10000-10002 | Blob, queue, and table emulation |
| MailHog | mailhog/mailhog |
1025, 8025 | SMTP capture and browser viewer |
The application currently logs placeholder notification behavior from the worker; MailHog is present for implementing and testing SMTP integration.
.env is ignored and must never be committed. Change at least:
NEXTAUTH_SECRET=<random-local-secret>
AUTH_ENABLE_DEMO_CREDENTIALS=true
DEMO_PASSWORD=<local-demo-password>Generate a session secret with:
openssl rand -base64 32The checked-in .env.example contains only local sample values.
Run all synthetic seeds:
npm run db:seed:allOr run them separately:
npm run db:seed
npm run db:seed:policy
npm run db:seed:permits
npm run db:seed:demoThe seeds are designed to be repeatable. They create fictional Contoso users, teams, modules, policy sections, and applications.
| Role | |
|---|---|
| Applicant | applicant@example.com |
| Reviewer | reviewer@example.com |
| Manager | manager@example.com |
| Administrator | admin@example.com |
All seeded users use DEMO_PASSWORD. Never use the local default in a shared environment.
AUTH_ENABLE_DEMO_CREDENTIALS is the server-side switch for password sign-in and local registration. NEXT_PUBLIC_DEMO_MODE only controls sample guidance. Set the server switch to false when testing the production identity surface.
Add the External ID and workforce ENTRA_* variables from .env.example to enable either OIDC provider locally. Each provider is all-or-nothing; partial configuration stops startup. Register the exact localhost callback URIs and follow Identity for user-flow and app-role setup.
After editing prisma/schema.prisma:
npm run db:migrate -- --name concise_change_name
npm run db:generate
npm run typecheckCommit both the schema change and generated migration SQL. Review destructive statements before applying them to data-bearing environments.
Reset local data only when it is safe to discard it:
npm run db:resetInspect local data with:
npm run db:studioThe generated licence uses a synthetic DOCX template. Regenerate it after changing scripts/generate-licence-template.mjs:
npm run templates:generateCommit both the generator and public/templates/private-hire-driver-licence.docx. Keep real authority letterheads, signatures, addresses, or licence-holder data out of this public repository.
The local app can call Azure OpenAI keylessly through your Azure CLI identity.
-
Sign in:
az login
-
Ensure your user has Cognitive Services OpenAI User on the target account.
-
Set:
AZURE_OPENAI_ENDPOINT=https://<resource>.openai.azure.com/ AZURE_OPENAI_DEPLOYMENT=gpt-4.1-mini AZURE_OPENAI_API_VERSION=2024-10-21
-
Seed the policy and start the app.
Leave OPENAI_API_KEY unset for the Azure keyless path. AI UI degrades gracefully when no endpoint is configured.
The scripts scripts/test-ai.ts and scripts/test-complex.ts call a configured Azure OpenAI deployment and can incur cost. Use only synthetic inputs.
Run before a pull request:
npm run lint
npm run typecheck
npm test
NODE_ENV=production npm run build
npm audit --audit-level=lowThe production build requires a reachable database only for routes that query at request time; build-time generation must not depend on local Azure resources.
docker build -t digital-permit-web:local .
docker build -f Dockerfile.worker -t digital-permit-worker:local .Both final images run as UID 1001. The web image exposes port 3000 and includes a liveness health check.
docker compose downDelete local volumes and all local data only when intended:
docker compose down -vSee Troubleshooting. Common causes are occupied ports, stale Docker volumes after schema changes, missing Prisma generation, a weak/missing NEXTAUTH_SECRET, or Azure CLI identity not authorised for Azure OpenAI.