Adam El Kadaoui
Selected work

Personal project · Interactive data visualization

Orbit
Pulse

Earth's orbital infrastructure, propagated in the browser.

An interactive visualization of the objects currently orbiting Earth. CelesTrak orbital element sets are refreshed at deploy time and served as a static dataset; a Web Worker propagates thousands of orbits with SGP4, and MapLibre draws every object through a single geospatial layer.

Propagated estimates from orbital element sets · Not live telemetry

Role
Architecture · Front-end engineering
Compute
Web Worker · SGP4 propagation
Rendering
MapLibre GL · one data layer
Data
CelesTrak OMM · refreshed at deploy
Stack
Angular · TypeScript · satellite.js
Delivery
Static build · Vercel

What it shows.

  1. 01 · Catalogue

    More than 11,000 real orbital objects on one globe.

    Space stations, GPS, weather and Earth-observation satellites, Starlink — deduplicated by NORAD catalog id.

  2. 02 · Inspect

    Search by name or NORAD id, then read one object's state.

    Altitude, velocity, inclination, period, perigee, apogee, element-set epoch.

  3. 03 · Track

    The selected object's ground track for one full revolution.

    Split at the antimeridian · trail behind, path ahead.

  4. 04 · Simulate

    A 24-hour UTC timeline at 1×, 10× or 100×.

    Simulation time and propagation cadence stay independent.

The OrbitPulse globe carrying 11,262 propagated orbital objects, with ISS (ZARYA) selected over the South Atlantic beside its ground track, a detail panel reading 419 km altitude and 7.66 km/s, and a 24-hour timeline
ISS (ZARYA) selected · 11,262 objects · Propagated estimatesLaunch ↗(opens in a new tab)

Mean elements in,
positions out.

An orbital element set describes an orbit, not a position. Turning eleven thousand of them into coordinates — and doing it again every time simulated time moves — is continuous work that cannot share a thread with a globe the visitor is dragging.

So it doesn't. The dataset is assembled once, at deploy time. A Web Worker builds one SGP4 record per object when the dataset loads, then propagates the whole catalogue on a bounded cadence and hands the results back as transferable typed arrays. The main thread only renders.

  1. 01CelesTrak GPOMM JSON
  2. 02Build-time refreshfetch · validate · dedupe
  3. 03Static datasetone file, no backend
  4. 04Angular appsignals · zoneless
  5. 05Web Workersatrec built once
  6. 06SGP4 positionsFloat32Array
  7. 07MapLibre globeall objects, one layer

Off the main thread — propagation never blocks rendering or input

Three decisions.

Performance

Off-main-thread simulation

SGP4 orbital propagation runs in a dedicated Web Worker, so thousands of position computations never block the interface.

Rendering

High-volume rendering

More than 11,000 orbital objects are rendered through a single MapLibre data layer instead of individual DOM markers.

Architecture

Static architecture

Orbital elements are refreshed during deployment, so the application runs without a backend, database or API keys.

Propagation and rendering are deliberately decoupled: the clock advances on animation frames, the worker propagates on its own bounded schedule and skips a tick if it is still busy, and category filtering is a MapLibre layer expression rather than a rewrite of the data.

Estimates,
not telemetry.

The result is an interactive globe carrying more than 11,000 real orbital objects, with search, category filters, ground tracks and time simulation — and no server, database or API key of its own.

What it shows are propagated estimates from mean elements, not live GPS telemetry. SGP4 accuracy decays as an element set ages, and the dataset is a snapshot taken when the site was last built, so every object's detail panel carries its element-set epoch and how old that epoch is.

Elements from
CelesTrak general perturbations
Refreshed
On every deployment
Scope
Selected groups, not the full catalog

Angular · TypeScript · MapLibre GL · Web Workers · SGP4 · CelesTrak