For example: “Your train should arrive in 8 minutes.”
WHY I BUILT SIGNAL CHICAGO
“The ETA helped me plan - until it kept changing while I waited.
I wanted a way to look beyond one arrival number. Signal Chicago keeps the earlier estimates, checks how they change, and asks whether the gap between trains matches the schedule.
WHAT HAPPENS EVERY TWO MINUTES
A protected cloud function requests new arrival estimates for twelve stations.
The database keeps each estimate so it does not disappear when CTA updates it.
Repeated ETAs become stability measurements; train gaps are compared with the schedule.
The site shows the rider answer first and keeps the analyst evidence one arrow away.
⌄ Open the technical architecture
Source: CTA Train Tracker API and CTA GTFS schedule files.
Collector: Supabase Edge Function triggered by Supabase Cron every two minutes.
Storage: PostgreSQL with validation, collection audit records, 14-day raw retention, and daily summaries.
Website: Static Next.js dashboard on Cloudflare Pages, requesting a read-only summary every minute.
Rider labels: Below 1.3x is close to schedule; 1.3x-1.74x is a larger gap; 1.75x or more is a much larger gap. A 15+ minute average wait can also trigger a watch label. These are Signal Chicago rules, not CTA standards.