GitHub - UtpalJayNadiger/wheres-my-muni: Live map of every Muni, BART & Caltrain in SF, with a from→to planner · GitHub
/" data-turbo-transient="true" />
Skip to content
Search/
Sign in<br>Sign upAppearance settings
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
UtpalJayNadiger
wheres-my-muni
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
main
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>3 Commits<br>3 Commits
public
public
scripts
scripts
.env.example
.env.example
.gitignore
.gitignore
Dockerfile
Dockerfile
LICENSE
LICENSE
README.md
README.md
package-lock.json
package-lock.json
package.json
package.json
server.js
server.js
View all files
Repository files navigation
Where's my Muni? 🚋
Every Muni bus and train, BART train and Caltrain in San Francisco on one live map. Type where you are and where you're going; it highlights the lines that connect them and rings the exact vehicles heading your way.
Run it in 2 minutes
git clone https://github.com/UtpalJayNadiger/wheres-my-muni && cd wheres-my-muni<br>npm install<br>cp .env.example .env # paste your free 511 token (link below)<br>npm start # → http://localhost:3000
Get a free 511.org token here (instant, emailed): https://511.org/open-data/token. Without it you still get BART; Muni and Caltrain need the token.
Or with Docker: docker build -t wheres-my-muni . && docker run -p 3000:3000 -e FIVE11_API_KEY=... wheres-my-muni
How it works
One Node process, no database. It polls 511.org's regional GTFS-Realtime vehicle positions feed once every 65s (511 caps a token at 60 requests/hour , so never fetch per-user or per-region), keeps the snapshot in memory and serves it to every browser from /api/vehicles.
Muni + Caltrain positions are real. Between polls the browser dead-reckons each vehicle along its route line at its last reported speed, then eases onto the real position when the next poll lands.
BART publishes no vehicle positions, so the server places trains on the line from BART's real-time arrival estimates for every station (every 30s) using scheduled segment times. Labeled "estimated" in the UI; the planner uses BART's real minutes when you board at a BART station.
Planner : nearest stops within a short walk of both points → direct lines (and one-transfer options only when they're clearly faster), ETAs from vehicle position + schedule.
Map: MapLibre GL + OpenFreeMap dark tiles (no key). Geocoding: Photon + local stop names.
Run
npm install<br>cp .env.example .env # paste your 511 token<br>npm start # http://localhost:3000
The server is one Node process, no database. It polls 511 every 65s (511 allows 60 req/hour/token) and BART every 30s, keeps the latest snapshot in memory and serves it to everyone from /api/vehicles. Don't run more than one instance per 511 token.
Refresh the schedule data
public/data/network.json is built from static GTFS (routes, stops, one representative shape per direction, scheduled travel times). Rebuild when agencies change schedules (a few times a year):
npm run fetch:gtfs # uses 3 of your hourly 511 requests, then rebuilds network.json
Deploy
Anything that runs one long-lived Node process: Fly, Railway, Render, a $4 VPS, a Raspberry Pi. Use the Dockerfile or npm start, set FIVE11_API_KEY. Serverless/multi-region setups will blow through the 511 rate limit; don't.
URL params
/?q=Dolores%20Park|Ferry%20Building — free-text from|to
/?from=37.7596,-122.4269,Dolores%20Park&to=37.7955,-122.3937,Ferry%20Building — pinned coordinates (what the Share button produces)
API
GET /api/vehicles — { feedTs, vehicles: [{ id, agency, route, dir, lat, lon, bearing, speed, ts, ... }] }
GET /api/bart — per-station real-time departures
GET /api/health
License
MIT
About<br>Live map of every Muni, BART & Caltrain in SF, with a from→to planner<br>Resources<br>Readme<br>MIT license<br>Activity<br>Stars<br>0 stars<br>Watchers<br>0 watching<br>Forks<br>0 forks<br>Report repository
Releases
Packages
Contributors
Languages
You can’t perform that action at this time.