This started as a solo side project: a real-time satellite tracker (satradar.com) that shows every active spacecraft orbiting Earth — Starlink trains rising over your horizon, the ISS passing overhead, the GPS constellation in MEO, weather satellites watching hurricanes, geosynchronous comms parked at 35,786 km — I managed to get it updating at up to 120 FPS in Chrome and Safari on my MacBook Pro, though it will do 60 FPS on an iPhone too. I filter out debris and rocket bodies so what you're seeing is the live, working fleet, not dead fragments.
The trick to keeping it fast: the entire SGP4/SDP4 orbital propagator runs inside a WebGL2 fragment shader. Two-Line Element sets (TLEs) go in as a texture, a render-to-texture pass spits Earth-Centered Inertial (ECI) positions out the other side, and the vertex shader reads them back the same frame. Kepler iteration, SDP4 lunar/solar perturbations, the J2/J3/J4 terms — all of it lives in one big GLSL function. The CPU does nothing per-frame.
The same orbit math runs natively on iPhone, iPad, Mac screensaver, Apple TV, and Vision Pro via a Metal port. Six surfaces, one source of truth for every render constant: a single satellite-config.json that both the Swift and the JS pull from at boot. Web throws on first paint if the JSON is missing a key — the two sides drifted silently too many times before I gave up and made it a hard error.
GLSL and Metal can disagree in subtle ways (atan2 near the poles, fp32 mantissa, ANGLE vs Apple's shader compiler, animation timers vs frozen sim clocks), so every push to main PNG-diffs all GPU backends against frozen-time baselines in R2, with GPT-5.4 as a tiebreaker on anything below the pixel threshold. Public dashboard: https://satradar.com/visual-tests.html
The Mac screensaver is free and walks you through everything that was in orbit from October 1957 (Sputnik, alone up there) to modern day — six decades of orbital history, sped up, watching the sky go from one object to more than ten thousand.
A couple of things to play with if you want to jump straight in: the URL accepts ?follow=<NORAD-ID> so you can deep-link to a specific satellite — the ISS, Astranis Arcturus (Astranis's first MicroGEO — a small, dedicated GEO comsat with a reprogrammable software-defined radio), or NuView Alpha (a brand-new commercial LIDAR satellite). It also takes ?date=YYYY-MM-DD, ?speed=<time-warp>, and ?altitude=<Earth-radii> for richer shareable views.
Would love feedback — features you'd want, satellites or constellations I'm not handling well, edge cases in the shader you can break. The iPhone and iPad app is live on the App Store (https://apps.apple.com/app/id6760600849), and the Mac screensaver is a free download. The Apple TV and Vision Pro builds are close behind — if you want into either beta, reply here or ping me and I'll add you.
That's pretty neat. I didn't realize how far out the GPS satellites were. Also, TIL that Hubble telescope was LEO. Wild.
This started as a solo side project: a real-time satellite tracker (satradar.com) that shows every active spacecraft orbiting Earth — Starlink trains rising over your horizon, the ISS passing overhead, the GPS constellation in MEO, weather satellites watching hurricanes, geosynchronous comms parked at 35,786 km — I managed to get it updating at up to 120 FPS in Chrome and Safari on my MacBook Pro, though it will do 60 FPS on an iPhone too. I filter out debris and rocket bodies so what you're seeing is the live, working fleet, not dead fragments.
The trick to keeping it fast: the entire SGP4/SDP4 orbital propagator runs inside a WebGL2 fragment shader. Two-Line Element sets (TLEs) go in as a texture, a render-to-texture pass spits Earth-Centered Inertial (ECI) positions out the other side, and the vertex shader reads them back the same frame. Kepler iteration, SDP4 lunar/solar perturbations, the J2/J3/J4 terms — all of it lives in one big GLSL function. The CPU does nothing per-frame.
The same orbit math runs natively on iPhone, iPad, Mac screensaver, Apple TV, and Vision Pro via a Metal port. Six surfaces, one source of truth for every render constant: a single satellite-config.json that both the Swift and the JS pull from at boot. Web throws on first paint if the JSON is missing a key — the two sides drifted silently too many times before I gave up and made it a hard error.
GLSL and Metal can disagree in subtle ways (atan2 near the poles, fp32 mantissa, ANGLE vs Apple's shader compiler, animation timers vs frozen sim clocks), so every push to main PNG-diffs all GPU backends against frozen-time baselines in R2, with GPT-5.4 as a tiebreaker on anything below the pixel threshold. Public dashboard: https://satradar.com/visual-tests.html
The Mac screensaver is free and walks you through everything that was in orbit from October 1957 (Sputnik, alone up there) to modern day — six decades of orbital history, sped up, watching the sky go from one object to more than ten thousand.
A couple of things to play with if you want to jump straight in: the URL accepts ?follow=<NORAD-ID> so you can deep-link to a specific satellite — the ISS, Astranis Arcturus (Astranis's first MicroGEO — a small, dedicated GEO comsat with a reprogrammable software-defined radio), or NuView Alpha (a brand-new commercial LIDAR satellite). It also takes ?date=YYYY-MM-DD, ?speed=<time-warp>, and ?altitude=<Earth-radii> for richer shareable views.
Would love feedback — features you'd want, satellites or constellations I'm not handling well, edge cases in the shader you can break. The iPhone and iPad app is live on the App Store (https://apps.apple.com/app/id6760600849), and the Mac screensaver is a free download. The Apple TV and Vision Pro builds are close behind — if you want into either beta, reply here or ping me and I'll add you.