Releases: chipi/orrery
Release list
v0.7.2
Added
- Capability + orientation responsive layout — the mobile / landscape UI now keys off
data-touch+data-orientationattributes rather than viewport width. On touch the site footer moves into the nav drawer as a bottom section; in landscape the bottom drawer controls collapse into one row beside the scale / scrubber; drawer panels are width-constrained to the portrait-stack size and centre above the tab that opens them. - Searchable orbit / land object index for
/mars,/moon,/earth(modelled on the ISS module list). Desktop edge-handle toggle + mobile drawer tab; free-text search; per-item agency logo; click-to-focus that flies the camera and opens the detail panel; filters for domain (in orbit / on land), agency, era (year), and status. Earth combines launch sites (land) with orbiters (orbit). - Global internal-link checker (
scripts/check-internal-links.mjs) wired intonpm run build+ preflight. Crawls every prerendered HTML page and fails on base-less (/foounder a based deploy) or unresolved internal links — the class of 404 that base-less client navigations produce on the/orrery/GitHub Pages base.
Fixed
- Tour navigation is base-aware — audio-tour
navigatestages route through${base}${target}, fixing the/science/transfers(and every other stage) hard-404 when served under the GitHub Pages base path. - Back button across the mission → launcher → fleet card chain — every detail→detail path now records the card chain, so the back button appears on the destination card.
- Panorama touch-swipe direction on surface routes — dragging now moves the view the same way the finger travels.
Testing
- The i18n route-sweep (
tests/e2e/i18n-all-routes.spec.ts) counts locale-script characters across visible text and accessible names (aria-label / title / placeholder / alt), so canvas-heavy routes (/explore,/fleet,/fly) stay green after the footer moved into the nav drawer.
v0.7.1
Changed
- PWA install + update reliability — bundle the i18n overlays and shrink the service-worker precache from 4,456 to 355 entries; stop precaching ~1.7 GB of imagery (was blocking SW install on iOS); register the SW under the
BASEpath with silent update rollover; add guardrails so silent update-stall regressions can't recur.
Added
MobileControlsDrawer— a unified, non-blocking partial drawer./exploreand the surface routes (/earth,/mars,/moon) gain a 3-tab drawer accordion, a top control cluster across all five canvas routes, and a station accordion on/iss+/tiangong.- Card back-chain extended to
/explorebodies and surface sites; planet missions link to their real mission records with a detail-card back button.
Fixed
- Mobile: flat-patch layout, stations-list close,
/flyspeed popover, lens stacking, surface chips,/flyaccordion,/planlens offset, and surface immersive-mode collisions; keep the mobile footer to one line (build date → tooltip); bottom-sheet scrim + z-order so detail panels always close. - Preflight: clear dead-holder locks instantly + fail-fast on lock contention.
Testing
- Migrate the mobile e2e specs to
MobileDrawerGroup; fix a11y / hang regressions; regenerate visual snapshot baselines.
v0.7.0 — Surface hotspots, image pipeline v2, science lens, cinematic /fly
The biggest release since v0.6.3 — the "throne of glory" push across surface imagery, the science lens, and /fly, plus a full image-pipeline rebuild and i18n expansion.
Highlights
- Surface hotspots — real tier-2 / tier-3 orbital + panorama imagery for Apollo, Chang'e, Luna, and Mars-rover sites; zoom-to-detail flat-patch + stand-at-site panorama modes.
- Image pipeline v2 (#148 / #363) — VisionProvider + sharp variants + sidecar layering + hero-override JSON, plus a
/devstaging-ground review surface (promote / prune). - Science lens — 28 physics-overlay layers across every 3D route; textured Mars moons, hydrosphere limb-glow, Earth–Moon tide arrow.
- Cinematic /fly — multi-camera flyby montage, adaptive establish / approach framing, ship-hero fallback, and a 14-mission catalog backfill (#341).
- i18n — 14 locales; science-overlay + UI-string translation pipelines.
- Analytics (#366) — typed event registry across all pages.
- /posters gallery, /explore time-playback controls, colophon provenance for original work.
Tagged retroactively at 6dc4f2d57, the last commit before the PWA-precache work.
v0.6.3
Mobile UX + reliability pass. Five user-filed mobile polish issues (#125-#129) plus three v0.6.2 follow-ups land together: missions density matches fleet, science-lens overlap on /fly cleared, space-stations black-canvas race fixed, deterministic e2e replacing retry-passes, release tooling made truly one-command, bundle warning silenced, and the encyclopedia gains two curated companion lists.
Added
- Reading list at
/science/reading-list(issue #128) — 8 curated beginner-to-intermediate space books (Cosmos, Pale Blue Dot, A Brief History of Time, The Right Stuff, Packing for Mars, Rocket Propulsion Elements, Fundamentals of Astrodynamics, How to Read the Solar System) + 5 long-form blog/journalism recommendations (Planetary Society, Casey Handmer, Eric Berger / Ars Technica, NASA Spaceflight Forum, Damn Interesting). Audience badges (beginner/intermediate/advanced), explanatory blurbs. - Watch list at
/science/watch-list(issue #129) — 7 sci-fi films (Contact, Interstellar, 2001, The Martian, Apollo 13, Moon, For All Mankind), 4 documentaries (For All Mankind '89, In the Shadow of the Moon, Cosmos: A Personal Voyage, When We Left Earth), 3 podcasts (Off-Nominal, MECO, Are We There Yet?), 4 YouTube channels (Scott Manley, Everyday Astronaut, Veritasium, PBS Space Time). - Both new pages are anchored as tab cards at the bottom of the
/sciencerail nav. New paraglide keysscience_tab_reading_list+science_tab_watch_listin en-US; other 13 locales fall back to JS title-casing via the existingtabLabelhelper (full localisation deferred to the next wave23 batch). scripts/release-rehearsal.ts— interactive version bump + CHANGELOG scaffold (issue #223). When the script detectspackage.json.versiondoesn't match the argument version, it offers to bump it via a[Y/n]prompt. When the CHANGELOG section is missing, it offers to scaffold a stub with today's date + empty Added/Fixed/Changed shells. Non-TTY contexts (CI, scripted) take the "no" default — the fail-closed contract from v0.6.2 #134 holds..github/workflows/release.ymlauto-publishing GH Release on tag push (was v0.6.2 work but properly exercised for the first time on v0.6.3 — confirmed idempotent on the v0.6.2 retag, marked Latest only for stable semver).
Changed
- Mobile mission tiles → 2-per-row (issue #125) —
/missionscard grid usesrepeat(auto-fill, minmax(150px, 1fr))on ≤600 px so the layout matches/fleetdensity (which the user prefers). Both surfaces carry agency logos so the same minimum-width floor works; very narrow viewports (<340 px) degrade gracefully to 1 column. - Equal-height cards in /missions + /fleet grids (issue #225) — within a row, card heights now stretch to match the tallest. Was sizing to content, so a card with a long name + caveat sat taller than its neighbours and broke the visual rhythm. Two-line fix per file:
.card-li { height: 100% }+.card { height: 100% }. - Science layers panel — collapsed-by-default on mobile, raised z-index (issue #126) — the expanded panel was overlapping
/fly's CAPCOM ticker. Now ships as a strip on ≤600 px (tap to expand), max-height 50vh → 40vh, z-index 32 → 37 so the active interaction renders above the CAPCOM panel rather than under it. /sciencewider page + flexible right rail (issue #226) —.page max-width 1200 → 1440 px, right rail track220px → minmax(220px, 320px). On viewports >1200 px the layout was sitting centered with empty margin on the right, and the right-rail section list couldn't grow into that space. Now wider viewports get more usable area and the section list claims some of it (capped so the prose column stays dominant). Mid-range (768-1024 px) behaviour unchanged.vite.config.tschunk-size warning ceiling 500 → 700 kB (issue #224). Identified the two offenders:three.module.js~513 kB (already auto-chunked by Vite, can't tree-shake further at the SvelteKit layer) and Paraglide'smessages.js~665 kB (per-locale split needs anoutputStructure: 'locale-modules'change in inlang/project — deferred follow-up). Both intentional; raising the ceiling stops the build log from carrying a known-known every release. >700 kB is now the real regression flag.
Fixed
- Space stations 3D black-canvas on cold mount (issue #127).
/iss+/tiangongkicked offstartThree()viaqueueMicrotaskafteronMountsetviewMode='3d', but queueMicrotask fires BEFORE the browser's first layout pass on a cold load — socontainer.clientWidthread0and the renderer was sized 0×0, giving a permanent black screen until something else triggered a resize (the workaround the user reported: navigating away and back). Fix: newstartThreeWhenSized()wrapper subscribes a ResizeObserver to the container and starts THREE on the first non-zero size emit. Synchronous when container is already sized (no regression in the happy path). - /moon + /mars: rotate planet to face the deep-linked site (issue #227). When a mission card's "to the surface" cross-link lands on
/moon?site=Xor/mars?site=X, the panel + halo open but previously the planet stayed in its default orientation — the site itself could be on the far side, invisible until the user manually dragged. NewfaceMoonAtSite()/faceMarsAtSite()callbacks (gated on aface: trueoption toselectSite) compute the longitude angle of the site and setmoonMesh.rotation.y/marsMesh.rotation.yso the site lands on the camera-facing +Z hemisphere. autoSpin pauses so it stays put. Latitude isn't adjusted (camera moves would be a heavier change), but the longitude flip alone fixes the "site on far side" case the user reported. - /fly red-dot vs blue-tube split — root-cause rewrite (issue #228). Five prior attempts (v0.6.1 sprite-tube alignment, v0.6.2 future-tube tip snap, plus three intermediate translations) treated symptoms. A debug log on the v0.6.2 build showed the gap between the TubeGeometry cross-section centroid and the spacecraft sprite peaking at 20.33 scene-units mid-arc (Earth orbit is 80 units, so the gap was visually huge). Root cause:
THREE.TubeGeometrysamples its curve viagetPointAt(arc-length uniform u)even when the sourcePolylineCurve3overridesgetPoint(t)to be a uniform-t lerp. For Kepler ellipses sampled at uniform true anomaly (transferEllipseinmission-arc.ts), adjacent-chord lengths differ by ~10× between perihelion and aphelion — so arc-length-uniform u disagreed with uniform-t parameter by exactly the gap we were chasing. Heliocentric tubes rewritten as one mesh per leg with a manual builder that places cross-sections at exactlypts[i]and aShaderMaterialwhose fragment shader paints bright ifvT<uProgress, dim otherwise — boundary lands at the sprite by mathematical identity (proven numerically against a Kepler-shape unit test, zero gap across 100 sampled t values). Same shader-gradient treatment applied to cislunar phase lines (#228b): each phase line carries per-vertexaT, per-frame uProgress derived frommet_daysvs phase's[start_met_days, end_met_days]window. Net delete: outLineFuture/retLineFuture meshes, snapTubeTip vertex-mutation function + tipMutation cache, PolylineCurve3 class (now unused), v0.6.2 debug console.log. ~140 LOC added, ~210 LOC removed. - 5 flaky mobile e2e tests — deterministic waits replacing retry-passes (issue #222). v0.6.2's release rehearsal had 5 mobile-chromium tests passing on retry:
earth.spec(satellite click) added a 150 mspanel.waitFor({state:'visible'})per click instead of bareisVisible();earth.spec(ISS GALLERY thumbnails) bumped timeout 5 s → 10 s for image-load on slow CI;fly.spec(3D/2D toggle) swapped fragile role+name regex for[data-testid="fly-view-toggle"]+not.toHaveText(initialLabel);_helpers/nav.ts.clickNavLinkwaits for the drawer link to be visible before clicking (coversi18n-pt-BR.spec);mars.spec(FULL MISSION CARD cross-link) droppedwaitForLoadState('networkidle')(mars streams canvas textures continuously, never hits the 500 ms quiet window) + bumped cross-link timeout to 10 s.
v0.6.2
Reliability + release-tooling pass on top of v0.6.1. Tightens the e2e suite (deterministic readiness signals, body-text translation coverage, Linux visual baselines), removes a parallel-agent footgun in validate-data, and codifies the AGENTS.md release-readiness checklist as actual tooling — a one-command pre-tag dry run and an auto-publish GH Release workflow on tag push.
Added
npm run release:rehearsal vX.Y.Z(issue #134) — single command that runs preflight + e2e on bothdesktop-chromiumandmobile-chromiumprojects, extracts the matching## [X.Y.Z]block fromCHANGELOG.md, and creates a DRAFT GH Release. Fail-closed on any step. Codifies the AGENTS.md §"Before tagging or releasing" checklist so the rule is verifiable, not just documented..github/workflows/release.yml— auto-publish GH Release on tag push (issue #135). Fires on anyv*tag push. Extracts the CHANGELOG section, creates the Release with that body, marks Latest only for stable semver (pre-releases likev0.6.2-rc1don't bump the homepage marker). Idempotent — re-runs on a re-tagged commit update the existing Release. Eliminates the "tagged but no Release" failure mode that hit v0.6.0 + v0.6.1.- Mobile Cmd-K affordance in
/science(issue #137) — the encyclopedia search trigger is now reachable on ≤640 px viewports via a Search row in the hamburger drawer. Samearia-labelas the desktop rail Search button, sogetByRole('button', {name: /Search the encyclopedia/i})matches in both viewports. Newnav_searchparaglide key in all 14 locales. scripts/regenerate-visual-baselines-linux.sh+npm run regen-visual-baselines-linux(issue #132). Runs the pinned Playwright Docker image with a host-side.linux-node-modules/overlay so Linux visual baselines are generated bit-identical to CI's ubuntu-latest runner, without touching the host's darwin install. Six new*-linux.pngbaselines committed; thetest.skip(process.platform !== 'darwin')guard from v0.6.1 is dropped.docs/guides/visual-regression-baselines.md— full regeneration workflow + commit conventions + three documented failure modes (esbuild arch collision,/.npmEACCES, non-deterministic renders). Cross-linked fromvisual.spec.ts.tests/e2e/i18n-body-text-desktop.spec.ts(issue #131) — desktop-only smoke covering 6 EU-Latin locales (de/es/fr/it/nl/pt-BR) asserting that a translated body-text token (plan_empty_title) actually renders. Closes the coverage gap the v0.6.1html[lang]-only migration left: a silent Paraglide en-US fallback on a translated screen now fails the smoke instead of passing.
Fixed
/fly3D ↔ 2D hash-invariant flake — deterministic readiness signal (issue #133). Replaces the v0.6.1data-out-vertex-hashstability poll with ADR-056 hooks:window.__flyArcHash()+window.__fly2DArcHash()return the stable 11-vertex hash ornullwhile hydrating;window.__flyMissionId()returns the id of the mission most recently committed to page$state. Reading from Svelte's reactive$stateat call time eliminates the microtask gap between framework flush and DOM attribute write. Targeted run (12 cases): 5 consecutive runs, zero flake. Full suite: 62/62 in 1.3 min.validate-datano longer scans untracked PRD/RFC drafts (issue #136). Scoped the doc-gating-sentence check togit ls-files docs/prd docs/rfc docs/adrso a parallel agent's untracked draft can't refuse your unrelatedgit push. Staged-but-uncommitted files still get gated. Falls back to the filesystem walk ifgitisn't accessible (CI shallow-clone edge case). The stash-and-restore workaround from AGENTS.md §"Pre-push hook quirks" + CLAUDE.md §"Untracked PRD/RFC drafts" is dropped.
Changed
v0.6.1 — e2e stability + footer + /fly 3D fix + PWA auto-update + space-themed docs
A patch landing the day after v0.6.0 to stabilise CI / e2e, add a build-date stamp + README + CHANGELOG links in the footer, fix a long-standing /fly 3D sprite-tube alignment bug, switch the service worker to silent auto-update, and ship a space-themed VitePress docs site.
Added
- Footer build date + README + CHANGELOG links — the footer now reads
Gallery | Credits | Library | License | README | v0.6.1 · 2026-05-16. README is a separate link (back from being merged into the version pill); the version + deploy-date pill links toCHANGELOG.mdon GitHub instead of the README. Build date is injected at build time via Vitedefine(same pattern as__APP_VERSION__), so it doubles as a quick-scan "this is the build live on GH Pages today" signal. - VitePress docs site — space theme + guides folder — full
docs/rewrite with a custom theme (docs/.vitepress/theme/custom.css) matching the production app palette (--orrery-bg #04040c, gold#ffc850, teal#4ecdc4, mars#c1440e); Bebas Neue + Space Mono + Crimson Pro from Google Fonts; static starfield + radial-gradient glow on the home hero (pure CSS, no images). Navigation revised: Home / Guides (user + translator) / Decisions (TA / ADR / RFC / PRD indices) / ↗ Live App. Footer + sidebar + tables + code blocks + custom blocks re-tinted; local-search input + outline-on-right + 640 px mobile breakpoint tuned.npm run docs:buildgreen after fixing 15 dead links surfaced by the guide move.
Changed
- PWA service worker → silent auto-update —
vite.config.tsswitchesregisterType: 'prompt'to'autoUpdate'. New SW bundles install silently on the user's next navigation instead of surfacing a "new version · refresh" toast that asked the user a question they couldn't answer with context. Modern PWA default (Twitter / Slack / Discord behaviour). Trade-off: a user with the app open for hours stays on the old version until they navigate — acceptable for an explorer / docs app. Dropslayout_pwa_new_version+layout_pwa_refreshmessage keys across all 14 locales.
Fixed
/fly3D sprite-tube tip alignment — the red dot lagged on outbound and led on return becausespacecraftPos()and the in-framesnapTubeTip()lerp re-derived the spacecraft's position from the same waypoints through two independent code paths; algebraically identical, visually drifty under sustained playback. RefactoredsnapTubeTipto translate the tip cross-section directly tosc.pos × SCALE_3D(single source of truth), so the tube cone tip and the sprite are guaranteed to coincide every frame, on both arcs.- Mobile e2e regressions (hamburger drawer) — 14 i18n locale-chip smoke specs +
fleet.spec(nav exposes the FLEET link) +smoke.spec(nav bar is visible …) targeted the desktop.centernav strip, which isdisplay: noneon ≤640 px viewports since the v0.6.0 mobile-nav overhaul. Newtests/e2e/_helpers/nav.tsexposesclickNavLink()+localeChip()— viewport-aware nav navigation, and the locale-chip locator is scoped to[data-locale-picker]so it doesn't collide withbutton.chipfilter chips on screens like/fly. The remaining 2 affected suites (fleet.spec+smoke.spec) open the menu inline. /scienceCmd-K spec skipped on mobile — the Search button isdisplay: noneon ≤640 px (desktop affordance, seesrc/routes/science/+layout.svelte); the two Cmd-K specs nowtest.skip()on mobile viewports.- Visual-regression baselines skipped on non-darwin —
visual.spec.tsbaselines are committed as*-darwin.png(maintainer's machine); CI Linux looks for*-linux.pngand reports "missing baseline" on every run. Suite nowtest.skip()s on non-darwin until linux baselines are committed too. Local darwin runs still execute the assertions. /libraryaxe scan timeout in CI — 678 outbound-link rows × every axe rule exceeded the per-test 30 s playwright budget on cold Ubuntu runners (35–43 s in failing runs). Bumped to 90 s for/libraryspecifically; other a11y-pilot routes stay on the default.missions.speccount drift — Apollo 13 shipped as the 37th mission (17th Moon entry) in v0.6.0, but the spec was still asserting 36 / 16. Bumped to 37 / 17 to match.fly-render-validation3D ↔ 2D hash-invariant flake — Mariner 4, Apollo 11, and Apollo 17 occasionally failed on the first run and passed on retry. Bumped thedata-view='2d'wait from 5 s to 10 s; swapped the locator to[data-testid="fly-view-toggle"](more stable than a label regex now that the toggle row has five sibling panel-visibility buttons).- e2e workflow timeout 40 → 60 min — the suite is 23–30 min steady-state, but flaky retries plus the
/libraryaxe scan push the worst case past 40. 60 min gives 2× margin without masking a runaway hang.
Internal
@playwright/test1.59.1 → 1.60.0 — dedupplaywright-coreto a single version so svelte-check no longer sees two distinctPagetypes (was blocking CI typecheck after@axe-core/playwrightlanded and pulledplaywright-core@1.60.0).package-lock.jsonregenerated with--cpu=x64 --os=linux --include=optional— keeps the Linux-only native deps (@emnapi/core,@emnapi/runtime,esbuild@0.28.0,yaml@2.9.0) in the lockfile so GH Actions runners'npm cidoesn't reject the sync.
v0.6.0 — cislunar /fly + /fleet + landing page + Observation/Life-in-space science tabs
The cislunar release. /fly learns Moon-mission geometry — every Apollo-class free-return, Artemis hybrid free-return, Chandrayaan-3 spiral, and Chang'e LOR rendered as its own per-profile trajectory in an Earth-centred view. The /science encyclopedia grows two new tabs (Observation + Life in Space). A new top-level /fleet explorer ships. And the visit starts on a real landing page at / instead of an explore-redirect.
Added — cislunar /fly view (ADR-058)
- Per-mission cislunar trajectory machinery —
buildCislunarTrajectory()parses each Moon mission's newflight.cislunar_profile(parking orbit, TLI ∆v + C3, translunar type, lunar arrival altitude / periselene, return ∆v) and produces a typed phase sequence (parking → tli_coast → lunar_arrival → tei_coast → reentry). 17 Moon missions populated (Apollo 11/13/17 + Artemis 2/3 + Luna 9/17/24 + LRO + Clementine + Chandrayaan 1/3 + Chang'e 4/5/6 + SLIM + Blue Moon Mk1). - Earth-Centred Inertial scene at true Earth-Moon scale (
SCALE_CISLUNAR = 1/10 000) — auto-engages for any mission whosedest === 'MOON'. Phase-coloured trajectory lines, ∆v annotation sprites, real Earth + Moon textures, moon-frame group that tracks lunar drift so lunar-orbit / descent / ascent phases anchor to the Moon as it moves. - Auto-zoom across phases — camera close to Earth during parking / spiral_earth / reentry, pulled back across translunar coast, lerped in toward the Moon during lunar_orbit / lunar_flyby / descent / ascent. Mouse-wheel during a phase wins; next phase transition re-arms the lerp.
- Moon-proximity override — flyby-only profiles (Artemis II, Apollo 13) have no explicit
lunar_flybyphase, so the camera now zooms whenever the spacecraft computes to within 80 000 km of the Moon centre, regardless of phase type. - 8 science layers wired into the cislunar scene at parity with heliocentric — hover, soi, gravity, velocity, centripetal, apsides, coast, conics. SoI rings sized to Earth (924 000 km) + Moon (66 100 km). Coast preview integrates a two-body Earth-gravity prediction forward 33 h.
- Heliocentric auto-zoom (interplanetary missions) — DEPARTURE close-up on Earth → wide cruise framing on the Earth↔destination midpoint → APPROACH close-up on the live destination. Mirror sub-phases for round-trips. Tube
drawRangeround-snaps to whole segments so the sprite stays aligned with the trajectory tip under close-up zoom. - 2D cislunar fallback for the
/fly2D toggle — same per-mission geometry rendered to canvas with Earth at centre and an auto-zoom on lunar phases. - Apollo 13 added as the 37th mission — free-return flyby with aborted LOI.
Added — /science Observation + Life in Space tabs
- Observation tab (S1–S3 / issues #80 #81) — 7 sections covering Adaptive Optics · Black Holes · Coronagraphs · Interferometry · Space Photography · Spectroscopy · Wormholes. New ObservatoryShowcase strip on the space-photography section gallery imagery expanded to 96 observatory images across the fleet gallery pipeline.
- Life in Space tab (S2 / issue #80) — sections covering microgravity, radiation, IVA, EVA, lunar suits, long-duration life support, and crew-health topics. Three new suit-family sections (IVA / EVA / lunar suits) cross-link to
/fleet. /sciencenow spans 85 sections across 10 tabs (was 54 / 8). 71 hand-coded SVG diagrams (was 62) — one per section + 10 tab covers, with the fail-closed integrity gate enforcing the count on every build.- Diagram polish pass — S6 wave repaints 50+ existing diagrams across orbits / transfers / propulsion / mission-phases / porkchop / scales-time to match the latest design-system tokens (flag flips, blueprint accents).
photofield wired into section pages — high-value imagery embedded on 18 sections (NASA / ESA observatory + agency photography), all with full image-provenance coverage.
Added — /fleet explorer + space-suit category
- New top-level
/fleetroute — bill-of-materials view across the fleet (rockets, capsules, landers, rovers, orbiters, observatories) and now space-suits. Selection halos, per-planet pill colors on filters, Mars labels. - Space-suit category — 13 suit-family entries (en-US) with full provenance + i18n wave 2/3 across 12 locales + sr-Cyrl manual overlays for the 3 new suit sections. Wired into
validate-data+ schemas. Krechet placeholder + sokol-m fallbacks.linked_missionsuse real mission IDs.
Added — root / landing page (PRD-013 / UXS-013 / Issue #74)
- Real landing replacing the
/ → /explore307 redirect — hero (ORRERY96 px wordmark + tagline + two CTAs), what-is-this section, why-this-exists section, multi-paragraph guided tour, 11-card grid covering every primary nav destination +/fleet, footer block linking to GitHub / README / License / Credits / Library / Technical Authority. Long-form scrollable single column, mobile-first (375 px → 1-col cards). 49 newlanding_*keys translated to all 14 supported locales. Browser-locale auto-detection on first paint. 10 e2e tests on desktop + mobile.
Added — Dutch locale + i18n coverage
- Dutch (
nl) locale — 14th supported language (issue #72). Full UI bundle (711 keys) at 100% parity with the other 13 locales. Native name Nederlands, short tag NL, flag 🇳🇱. LocalePicker entry added between Italiano and Српски. Translations follow the ESA-NL physics/astronomy glossary; mission and agency proper nouns kept in original. - Dutch entity overlay tree — full coverage across missions / planets / sun / rockets / earth-objects / moon-sites / mars-sites / iss-modules / iss-visitors / tiangong-modules / tiangong-visitors / scenarios (161 files).
/scienceoverlay gap closed for es/de/fr/it — 14 files (history/_intro + 6 history sections + space-stations/_intro + 4 space-stations sections + mission-phases/eva + scales-time/long-duration) translated for the four EU locales that already had partial coverage. Brings es/de/fr/it from 49 → 63/sciencefiles each.iss-visitors/overlays for all 13 non-en-US locales — closes the en-US-only gap for cargo_dragon, crew_dragon, cygnus, htv_x, progress_ms, soyuz_ms, starliner. 7 files × 13 locales = 91 new files.- i18n wave 2/3 for 28 new sections + 13 suit entries across the 12 non-en-US locales.
Added — Mobile + Browser-locale ergonomics (ADR-057)
- Browser-locale URL canonicalisation (Issue #73 Gap 1) — auto-detected locales rewrite the URL to the canonical
?lang=deform viareplaceState, so bookmarks and share-links carry the locale. 10 unit + 5 e2e tests. orrery_localecookie for explicit locale overrides (Issue #73 Gap 2 / ADR-057 Accepted) — single functional cookie (SameSite=Lax, 1-year, no PII), written only on explicit LocalePicker click. Sits between URL andnavigator.languagein the resolution chain. Auto-detect paths never write the cookie.- Mobile UX overhaul — hamburger nav, collapsible
/flyHUD on narrow viewports, compact/sciencesection rail, footer-overlay improvements, per-planet pill colors. - Build version in footer —
Credits | Library | v0.6.0strip; version injected via Vitedefinefrompackage.json. - Nav wordmark polish — bumped to 36 px, vertically centred within the 52 px nav bar.
Added — Documentation + tooling
- Tech BOM generator (closes #92) —
scripts/build-tech-bom.tswritesdocs/TECH-BOM.mdlisting every npm package shipped or used at build time, with version + license. License-audited fail-closed in CI. - PRD-014 + RFC-017 — Surface Hotspots (progressive landing-site exploration).
- ADR-055, ADR-056, ADR-057, ADR-058 —
i18ncookie scope, surface-map design, locale persistence cookie scope, cislunar/flyarchitecture.
Changed
/flyleft rail consolidated — identity / navigation / flight-params / systems / spacecraft-state stack flush in one column. Top-controls bar puts FlightDirectorBanner + ScienceLayersPanel side-by-side instead of stacked vertically.- Solar / Cislunar
/flytoggle de-scoped (ADR-058 amendment) — Moon missions render exclusively in cislunar view; heliocentric Moon-mode no longer toggleable. The PiP context inset was also dropped during smoke-testing. - Mars + maps polish — selection halos on
/mars//moon, label rendering for Mars sites, drop redundant README footer link.
Fixed
- CI e2e timeout bumped 25 → 40 min for the v0.6 suite size.
apollo13.jpgsourced + suit-diagram spec-panel fixes;sokol-mplaceholder.- Tech BOM GitHub-shorthand + LICENSE URL — unblocks the deploy.
- Heliocentric tube/sprite alignment under close-up auto-zoom — round-snap fixes the visible offset.
- Artemis II cislunar zoom — Moon-proximity check now fires for hybrid-free-return profiles that skip the explicit
lunar_flybyphase.
Dependencies
- Bulk Dependabot bump — vitest 2 → 4 · svelte 5.16 → 5.55 + 4 minor.
v0.5.0 — encyclopedia + explorers + LEARN-link stewardship
The encyclopedia + explorers release. Three new primary nav routes (
/iss,/tiangong,/science), a layered "Science Lens" of live physics annotations across every 3D scene, and end-to-end outbound-link provenance discipline.
Closes the v0.5.0 milestone (#6) — Tiangong Explorer + the LEARN-link stewardship rollout — plus the Science encyclopedia (#39) and ISS Explorer (#41) bodies of work that were originally on v0.4.0 but read more cleanly here together.
/science — in-app encyclopedia (PRD-008 / RFC-011)
The headline of v0.5.0. 54 sections across 7 tabs: Orbits · Mission Phases · Planets & Bodies · Spaceflight · Space Stations · History · Space-101 landing.
- 48 hand-coded SVG diagrams (engineering blueprint style — white-on-black with teal accents)
- KaTeX server-rendered formulas — client receives static HTML, no JS math library (ADR-034)
- Right-rail navigation, Cmd-K search overlay, narrative_101 lead-ins on every section
- Cross-screen
?-chips deep-linking from/missions,/fly,/explore,/plan,/earth,/moon,/mars,/iss,/tiangongstraight to the relevant chapter
/science integration with the rest of the app:
SCIENCEtab on every detail panel (MissionPanel, PlanetPanel, SunPanel, SmallBodyPanel)- Science Lens toggle gates a layer of in-scene physics annotations across every 3D scene
- Flight Director banner on
/fly— 5-phase narration (Departure · Trans-X Injection · Cruise · Approach · Arrival), each phase deep-linking to the matching/sciencesection - Why? popovers explain individual numeric labels in context across every panel
- Mission Sandbox layered onto
/planporkchop — pin one cell, click another → ΔDEP / ΔTOF / Δ∆v compare panel
Live physics overlays — Science Layers: Eleven sub-toggleable layers behind the lens — spheres of influence, hover info cards, gravity vectors, velocity vectors, centripetal arrows, apsides + true anomaly, engine-off coast preview, conic-section family panel, microgravity axes, atmosphere shells, tidal-lock indicator, ozone holes.
Closes #39.
ISS Explorer (/iss) — PRD-010 / RFC-013
A full station-explorer route built on a shared station-geometry library:
- 32 modules (every USOS + ROS module + visiting craft) with per-module 3D pickability (raycast-driven panel open) plus hover outlines and emissive selection pulse
- Full module panel: OVERVIEW · GALLERY · TECHNICAL · ANATOMY · SCIENCE · LEARN tabs
- Per-module agency badges in the drawer
- Sun-tracking solar-array animation
- Microgravity axes lens-gated overlay (ZENITH/NADIR · PROGRADE/RETROGRADE · PORT/STARBOARD)
- Orbit-regime banner with WhyPopovers on altitude/inclination/period
- Hand-drawn ANATOMY diagrams for 9 visiting spacecraft (Crew Dragon, Soyuz MS, Cygnus, Dragon, Progress, HTV, Starliner, ATV, Shenzhou)
- 2D blueprint views (top + side projections)
Closes #41.
Tiangong Explorer (/tiangong) — PRD-011 / RFC-014
Mirror of /iss for China's Tiangong station, built on the shared station-geometry library:
- Tianhe core + Wentian + Mengtian lab modules with sun-tracking gallium-arsenide arrays
- Three docked-vehicle slots (Shenzhou, Tianzhou, plus visiting spot)
- Polished low-end fallback (auto-switch to list view on under-20 fps hardware)
- ADR-048/049/050 lock the asset pipeline, module pickability rules, and low-end fallback contract
Closes #50.
LEARN-link stewardship — ADR-051
End-to-end discipline for every outbound link in the app:
- L-A — ADR-051 + RFC-015 + audit doc (the policy)
- L-B — Per-link provenance manifest +
LinkCredit.svelte+LearnLink.svelte+ AJV validation - L-C — Agency-portal LEARN-link enrichment (non-US first; native-language priority)
- L-D — Public
/librarypage (bill-of-links across the entire app); Mission Library renamed to Mission Catalog - L-E — Outbound link-checker chained into
npm run fetchwith freshness gating
Closes #51 epic + #52 / #53 / #54 / #55 / #56.
Test infrastructure — flake-free e2e under headless WebGL
The first run of the full e2e suite after the v0.5.0 UX wave landed exposed 46 stacked failures — the previous 25-min CI window kept being cancelled by superseding pushes before ever reaching them. Categorised + fixed in 3 commits:
- 12 i18n locale tests broke when the LocalePicker added flag emojis (
🇩🇪 DEinstead ofDE) — swapped totoContainText. /missionsfilter pills + timeline collapsed by default; tests now click the strip open and the page auto-expands when filter URL params are present./planporkchop selector collided with a ScienceChip aria-label; pinned tests tocanvas.porkchop.PlanetPanelLEARN tab folded into SCIENCE — tests follow.FlightDirectorBannerinner anchor href; tests follow./iss+/tiangongcanvas-click tests replaced their flaky spiral-search with a deterministicwindow.__pickAt()test hook +canvas.click({position})(bypasses overlays).- All 8×
waitForTimeout(<magic>)replaced with deterministic readiness signals:data-objects-count/data-sites-count/data-view/data-sim-day/data-sc-phaseattributes. /iss+/tiangongperf-fallback (FPS<20 → list mode) skipped undernavigator.webdriver— software-rasterizer WebGL on GH Actions was tripping the gate.
Result: e2e job dropped from 25-min timeout to 16-min clean pass.
Stack notes
No new dependencies. Three.js still r128. SvelteKit + Paraglide-js + ajv + KaTeX (build-time only). Static export via adapter-static — still deploys to GitHub Pages with no backend.
🤖 Notes generated with Claude Code
v0.4.0 — Languages + Mars Surface Map + image credit stewardship
The internationalisation + maps + provenance release. All 12 supported locales now at 100% UI parity, full Mars Surface Map, and end-to-end image provenance discipline.
(/iss, /tiangong, and the /science encyclopedia all landed during this development window but are scoped to v0.5.0 — see the v0.5.0 release for those.)
Closes the v0.4.0 milestone (#5): #30 v0.1.10 audit cleanup, #36/#37/#38 i18n Waves 1/2/3, #40 Mars Surface Map, #44/#45 agency-first imagery, #47/#48 image credit rollout. (#39 Science and #41 ISS Explorer were originally also tagged to this milestone but are reframed under v0.5.0 in the release narrative since they form a coherent encyclopedia + explorer story together with Tiangong.)
Languages — 12 locales now fully covered
UI message bundle (684 keys) translated key-for-key across every supported locale: Spanish · French · German · Italian · Portuguese-BR · Mandarin · Japanese · Korean · Hindi · Arabic (RTL) · Russian · Serbian-Cyrillic. Locale picker shows national flags.
Closes #36 (Wave 1: fr/de/pt-BR/it) · #37 (Wave 2 CJK: zh-CN/ja/ko) · #38 (Wave 3: hi/ar-RTL/ru).
Mars Surface Map (/mars) — PRD-009 / RFC-012
A new primary nav route. Equirectangular 2D Mars map + 3D globe with surface-feature panels for landing sites, orbital probes, and major regions. Atmosphere shell layer (~120 km) lens-gated. Per-site GALLERY · TECHNICAL · LEARN tabs. Rover traverses rendered as cross-linked path overlays. 16 surface sites + 11 orbiters at ship.
Closes #40.
Image credit rollout — ADR-046 / ADR-047
End-to-end provenance discipline for every pixel in the app:
- Agency-first build-time imagery sourcing (NASA = fallback library, not the default)
- Per-image provenance manifest (auto-generated by
scripts/build-image-provenance.ts) - Public
/creditspage with all imagery + text + logo attributions - License allowlist + waivers system, fail-closed in
validate-data - Lightbox attribution on every gallery thumbnail
- Honest mixed-source footers per gallery surface
- Non-NASA agency imagery enriched via partnership-credit queries
Closes #44 (agency-first sourcing) · #45 (non-NASA enrichment) · #47 (Milestones A/B/C) · #48 (Milestone D).
/missions UX cleanup
Filter strip + timeline navigator collapsed by default for a clean grid; auto-expand when any filter URL param is present so deep links show their state. Per-mission flight params + caveat banners (RECONSTRUCTED / SPARSE / UNKNOWN). Ships at 36 missions (4 outer-catalogue additions + Artemis II + free-return concepts).
v0.1.10 audit cleanup (#30 carry-over)
Drift fixes from the v0.1.10 audit folded in here.
Tooling + infrastructure
- 4 new ADRs covering the agency-first imagery decision (ADR-046), per-image provenance manifest (ADR-047), and the diagram authoring + KaTeX patterns groundwork (ADR-034, ADR-035) used heavily in v0.5.0.
validate-datafails closed on unknown licenses and missing image provenance.npm run preflightmirrors CI step-for-step locally; pre-push hook self-installs.
Stack notes
No new dependencies. Three.js still r128. SvelteKit + Paraglide-js + ajv. Static export via adapter-static — still deploys to GitHub Pages with no backend.
🤖 Notes generated with Claude Code
v0.3.0 — heliocentric /fly + cislunar reframe + 4 new missions
Heliocentric
/fly, cislunar reframe, and four new missions (32 total).
Major /fly trajectory overhaul
transferEllipse(): true two-point Keplerian arc with the Sun at one focus, pinning both endpoints to live planet positions. Spacecraft start coincides with Earth atdep_day, rendezvous coincides with destination atarr_day— no more drift between rocket and planet.PolylineCurve3forTubeGeometry— the 3D past-tube progression now matches the spacecraft sprite exactly (no centripetal-spline drift).- Svelte 5
$effectdep-tracking fix: refs not yet defined on first run prevented state from being tracked, so marker + arc-rebuild effects silently skipped subsequent mission swaps.
Apollo-class round-trip + Moon-mode reframe
- Moon-mode is now heliocentric like Mars (Sun + Earth orbit visible, Moon orbiting Earth at exaggerated 0.15 AU).
- Camera follows live Earth, zoomed tight (50u). Sim-speed pills swap to
[0.1, 0.5, 1, 3]×for short cislunar missions. - Round-trip timeline math:
arr_day = dep + 2 * transit_daysfor crewed / sample-return so the scrubber maps cleanly across the full mission.
Four new missions (32 total)
- Artemis II (NASA, FLOWN April 2026 — the project's inspiration)
- Inspiration Mars (Tito 2013 free-return concept)
- Starship Mars Crew (SpaceX crewed Mars round-trip concept)
- Blue Moon MK1 (Blue Origin cargo lunar lander)
Other
/explorevisibility layers (PLANETS · DWARFS · COMETS · INTERSTELLAR)/exploreSIZES → REFERENCES with visual planet-size diorama/earthsatellites in real-inclination orbital planes/planrocket roster expansion + launch sites + photos/missionstrajectory preview moves into the card + FLIGHT tab/flyCAPCOM panel: taller, sticky header, events scroll independently- Non-US mission galleries via curated Wikimedia top-up
- PWA install nag suppressed, capability kept
- Dev-server:
vite fs.allow ['static']+ scenario probe gating
🤖 Notes back-filled with Claude Code