Skip to content

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:

  1. 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.gov or the Apollo Lunar Surface Journal. Trying is a category mistake.
  2. 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."
  3. 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:

  1. #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.
  2. Marko's review of static/images/hotspots/<body>/<site>/tier3-pan.jpg against 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):

jsonc
{
  "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, dismissible
  • PanoramaCompassRose.svelte — top-right, rotates with yaw, N-arrow visible
  • PanoramaAnnotationCard.svelte — caption card next to clicked annotation sprite
  • PanoramaCycler.svelte — left/right arrows for multi-pano sites
  • PanoramaCrossLink.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:

MissionBodyAgencyYearWhy marquee
Apollo 11MoonNASA1969First lunar landing — iconic
Apollo 17MoonNASA1972Last lunar landing, science apex
CuriosityMarsNASA2012–Longest-running Mars rover
PerseveranceMarsNASA2021–Latest tech + Ingenuity selfie (the trigger reference)
Chang'e 4MoonCNSA2019First lunar farside landing
Chandrayaan-3MoonISRO2023First south-pole lunar landing
Mars 3MarsUSSR1971First 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-data updated
  • 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 in hotspot-tier3-skybox.ts
  • 2F PanoramaCycler.svelte + multi-pano panorama_set wiring
  • 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) — requestFullscreen API
  • 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-data passes 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 (/explore 4K 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

Orrery — architecture documentation · MIT · No tracking