New
Apps 1,895Makers 1,890This week 1,690
Promote your app−30%
2views in
the last 30 days

Toronto Transit Reach

Isochrone reach map and time-dependent trip planner for Toronto

Built with Claude Code

by luke-zhang-cs-py · Unclaimed · from USUnited States · added Oct 29, 2026
no ratings0 comments

Toronto Transit Reach

How far can you get from any point in Toronto in 30 minutes? Click the map and find out — plus how to make a specific trip, and what time you'd actually arrive.

▶ Try it now — runs in your browser, nothing to install

Dragging the time filter from 5 to 60 minutes: the reach spreads from a single stop to 247 of them, 30 km out

Above: the reach window widening from 5 to 60 minutes. Every stop is shaded by how long it takes to get there — computed live, in the page.

Read the full write-up → — where each number comes from, the graph it searches, and every bug this has had. (Or open docs/index.html locally.)

Run it

pip install -r requirements.txt
python app.py                      # http://127.0.0.1:5000
python tools/build_schedule.py     # optional: adds timetabled departures

Four years ahead, labelled as a projection. TTC publishes one board period at a time, six to eight weeks ahead. build_schedule.py therefore also runs tools/project_schedule.py, which repeats the latest published week with no holiday in it for four years past the feed's last date. Ontario's statutory holidays and Civic Holiday go on the feed's own holiday service, and a weekend holiday is also observed on the next free weekday. Projected dates are kept apart from published ones (projected in the index), and a wait read from them is labelled projected timetable, never "timetabled". Board-period changes and summer service are not known in advance, so a projected wait can be wrong by however much those change. Rebuilding after TTC's next release replaces projected dates with published ones. python tools/project_schedule.py --years N redoes only the projection.

No API key, no billing account. OpenStreetMap tiles in the browser; every travel time is computed locally against TTC's own open timetable and live feed.

How it runs with no server

The live demo above is docs/app/ — the same page with the server taken out. The graph is small enough (97 KB) to inline into the page, and the reachability search is a port of trips/routing.py's Dijkstra that runs in JavaScript. It's generated, not hand-forked:

python tools/build_static.py

The build refuses to write if the JS port and the Python disagree at any of the 516 stops. Two things it deliberately doesn't do: waits are modelled rather than measured, since GTFS-realtime needs a backend to fetch it, and there's no trip planner — an approximated arrival time is worse than none. Run the Flask app for both.

Every wait says where it came from

Three kinds of number share one screen and they don't deserve equal trust, so each one is labelled:

Source Means Covers
timetable the next actual departure subway + 6 streetcar routes
headway half the observed gap, live surface routes
modelled half an assumed headway YRT, MiWay, GO

Live service alerts apply on top — a closed line drops out of the graph, so trips route around it.

Layout

app.py        the Flask entry point, and the only module left in the root
network/      the graph: subway, streetcars, buses, regional, and the
              add_node / add_edge primitives they all use
feeds/        what TTC publishes: the GTFS archive, the departure index
              built from it, and the live vehicle feed
trips/        coordinates and a graph in, travel times and itineraries out
tools/        the two GTFS builders, the browser build, the figure refresh

Data in, graph, routes out — and the arrows only point one way, so feeds/ never imports trips/. feeds/schedule.py resolves the departure index two levels up, because getting that wrong does not raise: the departures simply stop being found and the app falls back to average headways as though no timetable had ever been built. A test pins the path.

notes/ holds the long-form write-ups — CODE_AUDIT.md — and CONTRIBUTING.md is in .github/, which is where GitHub looks for it.

Tests

pytest -q --cov --cov-branch --cov-fail-under=100    # what CI runs

317 tests, 100% of 1,844 statements — and that figure is itself checked, because it had already gone stale once. The suite never touches the network: the realtime tests run against recorded feeds, one containing a real Line 2 closure. The figure is the whole repository, lines and branches, the GTFS build tools included: they are tested against feeds of a few rows written by the test.

License

MIT — see CONTRIBUTING.md for setup and test conventions.

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#transit · #maps · #toronto