How to set up each app on your own machine, including the Python pipeline, a disposable database and generated assets.

Reference Value
Subject and boundary Local environments for apps/web, apps/data-proxy and apps/db. Checks to run are on ‣.
Verified source CONTRIBUTING.md, AGENTS.md, package.json, pyproject.toml, target_safety.py at main f32cd9b10a6cfa7ea87c07c979355c226e9ddbac, checked November 7, 2026.
Support state Supported on Linux and Windows for the JavaScript apps and the offline Python suite. Tests that drive Bash scripts and POSIX processes are only covered on Linux, as in CI.

Toolchain pins

Tool Pin owner Current source value
Node .nvmrc, engines.node 22.23.2 (>=22.17.0 <23)
Bun .bun-version, packageManager 1.4.4 (since #731; main 81db4fde, read 2026-11-10)
Python .python-version, requires-python 3.12 (>=3.12,<3.13)
Python packages apps/db/uv.lock via uv Locked
JavaScript packages bun.lock Frozen in CI

Read versions from these files rather than copying them elsewhere.

JavaScript workspace

bun install --frozen-lockfile
bun run setup:hooks   # pre-commit guard for generated social cards and icons
bun run dev           # web dashboard on http://localhost:5173
bun run test:changed  # fast local loop: Vitest --changed vs origin/main + impacted Playwright specs (#727)

For dependency changes, run bun install on the selected native host and commit the intended lockfile change. CI's pinned Linux bun install --frozen-lockfile decides whether it works; regenerate on Linux only if that install fails. For unchanged source, a local frozen-install failure is a setup problem and incidental lockfile changes stay out of the commit.

The web scripts regenerate TypeScript contract types from src/lib/v1/schemas/json (scripts/gen-contract.mjs) before dev, check, test and build.

Generated assets

Asset Build Check
Social cards (static/og) bun run og:build bun run og:check
Icons bun run icons:build bun run icons:check
Map posters bun run map-posters:build bun run map-posters:check

Run these from apps/web. The pre-commit hook rejects a staged generated card or icon unless its generator or input is staged too.

Python pipeline

cd apps/db
cp ../../.env.example .env
uv sync --locked
uv run transit-ops --help

Use uv-managed Python on Windows; the system Python on this host has an incomplete standard library. Do not run Docker locally on any host; service images are built on the production VM (Deployment and release). Bash and POSIX operator examples below target Linux; use native PowerShell environment assignment for Windows offline tests.

The tracked .env.example defaults to local storage (BRONZE_STORAGE_BACKEND=local, SNAPSHOT_STORAGE_BACKEND=local), so nothing is written to a remote bucket by accident. Capturing live feeds needs provider keys: STM_API_KEY and OCTRANSPO_API_KEY, plus the feed URL variables named in each provider manifest. See Providers for each feed's variables and Configuration reference for the full list.

Disposable test database

Real-database tests skip unless both variables are set. The target guard accepts only the role/database pairs transit_ci/transit_ci, postgres/transit_test and repro/transit_repro.

export TRANSIT_TEST_DATABASE_URL=postgresql+psycopg://transit_ci:[email protected]:5432/transit_ci
export TRANSIT_TEST_DATABASE_DISPOSABLE=I_UNDERSTAND_THIS_DATABASE_IS_DISPOSABLE
DATABASE_URL="$TRANSIT_TEST_DATABASE_URL" uv run alembic upgrade head
uv run pytest tests

Use a local PostgreSQL 16 with PostGIS. These tests change the database contents. Never point tests or migrations at production; a remote migration also refuses a URL loaded implicitly from .env (migration_guard.py).