Infrastructure
Last reviewed: 2026-05-13
Maintained by: Engineering
This repo currently uses split hosting for the web app and the API:
apps/back-office(Back Office) is deployed toVercelapps/manager-desk(Manager Desk) is deployed toVercelapps/apiis deployed toRenderPostgreSQLruns locally via Docker and uses environment-specific instances in hosted environments
Sentry is environment-configured only:
- API Sentry runtime vars live on the API host (
Renderin the current docs standard) - Manager Desk Sentry vars live in the
Vercelproject environment settings - Back Office Sentry vars live in the
Vercelproject environment settings - mobile Sentry vars live in
Expo/EASenvironment settings
Deployment Model
The branch flow is currently:
- feature branches -> merge into
main maindoes not auto-deploy anywhere- deploys to
StagingandProductionare triggered manually
GitHub Actions handles this through two workflows:
.github/workflows/ci.yml: validation onpull_requestandpush.github/workflows/deploy.yml: manual deployment promotion
What CI Actually Checks
ci.yml has the following main jobs:
1. Install, Typecheck, Lint
This confirms that the repo can:
- install dependencies with
pnpm install --frozen-lockfile - pass
pnpm run check:api - pass
pnpm run check:manager-desk - pass
pnpm run lint
This protects the repo from:
- broken
pnpm-lock.yaml - TypeScript regressions
- lint regressions
2. Build Apps
This confirms that the deployable apps still build cleanly:
pnpm run build:apipnpm run build:manager-desk
This protects the repo from:
- build-only regressions not caught by typecheck
- deploy-time packaging failures surfacing too late
3. Database Smoke Test
CI spins up a temporary PostgreSQL service and runs:
pnpm run db:migratepnpm run seed:demopnpm run db:migrate
This confirms that:
- new migrations work on an empty database
- the seed script matches the current schema
- rerunning migrations does not fail after the database is already migrated
4. Tests
This runs workspace tests through:
pnpm test
5. Migration Drift Check
This confirms committed migrations still reproduce the checked-in schema snapshot.
Deploy Flow
deploy.yml is manual-only and uses workflow_dispatch.
Staging
When you manually choose target staging:
- Manager Desk is deployed to the Vercel preview/staging target
- API is deployed to the Render staging service
- the workflow uses the GitHub Environment
Staging - the environment contract is validated before deploy steps run
Production
When you manually choose target production:
- Manager Desk is deployed to Vercel production
- API is deployed to the Render production service
- the workflow uses the GitHub Environment
Production - the environment contract is validated before deploy steps run
GitHub Environments
The repo expects two active GitHub Environments:
StagingProduction
Environment-scoped configuration matters because it allows:
- a different database connection per environment
- different JWT secrets per environment
- different
WEB_ALLOWED_ORIGINSper environment - separate Render and Vercel deployment targets
Mapping Local .env to GitHub
Local development uses root .env.example as the template.
GitHub uses the same contract, split into:
vars: non-sensitive runtime valuessecrets: sensitive values such as DB passwords, JWT secrets, and deploy tokens
Practical rule:
- if a value is safe to display in the GitHub UI, store it in
vars - otherwise store it in
secrets
Environment validation now happens during manual deploy, not on every CI push.
Required GitHub Variables
Required vars
NODE_ENVPORTDB_HOSTDB_PORTDB_NAMEDB_USERJWT_ACCESS_TTLJWT_REFRESH_TTL_DAYSWEB_ALLOWED_ORIGINSCOOKIE_SECURECOOKIE_SAME_SITECOOKIE_DOMAINoptionalSENTRY_ENABLEDoptionalSENTRY_ENVIRONMENToptionalSENTRY_RELEASEoptionalSENTRY_TRACES_SAMPLE_RATEoptionalRAILWAY_PROJECT_IDfor deploy environmentsRAILWAY_ENVIRONMENT_IDfor deploy environmentsRAILWAY_SERVICE_ID_APIfor deploy environmentsNEXT_PUBLIC_API_URLfor Manager Desk runtimeNEXT_PUBLIC_SENTRY_ENABLEDoptional for Manager Desk runtimeNEXT_PUBLIC_SENTRY_DSNoptional for Manager Desk runtimeNEXT_PUBLIC_SENTRY_ENVIRONMENToptional for Manager Desk runtimeNEXT_PUBLIC_SENTRY_RELEASEoptional for Manager Desk runtimeNEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATEoptional for Manager Desk runtimeNEXT_PUBLIC_API_URLfor Back Office runtimeNEXT_PUBLIC_SENTRY_ENABLEDoptional for Back Office runtimeNEXT_PUBLIC_SENTRY_DSNoptional for Back Office runtimeNEXT_PUBLIC_SENTRY_ENVIRONMENToptional for Back Office runtimeNEXT_PUBLIC_SENTRY_RELEASEoptional for Back Office runtimeNEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATEoptional for Back Office runtime
Required secrets
DB_PASSWORDDATABASE_URLJWT_ACCESS_SECRETJWT_REFRESH_SECRETSENTRY_DSNoptional for API runtimeVERCEL_TOKENfor deploy environmentsVERCEL_ORG_IDfor deploy environmentsVERCEL_PROJECT_ID_MANAGER_DESKfor deploy environmentsRAILWAY_TOKENfor deploy environments
Sentry Deployment Notes
- keep local Sentry disabled unless you are intentionally testing delivery
- do not hardcode DSNs, org IDs, project IDs, auth tokens, or release secrets in source
- session replay is intentionally not enabled
- source map upload is a later deployment task and is not part of the current repo wiring
Preview Strategy
The current setup intentionally uses the simplest preview model:
- Vercel-generated preview URLs for the web app
- Render-generated service URLs for the API
Custom subdomains are intentionally deferred until they become an operational requirement.
System Health Alert Retention (Manual)
System Health v1 does not introduce a dedicated scheduler for alert retention. Run manual cleanup during operations maintenance windows:
pnpm run cleanup:system-health-alerts
Default retention is 90 days. Optional override:
pnpm --filter @zgrid/api cleanup:system-health-alerts 120
Source of Truth
When you change the infrastructure setup, keep these files aligned:
- infrastructure.md
- ../99-reference/environment-contract.md
- docs home
.github/workflows/ci.yml.github/workflows/deploy.yml