AstrOS Engine: satellite orbits in the browser
A mission console with a catalog of satellites orbiting Earth: your own graphics card computes the whole scene, right in the browser, with nothing to install.
Tens of thousands of moving objects live, with no install
Thousands of moving objects at once usually kill smoothness: the CPU and off-the-shelf libraries cannot keep up, frame after frame. We wanted to prove the browser can carry the whole population when the graphics card does the math. No install, a small download, no dropped frames.
All the work on the GPU, zero CPU cost per object
- Seed once
- The orbital elements for 50,000 objects are uploaded to the GPU buffer one time: about 16,500 from the real CelesTrak catalog, the rest from the procedural generator.
- Compute per frame
- A WGSL shader propagates every object in parallel (Kepler + J2 + drag). The CPU never touches a single satellite.
- Render with no copy
- The render pass reads positions straight from the buffer (vertex pulling): one draw call per layer, with no rewriting of data on the CPU.
The engine is platform-agnostic: the same code builds real pipelines on a native Metal or Vulkan device, which lets it be tested in headless CI without a browser.
NASA and NOAA telemetry console
A panel sits over the 3D scene and thinks like a flight controller. Instead of five tables you get the conclusion straight, e.g. "ELEVATED: NOAA WARNING G2". A time slider (×0.125-×4096, log scale) speeds up the simulation, and the aurora on the globe reacts to the real Kp index, a measure of geomagnetic storms. It all works on a phone too.
- NOAA SWPC
- Planetary Kp, solar wind, space-weather alerts
- NASA NeoWs
- Near-Earth asteroids, hazard flags, closest approaches
- NASA EONET
- Natural events: wildfires, storms, volcanoes, floods
- APOD / EPIC / GIBS
- Picture of the day, Earth from DSCOVR, daily satellite imagery
- Launch Library 2
- Upcoming orbital launches with countdowns
Measured, not claimed
- ~16,500
- real objects from the CelesTrak catalog fill the scene (16,563 in the deploy of 2026-09-13; the catalog is re-fetched at every deploy, so the count creeps up), and a synthetic fleet fills it to 50,000, propagated on the GPU the same way.
- 25k-1M
- objects on the slider: you pick the scale of the scene yourself, and smoothness is measured live, not claimed.
- ~1100×
- faster to load the baked catalog than the same data as JSON: 9.2 µs against 10.2 ms for 10k objects, a criterion benchmark on an x86-64 CI host. It is a ratio, not the time on your hardware.
- 211 KB
- is the engine itself over the wire (527 KB unpacked); the whole first load of the page is 1.4 MB. Measured on the live deploy, 2026-09-13.
The baked blob is the array of GPU elements; decoding is practically a copy, with no per-object math. The realism rides the same zero-CPU-cost path as the rest of the engine. The SGP4 reader itself (pure Rust) matches the CelesTrak reference implementation to within 2×10⁻⁷ km.
Our own project. We built it and we run it ourselves. The scene is filled by the real catalog and a synthetic fleet, both propagated the same way.
Every choice has a reason
| Layer | Choice | What it does |
|---|---|---|
| Language | Rust, compiled to WebAssembly | The engine arrives as a small package and starts as soon as you open the page. |
| Graphics | wgpu (WebGPU) | The scene is drawn by your own graphics card, with no layer in between. |
| Physics | Compute shader (WGSL) | The orbits are computed in parallel, so the CPU stays free for the rest of the page. |
| Render | Vertex pulling | Positions go from the card's memory straight to the screen, with no copying both ways. |
| Data | CelesTrak catalog (SGP4) | The orbits come from a public catalog of objects, not from invented numbers. |
