An interactive celestial visualizer for Paul Fellows' excellent Once Around series of astronomy YouTube videos.
- ~8,400 stars from the Yale Bright Star Catalog — every naked-eye star, with accurate magnitudes
- Milky Way procedurally rendered based on galactic coordinates
- 88 constellations with IAU-standard lines and labels
- Stellar scintillation (twinkling) simulation in topocentric mode
- Planets with real-time positions via VSOP87 theory
- Planetary moons — Jupiter (4), Saturn (6), Uranus (5), Neptune (1), Mars (2)
- Dwarf planets & small bodies — Pluto, Ceres, Eris, Makemake, Haumea, TNOs (Sedna, Quaoar, and more), asteroids, and the NEOs Apophis and Bennu, all on JPL Horizons osculating elements
- Comets — Halley, NEOWISE, Hale-Bopp, Tsuchinshan-ATLAS, the Great Comet of 1811, Ikeya-Seki, and more, with anti-solar tails
- Orbital paths showing apparent motion against the stars
23 planetarium-style tours with keyframe animation: historic eclipses (1919 Eddington, 585 BCE Battle of Halys), great comets, historical supernovae (SN 1054, Tycho, Kepler, SN 1987A), Venus/Mercury transits, discovery moments (Galileo's moons, Uranus, Neptune, Pluto), and space mission moments (Apollo 8 Earthrise, Voyager 1's Pale Blue Dot). Deep-linkable via ?tour=....
- Upcoming-eclipse banner with center-line paths for the 2026 (Spain), 2027 (Egypt), and 2028 (Australia) total eclipses
- "Navigate to path" — jump your observer to the nearest point on the center line
- Local circumstances — distance from the center line and estimated totality duration
- 3D ground tracks rendered on the Earth globe
- Geocentric — Explore the celestial sphere from Earth's center
- Topocentric — Your local sky with horizon, Alt/Az coordinates
- Hubble — Ride the telescope in LEO, with Sun-avoidance zone, South Atlantic Anomaly, and orbital-path overlays
- JWST — View from L2 with field-of-regard overlay
- FGS guide star lock (
G) — lock onto a guide star and track it, telescope-style
- 30 deep field images from Hubble and JWST at actual sky positions
- DSO markers for galaxies, nebulae, and star clusters with info popups
- ISS and Hubble tracking with real-time positions and shadow state
- ISS pass predictions for your location, with a staleness warning if ephemeris data is out of date (data auto-refreshes weekly from NASA Horizons)
- 13 meteor showers with radiant markers during active periods
- Search — Find any star, planet, constellation, DSO, or satellite
- Time controls — Scrub through time to watch celestial motion
- Video markers — Links to relevant Once Around episodes
- AR mode — Use device orientation to explore (mobile)
- Night vision — Red-only mode for outdoor observing
- PWA — Installable, works offline
- URL deep linking — Share any view, time, or tour
The astronomy engine is regression-tested against JPL Horizons reference data (checked in, runs offline): planets and Pluto within 3′, the Moon within 2.5′ geocentric / 6′ topocentric, minor bodies within 3′ at their element epoch (Ceres at 0.21′), comets within 1°. Tolerances are derived from measured residuals and documented per body, including honest caveats where two-body propagation drifts (main-belt asteroids by 2030, NEOs across Earth encounters). These suites run in CI on every PR.
| Action | Input |
|---|---|
| Look around | Click and drag |
| Zoom | Scroll wheel or pinch |
| Search | / |
| Help / shortcut list | ? |
| Toggle labels | L |
| Toggle constellations | C |
| Toggle video markers | V |
| Toggle DSOs | D |
| Toggle deep fields | F |
| Toggle orbits | O |
| Toggle meteor showers | M |
| Toggle horizon | H |
| Night vision mode | R |
| Guide star lock (telescope modes) | G |
| Next eclipse | E |
| Jump to now | N |
| Play/pause time | P |
| Step time | ← / → |
| Fly to galactic center | Space |
- Frontend: TypeScript, Three.js, Vite
- Astronomy Engine: Rust compiled to WebAssembly
- VSOP87 planetary theory, Meeus lunar theory
- Orbital-element propagation for comets, minor bodies, and planetary moons
- Yale Bright Star Catalog (BSC5) data
- Data pipeline: NASA Horizons ephemerides (satellites auto-refresh weekly via GitHub Actions)
- CI: web typecheck + unit tests, Rust engine test suites (including Horizons accuracy validation)
- Deployment: Cloudflare Pages
once-around/
├── apps/web/ # Three.js frontend application
├── crates/
│ ├── sky_engine/ # WASM bindings
│ └── sky_engine_core/ # Core astronomy calculations (Rust)
├── data/ # Star catalog, ephemerides, and pipeline intermediates
├── scripts/ # Data pipeline (ephemerides, catalogs, transcripts)
├── docs/ # Project documentation
└── tests/ # Playwright end-to-end tests
The scripts/ directory mixes tooling with very different lifecycles, which
differ in how (and how often) they actually run:
- On-demand catalog pipeline — run manually whenever new videos are
published on the channel; there is no schedule or CI job behind it, so it sits
dormant between runs (last run 2026-07-05/06, adding 42 videos). Transcript
scraping (
get_transcripts.sh,scrape_transcripts.js) and catalog building (build_catalog.js). Catalog changes are then applied by hand-editingdata/catalog.json/data/final_placements.jsonand re-runninggenerate-videos-json.js(producesapps/web/public/videos.json) andgenerate_table.js(producesdata/catalog.csv). - Scheduled data refreshes — the two generators that GitHub Actions runs on
a cron.
generate_satellite_ephemeris.pyrefreshes the ISS/Hubble ephemerides weekly (.github/workflows/refresh-satellite-ephemeris.yml), andgenerate_minor_body_elements.pyrefreshes the minor-body orbital elements quarterly (.github/workflows/refresh-minor-body-elements.yml, which opens a PR for human review rather than committing directly). - Engine-support tooling — the two generators here are run by hand when the
data or fixtures they feed need to change.
preprocess_stars(a Rust workspace member) converts the Yale Bright Star / Hipparcos catalogs into the packed binaries underapps/web/public/data/stars/; andfetch_horizons_reference.pyregenerates the checked-in JPL Horizons CSV that keepscrates/sky_engine_core/tests/horizons_accuracy.rsoffline (the quarterly refresh PR asks a maintainer to re-run it by hand). Alongside them,test_generate_minor_body_elements.pyis a network-free unit test for the back-propagation math insidegenerate_minor_body_elements.py; it runs on every PR via thepython-testCI job, and locally withpython3 scripts/test_generate_minor_body_elements.py. - One-time catalog-bootstrap chain —
create_placement_data.js(stage 1) →create_final_placements.js(stage 2) originally produced the initialdata/final_placements.json/data/video_placements.json. It is superseded for incremental updates by the on-demand path above and is kept only so the catalog can be rebuilt from scratch if ever needed (see the header comments in each script). Stage 2 also readsdata/ephemeris.json, which is why that file and its producerfetch_ephemeris.jsare still here despite nothing invoking them routinely.
# Install dependencies
pnpm install
# Build WASM module (required before dev/test)
pnpm build:wasm
# Start dev server
pnpm dev
# Type-check and run web unit tests
pnpm typecheck
pnpm test:unit
# Run the Rust engine test suites
cargo test -p sky_engine_core
# Playwright end-to-end tests (also: test:perf, test:ui)
pnpm test
# Build for production (build:all = build:wasm + build), preview locally
pnpm build:all
pnpm preview
# Deploy to Cloudflare (also: deploy:preview, deploy:all)
pnpm deploy:prod- ROADMAP.md — planned features and known technical debt
- docs/COMPLETED_FEATURES.md — detailed record of implemented features
- Paul Fellows / Once Around for the inspiring video series
- Yale Bright Star Catalog for star data
- VSOP87 theory by Pierre Bretagnon and Gerard Francou
- NASA/JPL Horizons for ephemerides and reference data
- NASA GSFC / Fred Espenak for eclipse path predictions
MIT