Metro Now is a transit monorepo built around a NestJS backend, a Next.js web app, a background dataloader, and shared database packages. The repository uses pnpm workspaces and Turborepo for task orchestration, caching, and dependency-aware builds.
flowchart LR
subgraph Clients["Client apps"]
mobile["Mobile app<br/>iOS / watchOS"]
web["Web app<br/>landing page and map"]
end
subgraph Runtime["Runtime services"]
backend["Backend API<br/>NestJS REST + GraphQL"]
dataloader["Dataloader<br/>sync jobs and validation"]
redis["Redis<br/>response cache"]
postgres["PostgreSQL<br/>persistent transit data"]
end
subgraph Shared["Shared packages"]
database["Database package<br/>schema, migrations, seeds"]
shared["Shared library<br/>types and helpers"]
end
subgraph Sources["External data sources"]
pid["PID / GTFS feeds"]
golemio["Golemio API"]
end
mobile -->|"requests departures, stops, routes"| backend
web -->|"loads API-backed content"| backend
backend -->|"reads application data"| postgres
backend -->|"stores and reads cached responses"| redis
backend -->|"fetches selected live data"| golemio
dataloader -->|"downloads scheduled datasets"| pid
dataloader -->|"normalizes and writes snapshots"| postgres
database -.->|"defines schema for"| postgres
shared -.->|"shared code for"| backend
shared -.->|"shared code for"| dataloader
apps/
backend/ NestJS API
database/ database package, migrations, seeds
dataloader/ background sync worker
mobile/ iOS / watchOS app
web/ Next.js website
lib/
shared/ shared TypeScript package
- Node.js 20
pnpm9.1.0 via Corepack- Docker Desktop for local PostgreSQL, Redis, and container builds
- Xcode for the mobile app
Install dependencies once at the repository root:
corepack enable
pnpm install --frozen-lockfileCreate the backend local environment file:
cp apps/backend/.env.local.example apps/backend/.env.localThen update apps/backend/.env.local with your local values. For containerized runs, the repo also includes .env.docker and .env.web.docker.
Start local infrastructure only:
pnpm docker:up:devRun the main JavaScript development tasks through Turborepo:
pnpm devUseful scoped commands:
pnpm turbo run dev --filter=@metro-now/backend
pnpm turbo run start:debug --filter=@metro-now/backend
pnpm turbo run dev --filter=@metro-now/web
pnpm turbo run dev --filter=@metro-now/dataloaderOpen the Apple app in Xcode:
pnpm xcodeAll commands are run from the repository root.
pnpm build
pnpm test
pnpm lint
pnpm types:check
pnpm format:check
pnpm format
pnpm app:formatpnpm format and pnpm format:check run Biome for apps/backend, apps/dataloader, and lib/shared. pnpm app:format is the separate Swift formatting entry point for the mobile app.
Scoped commands:
pnpm turbo run build --filter=@metro-now/backend
pnpm turbo run test --filter=@metro-now/backend
pnpm turbo run test:e2e --filter=@metro-now/backend
pnpm turbo run lint --filter=@metro-now/backend
pnpm turbo run types:check --filter=@metro-now/backend
pnpm turbo run typegen --filter=@metro-now/backend
pnpm turbo run build --filter=@metro-now/web
pnpm turbo run lint --filter=@metro-now/web
pnpm turbo run types:check --filter=@metro-now/web
pnpm turbo run migrate:deploy --filter=@metro-now/database
pnpm turbo run migrate:rollback --filter=@metro-now/database
pnpm turbo run seed --filter=@metro-now/databaseStart the full stack with container builds:
pnpm docker:upStop containers and remove volumes:
pnpm docker:downThe default compose setup exposes:
- Web:
http://localhost:3000 - Backend:
http://localhost:3001 - PostgreSQL:
localhost:5532 - Redis:
localhost:6479 - Redis Stack UI:
http://localhost:8101
Turborepo is the task runner for this repository. Root scripts such as pnpm build, pnpm dev, and pnpm test resolve package dependencies automatically instead of relying on manual cd-based workflows.
Package-specific task configuration lives in:
turbo.jsonapps/backend/turbo.jsonapps/web/turbo.json
GitHub Actions uses the same root commands exposed locally:
- backend CI runs the backend Turbo tasks
- web CI runs the web Turbo tasks
- format CI runs Biome from the root
- Docker CI builds the production images from the root
Dockerfile
- The mobile app is part of the monorepo, but it is developed through Xcode rather than a Turbo
buildordevtask. - Backend GraphQL types are generated through
pnpm turbo run typegen --filter=@metro-now/backendand are also wired into the Turbo task graph for backend builds and e2e tests.
