Use the root scripts instead of starting each service in a separate terminal.
- PostgreSQL is already running locally and reachable with the values in
api/.env.local - Install dependencies once in the root,
api,dashboard, andnetwork-surveypackages - Create local env files from the checked-in examples if they do not already exist
npm run dev: validates env files, verifies Postgres is reachable, starts the API first, waits for API readiness, then starts the dashboard and survey appnpm run dev:stop: stops all services started bynpm run devnpm run db:setup: ensures localONAdatabase exists, then runs Liquibase migrations fromdb/changelogs/master-changelog.xmlnpm run db:migrate: runs Liquibase migrations only (does not create the database)npm run dev:setup: runsdb:setupand then starts local developmentnpm run dev:api: runs the API by itselfnpm run dev:dashboard: runs the dashboard by itselfnpm run dev:survey: runs the survey app by itself
api/.env.local.exampledashboard/.env.development.examplenetwork-survey/.env.development.example
The API runner treats RESEND_API_KEY or RESEND_KEY as optional for startup. Email-sending features will fail at runtime if neither key is configured.
Public dashboard self-signup is controlled by ALLOW_PUBLIC_SIGNUP. It defaults to enabled only in local/dev/test when unset; set ALLOW_PUBLIC_SIGNUP=false for staging/production unless public account creation is explicitly desired. AUTH_RATE_LIMIT_MAX and RESPONDENT_RATE_LIMIT_MAX can tune API throttling for login/register and respondent-token endpoints.
db:setupreads DB credentials fromapi/.env.local- The script requires Liquibase CLI on your
PATH - A generated Liquibase defaults file is created at
db/.liquibase.local.generated.propertiesduring setup db:setupalso ensures a bootstrap local admin account inusersso login is available immediately; when IAM tables are present it marks the account active/platform-admin and owner ofdefault-imported- Default bootstrap credentials are
admin/admin123 - Override bootstrap credentials with
LOCAL_ADMIN_USERNAMEandLOCAL_ADMIN_PASSWORDinapi/.env.local db:setupis local-only and refuses to run whenDB_HOSTis not local orNODE_ENVis non-local- For staging/production, migrations run automatically on the EC2 instance during deploys (see
.github/workflows/deploy.ymlandscripts/deploy/remote-deploy.sh) — the databases are not reachable from outside the VPC - Staging deploys also ensure the configured bootstrap dashboard administrator exists; setup requirements and recovery behavior are documented in
terraform/README.md - For intentional non-local one-off execution, pass
--allow-nonlocal(or setALLOW_NON_LOCAL_DB_SETUP=trueinapi/.env.local)
CIworkflow (every PR and push tomain): builds and tests both frontends, and runs an API integration smoke test against a migrated Postgres 15 service container (scripts/ci/api-smoke.sh).Deployworkflow: pushes tomaindeploy to staging automatically; production deploys are triggered manually from the Actions tab. Frontends are synced to S3 + CloudFront invalidated; the API is packaged as a tarball in S3 and installed on the EC2 instance via SSM (scripts/deploy/remote-deploy.sh) with a pm2 reload — instances are never rebuilt for a deploy. The workflow now performs external smoke checks after deploy.Redeploy API Artifactworkflow: manually redeploys a previously published API artifact SHA through SSM and can mark it aslatestafter the external API smoke check passes. This is an artifact redeploy, not a database/schema rollback.- Infrastructure (environments, IAM/OIDC for CI, setup steps) is documented in terraform/README.md. Runtime API secrets are stored in SSM Parameter Store SecureString values. Cleanup and hardening work is tracked in plans/infra-hardening-production-readiness-plan.md.
- API:
3000 - Dashboard:
3001 - Survey:
3002
The local runner verifies that the dashboard and survey point at the same API origin and that the API CORS origins match the local frontend URLs.