Skip to content

RFC-004 — Mission URL sharing: serialisation, back-button behaviour

Status · Decided TA anchor · §components/router · §components/fly-screen · §components/missions-screen Closed by · ADR-024 (2026-04-29) Why this is an RFC · The fly and missions screens support URL-encoded state. What exactly is encoded, what happens on back navigation, and what's out of scope for v1 are open questions with real trade-offs.

The question

Two screens support URL params:

  1. /fly?mission=curiosity — loads a specific mission arc
  2. /missions?dest=MARS — opens library with filter applied

Open questions: what state is encoded, how does back-button work, what stays out of scope for v1?

Use cases

  • "FLY THIS MISSION" in mission library navigates to /fly?mission=curiosity
  • Shared link opens directly to a specific mission's arc
  • User presses back from fly screen — returns to missions with filter intact
  • /missions?dest=MARS&status=ACTIVE opens with both filters applied

Goals

  • Shared links work without session state
  • Back button feels natural
  • Params are human-readable in the URL
  • Forward-compatible — adding params doesn't break old links

Constraints

From ADR-013: History API routing via SvelteKit. Params in the query string of the URL (/fly?mission=id). URLSearchParams handles parsing; $page.url.searchParams exposes them in Svelte components.

Proposed approach

Encoded state:

  • Fly screen: ?mission=[id] — mission ID. Absent = default ORRERY-1 scenario.
  • Missions screen: ?dest=[MARS|MOON] and ?status=[ACTIVE|FLOWN|PLANNED]. Combinable: ?dest=MARS&status=ACTIVE.
  • Nothing else encoded in v1 (porkchop range, camera angle, simulation time all reset on navigation).

Back button: router.navigate() pushes to hash history. Back/forward works naturally within session.

Link generation: "FLY THIS MISSION" calls router.navigate('fly', { mission: id })/fly?mission=id.

Alternatives considered

Encode simulation time in fly URL (?mission=curiosity&met=180) — allows sharing a moment in the trajectory. Adds initialisation complexity (fast-forward to encoded time). Deferred to v2.

Encode porkchop range in plan URL — useful for sharing a launch window analysis. Deferred to v2.

No URL params — breaks the "share this mission" use case. Rejected.

Trade-offs

v1 encodes mission ID and library filters only. Camera, simulation time, and porkchop configuration are not shared. This is an explicit scope decision.

Open questions

  1. Should ?mission=invalid-id fall back to ORRERY-1 or show an error state?
  2. Should filter combinations be bookmarkable beyond the two proposed params?
  3. Should /fly?mission=curiosity&met=180 be supported for deep-linking to a mission moment?

Closing evidence

/fly?mission=curiosity loads Curiosity's arc. /missions?dest=MARS opens Mars filter. Back button returns to previous filtered state. Available at Slice 4 gate.

How this closes

One ADR: URL encoding contract for mission and filter params.

Orrery — architecture documentation · MIT · No tracking