What Crosstown is
Crosstown shows every COTA bus in Columbus in real time and keeps a permanent record of how the system performs. The schedule says when each bus should arrive. Crosstown records when it did. The longer it runs, the more those records can tell you about a route.
Where the data comes from
COTA publishes two public GTFS-realtime feeds: vehicle positions and trip updates. A worker polls positions every 15 seconds and trip updates every 30 seconds, around the clock. The position feed is what moves the buses on the live map.
COTA's feed publishes predicted arrival times but not delays, so Crosstown computes each delay by joining the prediction against the published schedule. The last prediction before the bus reaches a stop is taken as the observed arrival. It is not perfect ground truth, but it is the same number COTA's own arrival screens run on. Stops the bus has not reached are never counted, and predictions left behind by trips that drop out of the feed are discarded rather than treated as arrivals.
What counts as on time
A bus counts as on time if it arrives no more than 1 minute early and no more than 5 minutes late, the standard most US transit agencies report. Early counts against a route because an early bus is one its riders missed. Every arrival lands in a per-route daily rollup, broken out by time of day. Raw arrival records are kept for 90 days, and the rollups are kept permanently.
How it is built
The project is two deployable pieces in one repo. A TypeScript Fastify service handles ingestion, Postgres, and the API, and pushes live positions to the browser over server-sent events. The frontend is Next.js, with MapLibre rendering the map and bus motion interpolated client-side between feed updates. The aggregations are plain SQL. Source is on GitHub.
// the shape of it
COTA GTFS-RT ──> poller (15s / 30s) ──> Postgres
static GTFS ───> loader ────────────────┘
Postgres ──> nightly rollups ──> stats API ──> charts
poller ──> SSE ──> live map
Built by Jonathan Schafer, a full-stack developer in Columbus. The data comes from COTA's open data program. This site is not affiliated with COTA.