A practical walkthrough for taking this starter kit, running it, and extending it with the help of modern AI development tools.
The WMATA API is free — you just need to register.
- Go to https://developer.wmata.com and click Sign up
- Confirm your email and sign in
- Go to Products → Default Tier → click Subscribe Without this step, your key returns HTTP 401 on every call.
- Go to Profile (top-right). You'll see two keys: Primary and Secondary. Either works.
- Copy the Primary key.
The free tier limits: 10 calls/sec and 50,000 calls/day — plenty for development and class demos.
# From the project root
cp .env.example .env
# Open .env in any editor and paste your key after the equals sign:
# WMATA_API_KEY=abc123def456...The .env file is gitignored — it will never be committed to your repo. Check this with git status after editing — .env should not appear.
🚨 If you ever accidentally commit a key, regenerate it on the WMATA portal immediately. Both keys (Primary and Secondary) can be rotated.
uv sync # install deps (first time only)
.venv/bin/streamlit run app/dashboard.py # launch the dashboardThe app opens at http://localhost:8501. Pick a station from the left sidebar — try Metro Center (busiest), Friendship Heights (Red Line, near AU), or Pentagon City.
To run the test suite:
.venv/bin/python tests/run_tests.pyYou should see 35/35 passed. If anything fails, the test output will tell you what's wrong (most often: stale fixture IDs, since WMATA occasionally renames bus routes).
Modern AI coding assistants are excellent partners for extending this codebase. Here's how to get the most out of each.
This repo includes Claude skills in .claude/skills/. After installing Claude Code (https://claude.com/code), cd into the project directory and start a session:
cd "WMATA Open Data Demo Apps"
claudeThen try:
/wmata-add-endpoint— guides you through adding a new WMATA API endpoint towmata/client.pywith a matching L1 test/wmata-add-feature— walks through adding a new dashboard feature (chart, panel, metric)/wmata-deploy— interactive deployment walkthrough
Tips:
- The skills are loaded automatically because they live in
.claude/skills/at the repo root. - Use
/initonce at the start to let Claude index the codebase. - Ask things like "add a tab showing on-time performance per line over the last hour" — Claude reads the existing tabs and follows the same pattern.
The Codex CLI (https://github.com/openai/codex) works on the same agentic principle as Claude Code. From the project root:
codexPre-flight tips:
- Drop a short note in
AGENTS.mdat the repo root summarizing the architecture (Codex reads it on startup, similar to how Claude readsCLAUDE.md). The README is a fine source to summarize from. - For the web ChatGPT, you can attach the repo as a ZIP, or paste the most relevant files (
wmata/client.py,app/dashboard.py, the test runner) into the conversation. - Codex tends to be more verbose — ask it for "minimal diff" when you want a small change.
For inline suggestions and chat in VS Code / JetBrains:
- Install the GitHub Copilot and Copilot Chat extensions
- Open the project folder in your IDE — Copilot indexes it automatically
- Use
@workspacein chat to give it project-wide context: "@workspace add a metric showing average wait time across all stations"
Tips:
- Copilot is strongest on inline completion as you type — start writing the function signature and let it draft the body.
- Use Copilot Chat for refactors and explanations of unfamiliar code (
/explainselected code). - It does not run code or browsers — pair it with a terminal you keep open for
streamlit runandpython tests/run_tests.py.
Perplexity's Computer lets an AI agent operate inside your browser tabs.
For this project:
- Use Perplexity Computer to research WMATA data quirks ("does WMATA publish historical GTFS archives?") and have it summarize with sources.
- Open the running dashboard in a Perplexity Computer tab and ask "explain what this dashboard is showing me" for a sanity-check before sharing with classmates.
- Perplexity Computer is not a code editor — you'll still write code in your IDE / Claude Code / Codex. Think of it as a research-and-validation companion.
| If you want to... | Best tool |
|---|---|
| Plan a multi-step extension and have it implemented | Claude Code or Codex CLI |
| Get inline autocomplete while typing | GitHub Copilot |
| Explore unfamiliar code | Copilot Chat or Claude Code |
| Research transit data, GTFS spec, BI patterns | Perplexity Computer (sources cited) |
| Pair-program a tricky algorithm | Claude Code (deeper reasoning) |
The biggest leverage comes from treating these tools as collaborators that read the same code and docs you do. Keep the README and lessons_learned.md accurate — those become the agent's onboarding material.
# wmata/client.py
def get_train_positions(api_key: str) -> list[dict]:
"""Live positions of every train currently in service."""
data = _get(api_key, "/TrainPositions/TrainPositions",
params={"contentType": "json"})
return data.get("TrainPositions", []) if data else []Then add a test in tests/run_tests.py and re-export from wmata/__init__.py.
The pattern in app/dashboard.py is clear: each tab is its own block under with tab_X:. Copy the System tab as a template and replace the contents.
Write a small script that polls every minute:
import time, sqlite3, os
from wmata import get_predictions
while True:
rows = get_predictions(os.environ["WMATA_API_KEY"], "A01")
# ... write to SQLite or DuckDB
time.sleep(60)Then build a "headway analysis" tab against your historical table.
- API issues — check
Research/wmata_api_overview.mdfor known quirks (the railMinfield is a string, weekends breakjRouteDetails, etc.) - License questions —
Research/wmata_license_compliance.mdhas the full breakdown - What was tried before —
lessons_learned.mddocuments dead-ends and decisions session by session - Test failures — fixtures may have aged; the test runner prints the exact failing assertion
Welcome to the kit. Build something interesting.