Skip to content

About

TransitMatters performance visualizer for the MBTA

Topics

Resources

Contributing

Stars

56 stars

Watchers

4 watching

Forks

Latest commit

 

History

1,239 Commits

Folders and files

Repository files navigation

TransitMatters Data Dashboard

Release lint build deploy healthcheck

This is the repository for the TransitMatters Data Dashboard. Client code is written in Typescript with React and Next.js, and the backend is written in Python with Chalice.


🧰 Requirements to Develop Locally

  • node 24.x and npm 11.x+ required
    • verify with node -v
  • Python 3.12 with recent uv (0.9.8 or later)
    • Verify with python --version && uv --version
    • uv self update to update uv
  • With mise installed, mise trust && mise install sets up Node and Python (versions are pinned in .nvmrc / .python-version)

🧪 Local Development

  1. Add MBTA_V3_API_KEY to your shell environment:
    • export MBTA_V3_API_KEY='KEY' in ~/.bashrc or ~/.zshrc
  2. In the root directory, run npm install to install all frontend and backend dependencies
  3. Run npm start to start both the JavaScript development server and the Python backend at the same time.
  4. Navigate to http://localhost:3000 (or the url provided after running npm start)

Backend Data Source

The backend supports three data source modes, controlled by the TM_BACKEND_SOURCE environment variable:

Mode Description
aws Use local AWS credentials to query DynamoDB/S3 directly (default if AWS credentials are detected)
prod Proxy requests to the production API (live data, no AWS credentials needed)
static Use cached sample data (offline development, default if no AWS credentials)

For external contributors (no AWS access): No configuration needed! The backend auto-detects missing AWS credentials and falls back to cached sample data. For live data without AWS credentials:

export TM_BACKEND_SOURCE=prod

For TransitMatters members (with AWS access):

export TM_BACKEND_SOURCE=aws

☁️ AWS Setup

If you have access to AWS credentials, add them to your local setup for a better development experience. If you don't yet have TransitMatters AWS credentials, reach out in slack.

  1. Add your AWS credentials (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY) to your shell environment, OR add them to a .boto config file with awscli command aws configure.
  2. Ensure that AWS is set to read from/to us-east-1 via export AWS_DEFAULT_REGION=us-east-1 or with an aws config

AWS access is not strictly required for development - see "Backend Data Source" above for alternatives

🚀 Deployment Instructions

  1. Configure AWS CLI 2.x with your AWS access key ID and secret under the profile name transitmatters.
  2. Configure shell environment variables for AWS ACM domain certificates.
    • TM_FRONTEND_CERT_ARN
    • TM_LABS_WILDCARD_CERT_ARN
    • (You may also need to set AWS_DEFAULT_REGION in your shell to us-east-1. Maybe not! We're not sure.)
  3. Execute ./deploy.sh (for beta) or ./deploy.sh -p (for production). If deploying from a CI platform (such as GitHub Actions) you may also want to include the -c flag.

Additional notes:

  • If you're running this locally, your local MBTA-performance API key (which might be your own) will get uploaded to AWS!
  • If you're on a platform with a non-GNU sed, deploy.sh might fail. On macOS, this is fixed by brew install gnu-sed and adding it to your PATH.
  • If you get an unexplained error, check the CloudFormation stack status in AWS Console. Good luck!

🗺️ Project Structure

pages/              # Next.js pages (routing); pages compose layouts via a `Layout` property
modules/            # Self-contained feature modules (alerts, delays, headways, slowzones, etc.)
common/
  api/              # API client and React Query hooks (common/api/hooks/)
  components/       # Shared UI components
  constants/        # Date ranges, line configurations, colors
  state/            # Zustand stores (date and station selection)
  types/            # TypeScript types (lines.ts has line and route definitions)
  utils/            # Utility functions
server/
  app.py            # Chalice API routes
  chalicelib/       # Backend modules; data sources are abstracted in data_funcs.py, s3.py, dynamo.py
  chalicelib/models.py  # Pydantic response models
  chalicelib/config.py  # Backend configuration
  openapi.json      # Generated API spec

The frontend uses Next.js, Zustand, TanStack React Query, Tailwind CSS, and Chart.js. The backend is Python on AWS Chalice, reading from DynamoDB and S3.

Other useful commands:

  • npm run get-data fetches static data for local development (runs automatically with npm start)
  • npm run storybook starts Storybook on port 6006
  • npm run generate-openapi regenerates server/openapi.json. Run it after changing API routes or models; CI fails if the committed spec is out of date.

✨ Linting, Code Style, and Tests

To lint frontend and backend code, run npm run lint in the root directory

To lint just frontend code, run npm run lint-frontend (or npm run lint-frontend-fix to auto-fix)

To lint just backend code, run npm run lint-backend (or npm run lint-backend-fix to auto-fix)

To run backend tests, run cd server && uv run pytest

Frontend code uses ESLint with Prettier, enforced import ordering, and type imports (import type { Foo }). Backend code uses Ruff with a 120 character line length.

VSCode

If you're using VSCode, .vscode contains a based default workspace setup. It also includes recommended extentions that will improve the dev experience. This config is meant to be as small as possible to enable an "out of the box" easy experience for handling eslint.

🗂️ Data Maintenance

Adding or changing a bus route

The MBTA changes bus routes every few months, usually as part of Better Bus Network. Each dashboard bus route is a station manifest in common/constants/bus_constants/. To update them:

  1. From server/bus, generate the manifest from the GTFS schedule in effect after the change: uv run python manifest.py ../../common/constants/bus_constants/<route>.json -r <route ids...> --gtfs-date <YYYY-MM-DD> --service-start <YYYY-MM-DD>. For combined pages, pass every route and keep the existing key with --name. Run check_latest_manifests.sh <YYYY-MM-DD> to diff every current manifest against the new schedule.
  2. If a route's stops changed, keep the old manifest as <route>-legacy.json with a service_end and give the new one a service_start, so the old data stays reachable.
  3. Register new keys in common/constants/stations.ts and common/types/lines.ts (BusRoute, BusRouteId, BUS_ROUTES), and add a PEAK_RIDERSHIP entry in common/constants/baselines.ts (server/scripts/update_max_ridership.py can compute it). Combined routes also need an entry in getStationForInvalidFromSelection (common/utils/stations.ts).
  4. For Better Bus Network changes, add the phase to common/constants/bnrd.ts and banner text to common/components/notices/BnrdBanner.tsx.

Updating historical backend data

GTFS archives used by the bus scripts are downloaded to data/gtfs_archives/ by default. Set GTFS_DATA_DIR to share them with other TransitMatters repos (they'll go in $GTFS_DATA_DIR/gtfs_archives).

❤️ Support TransitMatters

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.

About

TransitMatters performance visualizer for the MBTA

Topics

Resources

Contributing

Stars

56 stars

Watchers

4 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages