A personal project · idea to live
I built a live radar for Delhi AirportMumbai Airport. Fly through how it happened.
Four runways, three terminals and traffic day and night. Two crossing runways, a creek and the sea next door. One person, a lean toolkit and a lot of curiosity. Scroll down to take off.
Scroll to fly ↓
01 · Where it began
It started as a pretty picture
I wanted an isometric map with white buildings, a little neon and the Geist font. Nothing more. An airport was the perfect subject: real live data, a clear layout, and everyone has waited at arrivals. Delhi came first.Mumbai came second, built the same way, with Delhi left untouched.
The turning point
"Who would actually use this?"
02 · The people
Three users. I picked two.
03 · Reality check
Constraints set the rules
- A steady data pulse. So the page refreshes every 30 seconds and shows how old the data is.
- Thin coverage near Delhi. I say "no data" honestly and label demo planes as sample.
- Two crossing runways. A landing and a takeoff can overlap, so the map shows each runway on its own.
- One login per airport. Mumbai got its own data login, so Delhi never runs out of requests.
- No schedules or delays. I show what I can see: position, height, speed.
- No push server. Browser alerts work while the page is open.
- Light hosting. Tiny pages, and more viewers never add load on the source.
04 · The look
Calm, honest, plain, fit for the job
- Calm. White surfaces. Color only where something moves. Mumbai adds soft blue for the sea and creek.
- Honest. Every number says live or sample.
- Plain. "Landing in 12 minutes", not runway codes.
- Fit to task. Dense for controllers, one answer for pickups.
Tap the floating color tiles, or these:
05 · Under the hood
How the data travels
- OpenSky gives live aircraft positions.
- A GitHub Actions poller asks every 30 seconds and is the only thing that talks to the source.
- Supabase stores the latest snapshot and history.
- Vercel serves the pages, which only read from Supabase.
So more viewers never add load on the source.
06 · What went wrong
Turbulence ahead
The live feed went stale
The scheduled call kept timing out. I moved the poller to GitHub Actions and it came back.
GitHub started late
Scheduled runs can wait up to an hour. I used one long job with a guard so two never overlap.
A crash from my own code
My route feature overwrote a field named "to". I renamed mine and learned to check names first.
"Permission denied" on Mumbai
The new Mumbai tables were created but the page was not allowed to read them. One small permissions fix, then they showed up.
Flight volume stayed empty
The history panel said "no flights counted yet". The table was reachable but nothing had been written, so I checked the recorder next.
The phone page scrolled sideways
One grid item refused to shrink. Two small CSS rules fixed it.
"Not enough history yet"
The history table was empty because the old poller was still running. I made the table and restarted it.
07 · Final approach
Going live, checklist style
08 · Second product
"Where's my pickup?"
A phone-first page for people at arrivals. One question, one plain answer. Slide to try the demo.
About 12 minutes away
09 · Landed
What I'd tell my past self
- Limits are a design input. They gave me the honesty rule.
- Ask "who is this for?" before you polish.
- A stale feed needs a visible warning and a fix.
- Make the page read-only. Keep the admin side private.
- Build the second airport from a kit, not from memory.
Next flight: real weather, schedules and delays, more airports.
10 · Layover
Your connecting flight
You landed in DelhiMumbai. The same story has a second airport. Want to connect?
11 · Next gate
More airports, same kit
Each airport is one small config file plus a few parts for its runways, terminals and names. The shared engine, night view, ATC radar and pilot view come for free, so the next one takes about an hour.
Pick the next gate. Your tap is only saved on this device.