PRD-022 · Tier-3 panorama as spatial-context exhibit — honest source, captions, annotations, multi-pano, cross-link
Status · Draft Date · 2026-05-31 Owner · Marko Closes into · ADR-074 (technical schema + renderer decisions), #286 (issue), Phases 1-4 implementation slices Slice gate · None — Phase 0 (this doc + ADR-074 + visual mockups) gates Phase 1+2 code work
Why this is a PRD. The change spans three subsystems: the asset pipeline (re-source higher-res NASA panoramas, kill procedural sky, fix ragged nadir), the data schema (per-panorama metadata + yaw/pitch annotations + multi-pano set + traverse cross-link), and the renderer (
hotspot-tier3-skybox.ts+ new HUD overlays for caption / compass / annotation sprites / free-pitch + microcopy). Plus editorial curation work for 7 marquee sites in Phase 4. One owner doc, one design lens, one source of truth on the META question.
What
The Tier-3 panorama view today is the lowest-quality felt experience in Orrery. Users click "Stand at site" expecting a NASA-grade panorama and get a 4 K equirectangular JPEG with procedural orange sky (Mars), ragged stitched nadir (Perseverance), grey fill block (Apollo 11), no caption, no compass, no annotations, ±20° pitch clamp. The visceral read is "low-effort Street View embed," not "I'm standing on the surface of Mars."
This PRD locks the strategy for the redesign, scoped to:
- The 7 marquee sites in Phase 1+2 (Apollo 11, Apollo 17, Curiosity, Perseverance, Chang'e 4, Chandrayaan-3, Mars 3 — see §"Marquee 7 picks" below for the rationale)
- The remaining 21 panoramas in a Phase 5 follow-up slice (likely v0.8)
- The renderer + HUD + schema + mockups for all marquee sites in this initiative, even though some annotation curation lands in Phase 4
/explore, /earth, base-texture LOD are out of scope (separate initiatives — see #287 and PRD-021 respectively).
The META decision
The original issue (#286) flagged a meta-question before any of the 8 specific improvements:
Should we compete with NASA on raw panorama quality, or lean into spatial context as the differentiator?
This PRD commits to spatial context. Three reasons:
- NASA wins on raw quality forever. Their imagery library + editorial muscle is the whole point of being NASA. The 28-panorama corpus cannot meaningfully out-imagery
mars.nasa.govor the Apollo Lunar Surface Journal. Trying is a category mistake. - The differentiator is putting each image in its place. Orrery already does this for missions ↔ fleet ↔ launchpads ↔ traverse stops. The panorama as "one node in the mission-experience graph" is the same pattern, applied to imagery: "this is sol 46 of Perseverance's mission; here's where Perseverance was on Mars at that moment; here's the traverse path that led to this spot; here's the rover's selfie at this site; here's the next sol's view."
- The cheap polish items serve both readings. Captions, compass, honest sky, annotations all express spatial-context AND fix the dishonest parts of the existing assets. Same work serves both goals.
This commitment downgrades #1 (16 K tile pyramids, weeks of asset pipeline work) from "biggest single quality win" to "asset polish, do it where it matters." It upgrades #2 (metadata) + #3 (annotations) + #4 (compass) + #5 (honest sky) to the design center.
Why now
Two signals converged:
- #283 (Surface Hotspots v2) shipped May 2026. The Tier-3 panorama is the deepest zoom level in that hierarchy and the only one that didn't receive the v2 redesign treatment. Closing the loop on the surface-hotspots experience requires closing the loop on the panorama.
- Marko's review of
static/images/hotspots/<body>/<site>/tier3-pan.jpgagainst NASA reference (Perseverance selfie, Mars Trek, Apollo LSJ pans) surfaced a felt-quality gap that's visible in seconds. The current panoramas are good enough to ship but visibly the weakest link.
The post-#283 panel-imagery work (Path A — Mars galleries seeded in commit d37a98375) was the warm-up. This is the structural fix.
Users
Same audience as /moon and /mars:
- Curious adults who want to be at the landing site, not be shown a picture of the landing site.
- Educators using the panorama as anchor for a mission narrative ("here's where Apollo 11 landed; pan around; here's where Buzz set up the seismograph").
- Mission-history readers who want to ground a panorama in time (which sol, which experiment, which discovery).
Goals + non-goals
Goals:
- Honest panorama — every visible region either real photographic data, or clearly marked as synthetic/missing. No procedural orange sky on Mars; no grey fill block on Apollo 11.
- Caption inline — sol/date/instrument/credit/caption text overlay visible on entry, dismissible.
- Compass orientation aid — small N-arrow on the HUD, rotating with yaw.
- Free pitch — drop ±20° clamp to ±60° (or full ±90° with explicit "no data here" microcopy in unphotographed regions).
- Clickable feature annotations — yaw/pitch sprites with caption cards naming named terrain features per marquee site.
- Multiple panoramas per site — cycle UI for Curiosity / Perseverance (multi-sol coverage); single-pano sites unaffected.
- Cross-link — panorama links to traverse-stop (when one exists at this location) + fleet entry + audio episode (when any exists).
- Marquee 7 first — all features land for 7 sites before scaling to all 28.
- i18n — caption + annotation strings localised in 14 locales (paraglide).
- Mobile + reduced-motion + a11y unaffected — every feature works on touch, respects
prefers-reduced-motion, has sr-only equivalents.
Non-goals:
- Competing with NASA on raw image quality. 16 K tile pyramids deferred to a much later follow-up if signal warrants. The 4 K → 8 K source upgrade for marquee 7 is in scope (modest pipeline work, big visible win); 16 K + progressive tiles is not.
- VR / WebXR mode. Future possibility; not this initiative.
- All 28 panoramas at once. Marquee 7 first; rest as follow-up slice.
- Auto-generation of annotations. Annotation curation is editorial (5-10 named features per site); the schema supports it but the content is human-curated, not vision-API-extracted.
- Stitching repair of source panoramas. If NASA published seams + prism artifacts, we honour them as historical record. Where re-sourcing yields a cleaner master, we use that; otherwise we caption the artifact honestly ("Hasselblad frame edges + chromatic stitching seam visible at LM — original Apollo 11 panorama published with these artifacts").
Approach
Locked by ADR-074. Summary:
Three layered concerns
Layer A — Asset honesty (Phase 1)
For each marquee site, re-evaluate the source panorama:
- If the existing 4096 × 2048 JPEG has procedural fill (e.g., Perseverance orange sky), re-source from NASA at higher resolution OR alpha-out the synthetic region + replace with a synthetic-pattern fill (light dotted graticule) so it reads as "not photographed."
- If the existing JPEG has honest content (Apollo 11 black sky), keep as-is.
- If the existing JPEG has ragged nadir, decide per-site: keep the rover-deck pass-through (honest), OR replace with a synthetic-pattern fill + microcopy.
- Higher-res re-source where available — 8 K source for Curiosity / Perseverance (NASA publishes 8 K Mastcam-Z pans regularly), keep 4 K for Apollo (8 K masters rarely surface for Apollo pans without ALSJ-style hand-stitching that's out of scope).
Layer B — Schema + renderer + HUD (Phase 2)
Schema extensions on the surface-hotspots entry (existing hotspot_tier3_panorama: string becomes the default-URL fallback; new sidecar fields layered on top):
{
"id": "perseverance",
"hotspot_tier3_panorama": "/images/hotspots/mars/perseverance/tier3-pan.jpg", // existing
"panorama_metadata": {
"sol": 46,
"date": "2021-04-06",
"instrument": "Mastcam-Z",
"caption": "Jezero Crater floor with sample tubes deposited at Three Forks depot. Ingenuity helicopter visible right.",
"credit_team": "NASA/JPL-Caltech/ASU",
"nasa_id": "PIA24906",
"real_extent_pct_vertical": 35,
"synthetic_regions": ["sky_above_+15deg"] // pitch ranges of synthetic / no-data regions
},
"panorama_annotations": [
{
"id": "ingenuity",
"yaw_deg": 80,
"pitch_deg": -5,
"label": "Ingenuity helicopter",
"body": "First powered flight on another planet — Apr 19, 2021"
}
],
"panorama_set": [
{ "id": "sol-46", "url": "...", "metadata": {...}, "annotations": [...], "default": true },
{ "id": "sol-1023", "url": "...", "metadata": {...}, "annotations": [...] }
],
"traverse_stop_link": "stop-3"
}Renderer changes in src/lib/hotspot-tier3-skybox.ts:
- Drop the ±20° pitch clamp (default to ±60°, opt-in to ±90° per-site)
- Add annotation sprite rendering inside the skybox sphere (3D Sprite at distance ≈ 80 in yaw/pitch direction)
- Add compass-yaw readout for HUD consumption
New HUD components (src/lib/components/panorama-*.svelte):
PanoramaCaptionOverlay.svelte— bottom-left, fades on entry, dismissiblePanoramaCompassRose.svelte— top-right, rotates with yaw, N-arrow visiblePanoramaAnnotationCard.svelte— caption card next to clicked annotation spritePanoramaCycler.svelte— left/right arrows for multi-pano sitesPanoramaCrossLink.svelte— caption-bar bottom-right with "this stop on the traverse" / "fleet entry" / "audio episode" links
Layer C — Curation (Phase 4, parallel)
For each marquee site:
- 5-10 named-feature annotations authored against the existing pano (Mt. Sharp, Vera Rubin Ridge, US flag, LM Eagle, Yutu rover tracks, Vikram lander, Mars 3 capsule horizon, etc.)
- Multi-pano selection for Curiosity (e.g., sol 1, sol 1000, sol 3573 Mt. Sharp climb) + Perseverance (sol 1, sol 46 selfie, sol 380 sample depot)
- Honest provenance pass — flag synthetic regions in metadata for honest-microcopy rendering
Marquee 7 picks
Balancing global-program representation (Marko's "celebrate global space programs" principle) with narrative weight:
| Mission | Body | Agency | Year | Why marquee |
|---|---|---|---|---|
| Apollo 11 | Moon | NASA | 1969 | First lunar landing — iconic |
| Apollo 17 | Moon | NASA | 1972 | Last lunar landing, science apex |
| Curiosity | Mars | NASA | 2012– | Longest-running Mars rover |
| Perseverance | Mars | NASA | 2021– | Latest tech + Ingenuity selfie (the trigger reference) |
| Chang'e 4 | Moon | CNSA | 2019 | First lunar farside landing |
| Chandrayaan-3 | Moon | ISRO | 2023 | First south-pole lunar landing |
| Mars 3 | Mars | USSR | 1971 | First Mars soft landing |
4 NASA + 1 CNSA + 1 ISRO + 1 Soviet. Each non-NASA entry is a "historic first." Bias was: at least one global-first per other agency that has a landed-surface mission with a panorama.
Open question — alternates: SLIM (JAXA, 2024) could swap in for Apollo 17, giving 3-3 NASA/non-NASA balance. Decision deferred to Marko's review of Phase 0 mockups.
Phases
Phase 0 — Foundation (1-2 sessions)
- This PRD
- ADR-074 (schema + renderer technical decisions)
- Schematic SVG mockups via
scripts/mockups/render-panorama-redesign.mjs(Playwright-rendered HTML/SVG over current panorama backgrounds) — 8 frames: 7 per-site target states + 1 cross-link / "this is sol 46" exhibit-mode frame - Update #286 with linked slice plan
- Gate: Marko's sign-off on mockups + this PRD before any code
Phase 1 — Asset honesty (1-2 weeks, partly parallel with Phase 2)
- 1A re-source higher-res panoramas where available (Curiosity / Perseverance 8 K; Apollo / Chang'e / Chandrayaan / Mars 3 keep current)
- 1B Mars sky: alpha-out procedural orange-gradient + replace with synthetic-pattern fill + caption microcopy "this region above the photographed horizon"
- 1C Nadir cleanup: per-site decision (keep rover-deck pass-through, OR synthetic-fill + microcopy)
- 1D Workbox/SW cache audit for new sizes
- 1E (deferred / optional) Tile pyramid pipeline + progressive loader — only ship if Phase 1A re-source moves into the 16 K range; otherwise stays as a Phase 5 candidate
Phase 2 — Spatial-context UX (3-4 weeks, interleaved with Phase 1)
- 2A Schema extensions land (per ADR-074);
validate-dataupdated - 2B
PanoramaCaptionOverlay.svelte+ metadata wiring - 2C
PanoramaCompassRose.svelte+ yaw readout from skybox handle - 2D Free pitch (drop ±20° clamp; honest microcopy on synthetic regions)
- 2E
PanoramaAnnotationCard.svelte+ 3D sprite rendering inhotspot-tier3-skybox.ts - 2F
PanoramaCycler.svelte+ multi-panopanorama_setwiring - 2G
PanoramaCrossLink.svelte+ traverse-stop / fleet-entry / audio-episode cross-link UI
Phase 3 — Polish + share (1-2 weeks)
- 3A Fullscreen toggle (F key + button) —
requestFullscreenAPI - 3B Deep-link share
?site=&pano=&yaw=&pitch=— URL params restore exact view - 3C Auto-tour mode — "play tour" auto-pans through annotations with caption-card hand-off
- 3D Mobile e2e + 14-locale i18n
- 3E Reduced-motion + a11y review + sr-only walkthrough
Phase 4 — Curation (continuous, parallel with Phases 1-3)
- 4A Author 5-10 annotations per marquee site
- 4B Multi-pano set curation for Curiosity / Perseverance
- 4C Honest-provenance pass — flag synthetic regions
Phase 5 — Scale-out (v0.8 follow-up issue)
- Same treatment for the remaining 21 panoramas
- Filed as separate issue, gated on Phase 4 completion
Success criteria
- Open
/mars?site=perseverance→ "Stand at site" → caption visible bottom-left within 1 s of skybox entry, compass top-right, annotations clickable, pitch free to ±60°. - No procedural orange sky visible on Perseverance, Curiosity, or any Mars marquee site.
- Apollo 11 panorama's grey-fill nadir replaced with honest synthetic-pattern + microcopy.
- Cycle through 2-3 panoramas on Curiosity (sol 1, sol N, sol M).
- Cross-link from panorama to traverse stop or fleet entry where data exists.
- Mobile e2e green: enter panorama, drag-orbit, tap annotation, see caption card, dismiss, exit.
- 14-locale screenshots show caption + annotation labels in target language.
- a11y: screen reader announces caption + annotations on entry; arrow keys navigate annotations.
validate-datapasses with new schema fields enforced.- Image-provenance.json carries entries for any re-sourced or new panorama assets.
Out of scope (explicitly)
- 16 K tile pyramid pipeline (defer to signal)
- VR / WebXR mode
- Vision-API-generated annotations (curation is editorial)
- Stitch repair of historical panoramas (honour the published artifact)
- Animated panorama playback / time-lapse (separate initiative if ever)
- All 28 panoramas in this initiative — 7 marquee first, rest in v0.8 follow-up
Anti-success criteria — what failure looks like
- Captions read as boilerplate ("Mars surface — NASA/JPL") instead of being grounded in sol/date/instrument.
- Annotations are decorative (no real terrain anchors) or auto-extracted (vision-API hallucination).
- Sky-honesty pass replaces one form of dishonesty (procedural gradient) with another (a fake "stars at horizon" sky that the source doesn't have).
- Cross-link UI exists but no marquee site has linked traverse-stop / fleet / episode data → exhibit feels empty.
- The redesign ships only on Apollo 11 + Curiosity + Perseverance, leaving Chang'e 4 / Chandrayaan-3 / Mars 3 with the old experience → "celebrate global space programs" principle broken.
References
- Issue: #286
- Related: closed #283 (Surface Hotspots v2 epic — ADR-061 / ADR-062 / ADR-072)
- Related: PRD-021 / ADR-073 (Surface texture LOD — orthogonal, different layer)
- Related: #287 (
/explore4K planet textures — separate initiative) - Trigger reference: https://science.nasa.gov/resource/perseverances-selfie-with-ingenuity/ (still photograph, not a panorama, but the image-presentation gap is what prompted this)
- NASA reference patterns: Mars Trek, eyes.nasa.gov Mastcam-Z viewers, Apollo Lunar Surface Journal pan archive