Community-run transit monitoring for Singapore MRT/LRT disruptions.
mrtdown-site is a TanStack Start React app deployed to Cloudflare Workers. The
app reads canonical mrtdown data through a Cloudflare D1 read model populated
from data archives.
- React 19, TanStack Start, TanStack Router, and Vite.
- Cloudflare Workers, Workflows, D1, and Wrangler.
- SQLite/D1 with Drizzle ORM and Drizzle Kit migrations.
- Biome, TypeScript, and Vitest for quality checks.
-
Install dependencies:
npm install
-
Create local environment variables:
cp .env.example .env
Keep
VITE_ROOT_URL=http://localhost:3000for local work. -
Apply local D1 migrations:
npm run db:migrate:local
-
Start the app:
npm run dev
Visit http://localhost:3000.
-
Trigger the local pull endpoint to populate the local read model when needed:
npm run dev:pull
npm run dev: start the Vite dev server.npm run build: build the app.npm run deploy: build and deploy with Wrangler.npm run typecheck: run TypeScript without emitting files.npm run lint: run Biome linting.npm run format:check: check formatting across the repository.npm run test:run: run Vitest once.npm run verify: run typecheck, lint, formatting check, migration drift check, and tests.npm run db:generate: generate Drizzle migrations after schema changes.npm run db:generate:check: verify schema changes do not require a new migration.npm run db:migrate:local: apply D1 migrations to the local Wrangler D1 database.npm run db:migrate: apply D1 migrations to a remote Wrangler environment; pass-- --env preview,-- --env staging, or-- --env production.npm run dev:pull: trigger the local pull workflow endpoint while the dev server is running.
app/routes: file-based routes, route loaders, page metadata, and API routes.app/util/*.functions.ts: TanStack server functions used by loaders and client code.app/util/db.queries.ts: DB-backed read model queries.app/db: Drizzle schema, enum helpers, and database connection setup.app/workflows/pull: Cloudflare Workflow code that stages and promotes canonical data.app/components: reusable UI and page-level components.docs: architecture, data pipeline, quality, and generated-file notes.
Canonical mrtdown archive data is fetched by the pull workflow, inserted into
*_next staging tables, promoted into normalized live tables, and read by server
functions through app/util/db.queries.ts.
The generated MRTDown API client has been retired. Server-side reads use the
DB-backed query layer, with canonical domain types coming from @mrtdown/core
where possible.
Do not hand-edit generated files unless the task is explicitly about generated output. Regenerate them through the relevant script or tool, then review the produced diff.
app/routeTree.gen.ts: generated by TanStack Router tooling.drizzle/**andmigrations/**: generated by Drizzle Kit withnpm run db:generateand mirrored for Wrangler D1 migrations.app/components/StationMap/components/Map*.tsx: mechanically converted station map snapshots.
See docs/GENERATED_FILES.md for more detail.
docs/ARCHITECTURE.md: current app architecture and deployment branch mapping.docs/DATA_PIPELINE.md: canonical data pull and read model flow.docs/QUALITY.md: verification harness and current test gaps.docs/runbooks/: operational procedures for deployments and recovery.docs/OVERHAUL_BASELINE.md: historical baseline for the read-model migration.docs/plans/README.md: conventions for checked-in execution plans.docs/plans/active/: active multi-phase work, including read-model overhaul and production performance plans.docs/investigations/: dated investigation notes that inform plans and architecture docs.
Run npm run verify before publishing changes. Use narrower commands such as
npm run typecheck, npm run lint, npm run format:check, and
npm run test:run while iterating.
Pull request titles should follow Conventional Commits, for example
feat: add station history filters or fix: handle missing fact coverage.