Transport Adequacy App — Ideation
How to build it, and how to make it better than the original report
Planning doc · No code · April 2026
The original transport_gaps report had one fundamental flaw behind all the surface errors: it tried to be a narrative, not an instrument. It decided what the story was ("transit fails them", "formula works") and mined the data to support it. An app inherits that frame or breaks it. This document is about breaking it.
1What is the question the app is actually answering?
The original conflates four different questions under one roof:
| Question | Who asks | What they need |
| Do residents have transit near them? | Planners, public | Coverage map |
| Can people reach where they need to go? | Residents, equity researchers | Accessibility, not coverage |
| Is the system overloaded? | Operators, LTA | Capacity / utilization |
| Where should we invest next? | Policy, investors | Marginal impact analysis |
These are different apps under one shell, not one dashboard. An honest app lets the user pick the question first, then shows metrics fit for that question. The mistake of the original is treating pop/station and taps/resident and distance-to-MRT as if they answer the same question — they don't.
2The shift that matters: from coverage to accessibility
Coverage: "Is there a station within 800m?" — an infrastructure fact.
Accessibility: "In 30 minutes of public transport, what fraction of jobs / schools / hospitals / groceries can I reach?" — what people actually care about.
Singapore has the rare privilege of origin-destination data being public (LTA od_train files). That means the app can compute true isochrones — not "distance from station" but "time to anywhere." This is the single biggest honesty upgrade available, and it flips the conclusion in multiple places. A zone 900m from an MRT station on a fast line with 3-minute headways may have better 30-min accessibility than a zone 400m from a slow terminal.
Almost every per-subzone finding in the original dashboard changes under this lens. Woodlands East isn't "overcrowded" — it's "an origin with 40-min mean travel time to CBD." That's actionable.
3The metrics that would be honest
Replace the original's metric set with something the audit can survive:
| Axis | Honest metric | Flawed proxy it replaces |
| Access | % of jobs reachable in 30/45/60 min by PT, population-weighted | distance-to-nearest-MRT |
| Capacity stress | peak-hour line load vs design capacity, by segment | pop/station |
| First-mile | median walk-time to first PT boarding (from building footprints) | bus-stops-per-zone |
| Transfer penalty | % of trips requiring 2+ transfers | coverage-only |
| Temporal adequacy | adequacy at 8am / 2pm / 10pm / Sunday — separately | single average |
| Equity gap | accessibility P10/P50/P90 by HDB/private, elderly %, income | none in original |
| Demand signal | observed taps ÷ modeled demand (under-served = taps << expected) | ridehail-as-canary |
The audit-killer was that every original metric used the wrong denominator. Fix it by being explicit about denominators: residents for residential adequacy, workers for employment-zone adequacy, daytime pop for commercial, visits for tourist.
4The interaction model
Two modes, both first-class:
Reverse-geocoding mode — pick a location
- Your 15/30/45-min reach by walk / bus / MRT / multimodal
- % of SG jobs reachable in 30 min; % of hospitals, schools, groceries
- Your percentile among SG residential zones
- The chain that breaks — e.g. "walk 8 min → bus 22 min → MRT 15 min. First mile is 50% of your time budget. That's the weak link."
Destination mode — pick a destination
- Its PT-shed: color each origin zone by time-to-get-here
- Equity lens: who can't reach it in 45 min? Map overlay by HDB share / elderly %
- Arrival-time distribution: how many can arrive by 8 am vs 9 am
Scenario mode — add a hypothetical station / bus route
- Compute delta in accessibility
- Residents newly inside 30-min iso
- Cost-per-newly-served-resident
Without scenario mode this is just a visualization. With it, it's a decision tool.
5Methodology as UI, not as footer
The audit failed the original because methodology was hidden. An honest app inverts this:
- Every number has a "why" tooltip that shows the formula.
- Definition toggles are primary UI: MRT-only vs MRT+LRT / Euclidean vs network / weekday-peak vs all-day. When you flip a toggle, numbers move. This teaches the user that the number is conditional.
- Confidence bands, not point estimates. "1.0M ± 200K residents beyond 800m, depending on how you define walk distance" is more truthful than "1.0M".
- Public methodology doc at
/methodology with the exact code paths.
This is the single biggest differentiator from the original. Most dashboards hide their assumptions; this one surfaces them.
6The cross-city angle
Atlas already has NYC, Chicago, LA, SF, SJ. Singapore in comparative context is a killer feature:
- "Singapore HDB towns have better rail accessibility than Manhattan outer boroughs"
- "Tuas West workers have accessibility comparable to LA industrial zones"
- "SG median walk-to-rail is X; NYC is Y"
The 135-d graph fingerprint vectors already in atlas can be extended with an accessibility fingerprint. Then SG subzones get nearest-neighbours in NYC/Chicago — a way to import lessons. The original report's ceiling was Singapore-only; this breaks that ceiling.
7What's currently missing in the data repo
Critical gaps to close before building:
| Data | Why needed | Status |
| Bus GTFS (stops + routes + frequencies) | Accessibility by bus is unreliable without it | MISSING |
| OSM pedestrian network for SG | Network walk distance > Euclidean | PARTIAL (roads exist, ped subset unclear) |
| Daytime / worker location | Correct denominator for CBD zones | MODELED (flag as proxy) |
| Ridehail trips | Only with operator partnership | UNAVAILABLE — drop canary narrative |
| Future LTA master plan (JRL, CRL) | Scenario mode needs this | TO PULL |
| Building footprints + unit counts | First-mile from doorstep, not centroid | PARTIAL (HDB exists, coverage TBD) |
8Architecture, at the level of principles
Three layers:
- Compute layer (offline, heavy): isochrones, accessibility scores, percentile normalizations. Batched nightly. Output: parquet per subzone / hex / building.
- Tile layer: vector tiles for choropleths; per-feature JSON for drill-in. Cache-friendly.
- App layer: thin. No heavy client math. Map + query + methodology UI.
Why this matters: the original dashboard likely did everything client-side with static HTML. That's fine for a report but bad for an app. For an app, the expensive stuff has to be precomputed and served, and the UI has to be cheap to interact with.
Hex vs subzone: subzone is government-natural (matches demography and planning); hex (H3 at res 8 or 9) is analytically cleaner (equal area, no boundary artifacts like "Selegie has 0 MRT"). An honest app shows both and lets the user toggle — and population-weights within a hex, not centroid.
9Pitfalls to name up front
- OSM walk network is imperfect in Singapore — pedestrian overhead bridges, covered linkways, mall through-routes are often missing. Field verification matters for headline numbers.
- Isochrones are sensitive to start time — miss a 10-min bus by 30 seconds and your accessibility halves. Report distributions, not points.
- Daytime pop is modelled downstream — treat as proxy, label it so.
- Peak hour is not one number — morning peak and evening peak have different geometries. Treat them separately.
- Singapore is small — edge effects are real. 800m at the edge of a subzone that's 1 km across means half the zone is in the "gap" even if 90% of residents are in range.
10Where I'd start, if we agree on the above
The smallest unit that would be visibly better than the original report:
- Pedestrian isochrone (15 / 30 / 45 min) from each subzone building footprint centroid, using OSM walk network. Replaces the Euclidean 800m metric.
- Job accessibility score: % of SG jobs reachable in 30 min by multimodal PT, using LTA od_train + bus GTFS.
- Two interaction modes: pick-your-origin and pick-your-destination.
- Definition toggle (MRT-only vs MRT+LRT, time budget 30 / 45 / 60).
- Methodology drawer on every metric.
- No ridehail, no "canary" narrative, no causal claims.
Everything else — scenarios, equity overlays, cross-city benchmarking, temporal slider, growth-readiness — is phase 2+.
The strongest opinion in this doc: the biggest value of this app is not the pretty map. It's forcing the conversation from "where are the gaps in infrastructure?" to "where are the gaps in access?" The first is easy to argue about; the second has an answer. Singapore has the data to give that answer honestly, and almost nobody has built that — not even LTA publicly.
Open questions — where do you want to push back or go deeper?
1. Is accessibility-first the right reframe, or do you want to keep a coverage lens as the primary view?
2. Is scenario mode (hypothetical station → delta) table-stakes, or phase 2?
3. Cross-city benchmarking — phase 1 or defer?