A live map that tracks the MBTA Pride bus (#1843) as it travels around the network during Pride season. A React + Vite frontend renders the map and route; a Python Chalice app proxies the MBTA V3 API.
- Frontend: React, TypeScript, Vite, Leaflet, Tailwind CSS
- Backend: Python 3.12, AWS Chalice (Lambda + API Gateway)
- Tooling: uv (Python), npm (Node), Ruff (lint + format), ESLint + Prettier, pre-commit
src/ # React frontend (map, layers, and API hooks in api.ts)
server/app.py # Chalice app that proxies the MBTA V3 API; the bus ID (y1843) is set here
server/cloudformation.json # S3 bucket and CloudFront distribution for the frontend
deploy.sh # Builds and deploys the whole stack
- Node 24.x and npm 11+
- With mise installed:
mise trust && mise install(pinned in.nvmrc/.python-version) - Verify with
node -v
- With mise installed:
- Python 3.12 via uv
- Install uv:
curl -LsSf https://astral.sh/uv/install.sh | sh(orbrew install uv) - Verify with
uv --version - uv installs and manages the pinned Python 3.12 toolchain automatically — you do not need to install Python yourself.
- Install uv:
mise install # select Node 24 and Python 3.12
npm install # installs Node deps; `postinstall` runs `uv sync` for Python depsnpm install runs uv sync automatically, which creates the .venv and
installs the Python dependencies from uv.lock. To install Python deps on their
own, run uv sync.
(Optional but recommended) enable the git hooks so linting/formatting run on every commit:
uv run pre-commit installnpm startThis runs the Vite dev server and the Chalice backend (chalice local)
concurrently. The backend requires an MBTA V3 API key in the MBTA_V3_API_KEY
environment variable; without it, every API request returns a 500. You can get a
free key from the MBTA V3 API portal.
Python is linted and formatted with Ruff; the frontend uses ESLint and Prettier.
npm run lint # lint frontend + backend
npm run lint-frontend # ESLint
npm run lint-backend # Ruff check + Ruff format --check
npm run format-backend # Ruff autofix + format (writes changes)The same Python checks (plus a uv.lock consistency check) run via pre-commit
and in CI.
Deploys happen automatically from main via GitHub Actions. To deploy manually
you need the AWS credentials and secrets referenced in deploy.sh, then:
bash deploy.shThis builds the frontend, packages the Chalice backend (exporting
requirements.txt from uv.lock), deploys the CloudFormation stack, and syncs
the static site to S3 + invalidates CloudFront.
If you've found this app helpful or interesting, please consider donating to TransitMatters to help support our mission to provide data-driven advocacy for a more reliable, sustainable, and equitable transit system in Metropolitan Boston.