AeroGlobe
In active development · data pipeline & 3D visualization
A browser-based 3D globe for flight tracking. It is a work in progress, and an early version is live. The implementation details and test counts below describe the 23 October 2026 snapshot, not a continuously updated release dashboard.
Work in progress. This case study describes the code on 23 October 2026. The repository’s deployment notes, checked on 6 November, still describe build-time OpenSky observations with a labeled sample-data fallback and a generated sample day. The live site is not a continuously polling live feed, and no real historical day is published yet. Dataset availability can change between builds.
At a glance
282 test declarations in 43 files at the 30 October 2026 snapshot; not a current passing-test total
4 stages in the data pipeline: normalize, segment, chunk, catalog
8,090 lines of TypeScript at the same snapshot
The problem
Most flight trackers show what is in the air now. I wanted to look at flights that have already happened: where an aircraft went, how a route looked over a day, and what a busy hour of global traffic looks like on a globe. That is a data problem before it is a graphics problem. Bulk historical flight logs are large, free and awkward, and a live API gives you only a short window.
My first version was live-first, polling an API every 15 seconds. Auditing it showed that a historical view needs a different shape: process the data ahead of time, publish it as static files, and let the browser do the rest.
Approach
The client is React and TypeScript with CesiumJS for the globe. State lives in Zustand stores, and search and filtering work on a set derived from the flight store. A small Express server proxies the live feed for local development.
The data side is a Node and TypeScript pipeline. It takes state vectors, turns them into per-aircraft tracks, splits each track into flights, slices the tracks into hourly chunks and writes a catalog. The output is plain JSON that a static host can serve, so there is no database and no always-on API. The pipeline puts a size limit on each hourly chunk and throws an error when a chunk goes over it.
What I built
- The globe client. A Cesium viewer with aircraft markers, search, filters for region, altitude, status and airline, a flight detail card, a flight list and a dark and light skin.
- A static data pipeline. Normalization, flight segmentation, hourly chunking and a catalog, with a snapshot command that records a few OpenSky observations and a fixture command that writes a deterministic set of generated traces for offline work.
- A historical source. An adapter for full days of adsb.lol flight data, which runs through the same pipeline and can publish to a separate data branch from my own machine. A global day needs about 10 GB of disk.
- Playback and track replay. A day picker and a time slider with play and pause, driven by the globe’s clock, that moves every aircraft along its recorded positions. A Replay track control follows one selected aircraft, with an option to keep the camera on it. Up to 2,000 aircraft nearest the camera draw a short trail from their consecutive observations.
- Reference data. Airport and airline tables built from public sources, with the source and licence of each recorded next to the file, and time-zone polygons for the planned overlay.
- Tests and checks. The repository’s continuous integration runs lint, the type-checker, the tests and the build on pushes and pull requests to the main branch.
What is planned
The design spec for the next stage is a draft. In outline:
- a published historical day on the live site;
- a faster playback engine that decodes data off the main thread and draws aircraft as one layer, with a transport bar that sets the speed and shows traffic over the day;
- inferred routes between airports and a time-zone overlay;
- a per-aircraft history panel;
- a personal flight logbook kept in the browser.
None of these is built yet beyond the basic playback above, and the spec may change as I build.
What I’m learning
- Choose where the work happens before choosing the framework. Moving the heavy work into a build step is what makes a historical view possible without running a server.
- Fixtures are worth building early. Because the pipeline can run on generated traces, every stage has a test that needs no network.
- An audit of my own first version was more useful than adding features to it.
Stack
TypeScript React CesiumJS Zustand Vite Node Express Vitest