Polaris

A world intelligence website: wildfires, storms, earthquakes, aircraft and satellites on a live 3D Earth, each with its source and the time it was observed.

Status
Live

Deployed on Vercel; stored history in PostGIS is the next phase

Role
Owner and developer: product scope, data pipeline, the globe engine and the site.
Built with
Next.js 16, React 19, TypeScript, CesiumJS, satellite.js (SGP4), zod, Tailwind CSS, Vitest, Playwright, axe-core
Polaris globe showing the Americas with 451 natural events and earthquake markers, a layer rail on the left, an event feed on the right and a 7-day timeline below.
Polaris search showing two ISS modules as results, over Taiwan's city lights on the night side of the globe.Polaris detail panel for a point of open water in the Pacific: modelled weather from Open-Meteo and no other events within 800 km.

The problem

Earth-observation data is public but scattered across agency feeds with different formats, limits and update rates. Polaris puts it on one globe and labels every object with where it came from and how old it is, so a visitor can trust what they are looking at.

How it works

  • Server routes collect from NASA EONET, USGS, OpenSky, CelesTrak, NASA GIBS and Open-Meteo. Every response is validated with zod and normalised into one domain model.
  • Collectors fetch only when someone asks and the cache is due, never run two requests at once, keep serving the last good copy on failure, and back off for exactly as long as a provider's Retry-After says.
  • CesiumJS renders NASA Blue Marble with real VIIRS city lights on the night side. Rendering stays out of React: aircraft are billboards in collections and satellites a point collection propagated once a second with SGP4.
  • The scene renders on demand, so an idle globe costs almost nothing, and a 7-day timeline replays recorded observations.

Decisions that mattered

The browser never talks to rate-limited providers
The server holds every credential and enforces each provider's limits; browsers only load NASA imagery tiles directly.
On-demand, single-flight collection
An idle site spends no provider quota, which matters with anonymous OpenSky's 400 credits a day.
Estimates are labelled as estimates
Satellite positions are SGP4 estimates from published elements, not tracking, and the detail panel says so.
Privacy by construction
No accounts, cookies or analytics. Aircraft appear only by broadcast identifiers; owners are never looked up.

Problems I had to solve

Thousands of aircraft without React re-rendering

About 10,000 aircraft and every tracked satellite are drawn as Cesium primitives that React drives through method calls on a GlobeEngine, instead of components that re-render each update.

Living inside provider limits

Anonymous OpenSky allows roughly one global snapshot every 15 minutes, and CelesTrak asks not to be polled faster than every 2 hours. Each feed has its own refresh policy and freshness threshold, and the Sources page shows the live state of every one.

What is verified, and what isn't

Verification status of each part of Polaris
PartState
41 unit tests passing for normalisers, the collector, geo maths and SGP4 (run 25 Oct 2026)Verified
Live on Vercel at polaris-seven-ashen.vercel.appVerified
Playwright end-to-end and axe accessibility specsBuilt, not yet verified
Stored history in PostgreSQL + PostGIS on an Oracle VMBlocked

Taken from the project's own status documents.

Still unfinished

  • PostgreSQL + PostGIS on the Oracle VM for stored history
  • Docker Compose and an HTTPS reverse proxy for the server phase
  • Authenticated OpenSky access for a faster aircraft refresh