Decisions

ADR-058: Platform UI adopts five modes — Home / Ship / Operate / Infra / Experiment

ADR-054 (shipped earlier on 2026-04-22) split the Platform UI's single-page mode dispatcher into three dedicated routes — `/ship`, `/operate`, `/experiment` — and reserved `/` for a Gyrum.ai identity page. The Designer…

#058

ADR-058: Platform UI adopts five modes — Home / Ship / Operate / Infra / Experiment

Status: Accepted Date: 2026-04-22 Extends: ADR-054 (three-mode-routes-supersede-ai-frontend-adr-003)

Context

ADR-054 (shipped earlier on 2026-04-22) split the Platform UI's single-page mode dispatcher into three dedicated routes — /ship, /operate, /experiment — and reserved / for a Gyrum.ai identity page. The Designer agent shipped that change under PRs #94–#97 (ai-frontend) with a persistent 216px left rail that hosted the five platform actions (Build MVP · Pipelines · Operators · Experiments · Assets) statically across every route.

Two things surfaced as that landed in the hands of the operator:

  1. The rail doesn't belong to the homepage. On /ship, /operate, /experiment the five platform-action links compete with the mode's own content for attention. They are a / concern (start something, go somewhere), not a mode-home concern (look at what's happening).
  2. Infra is not a section, it's a job. /infra/* already had its own grouped sidebar — Overview / Runtime / Code / Delivery / Findings — parallel to the five-action rail. Two nav surfaces claimed the same left column. Operators treated "what's the state of the platform?" as a first-class mode, not a section.

The UX-redesign session on 2026-04-22 resolved both by promoting Home (the homepage) and Infra (the platform-state jobs) to first-class modes alongside Ship / Operate / Experiment. The mode switcher becomes a five-button pill; the sidebar becomes mode-dependent; the infra layout's existing nav is hoisted to a shared module so it powers the mode-sidebar directly (no duplication).

Decision

The Platform UI has five modes, each with a dedicated top-level route, its own palette, and its own sidebar content:

Mode Shortcut Route Sidebar Palette
Home ⌘1 / Build MVP · Pipelines · Operators · Experiments · Assets Calm slate (#334155)
Ship ⌘2 /ship Placeholder — "No navigation yet" Green (#15803d)
Operate ⌘3 /operate Placeholder — "No navigation yet" Alert blue (#1d4ed8)
Infra ⌘4 /infra Grouped Overview / Runtime / Code / Delivery Slate-600 (#475569)
Experiment ⌘5 /experiment Placeholder — "No navigation yet" Warm amber (#b45309)

Specific decisions:

  1. URL is the source of truth for the active mode. Landing on /infra/hetzner yields Infra mode regardless of what localStorage.gyrum.mode says. The $effect in the root layout reads $page.url.pathname through a pure modeFromPath(pathname) helper and calls modeStore.set(derived) whenever they disagree. localStorage persists the last-visited mode as a convenience default for the initial landing; the URL then takes over.
  2. Sidebar is mode-dependent. SideRail.svelte renders different content per mode. Home renders $lib/nav/home-nav.ts, Infra renders $lib/nav/infra-nav.ts; the three others render a one-line placeholder ("No navigation yet — mode content below.") that reserves the 216px column so the layout does not shift when real content lands.
  3. Infra nav lives in one place. src/routes/infra/+layout.svelte stops rendering its own sidebar; the mode-sidebar owns it. The shared module $lib/nav/infra-nav.ts is imported by both, so adding a new Infra surface edits one file.
  4. Keyboard shortcuts cover all five modes. Cmd+1..5 (and Ctrl+ variants) map to Home/Ship/Operate/Infra/Experiment via a single SHORTCUT_TO_MODE table — one source of truth for the keyboard and the switcher label ordering.
  5. Home is the default. :root with no data-mode (SSR, first paint) binds to the Home palette — matching "you arrive at /, the homepage is calm and neutral".

Consequences

Easier.

  • The sidebar is no longer a fifth source of noise on mode-home pages. Ship/Operate/Experiment pages render against a calm reserved column until their sidebars are designed.
  • /infra gets a real mode treatment — palette, shortcut, sidebar all feel first-class rather than "the section I tabbed into".
  • One source of truth for Infra nav — the mode-sidebar and /infra/+layout.svelte can't drift.
  • Deep-linking works for every mode: /, /ship, /operate, /infra, /experiment are all legitimate links.

Harder.

  • Anyone who memorised Cmd+1=Ship from the ADR-003 era now finds Cmd+1=Home. The shortcut is printed on every switcher button (⌘1..⌘5) so the mapping is discoverable without a shortcut-help overlay.
  • Mode gained two values, so any consumer of the type needs to handle 'home' and 'infra'. In practice only the mode-store, the switcher, the FOUC script, and mode-tokens.css touch Mode directly.

What we sign up to maintain.

  • The 5-mode contract: any new mode earns its own top-level route, palette, and sidebar. The MODE_HOMES table is the contract.
  • Ship / Operate / Experiment sidebar designs are genuinely open — until they exist, the placeholder is the UI. We avoid filling the column with "nav coming soon" lorem ipsum; a single calm line is enough.
  • modeFromPath stays pure and reversible. If a new section (e.g. /admin) needs a mode affiliation, it is added here — never by sniffing the URL inside a component.

Alternatives considered

  • Amend ADR-054 in place. Considered and rejected: ADR-054's three-mode story is complete and correct as of 2026-04-22 morning. The five-mode model is a new decision made the same afternoon based on UX feedback — cleaner as its own ADR that extends 054 than as an edit that rewrites history.
  • Keep the rail static and add Home/Infra as sections. Rejected: the rail-as-universal-chrome pattern was what made the post-054 layout feel crowded. Sections share chrome; modes own it.
  • Mode = palette only, sidebar stays shared. Tempting but loses the Infra win: the infra layout already had its own sidebar — collapsing it into a shared surface meant either duplicating groups or breaking the Infra UX. Promoting Infra to a mode lets its existing nav become the mode's sidebar.
  • Build mode-specific sidebars for Ship/Operate/Experiment now. Rejected as scope-creep: the sidebars aren't designed yet. Reserving the column with a placeholder and landing the wiring today is the lowest-risk path; the three sidebars ship in follow-up PRs when design catches up.

Related ADRs

  • Extends: ADR-054 (three-mode routes supersede ai-frontend ADR-003) — same route-per-mode contract, just widened from 3 to 5.
  • Supersedes by extension: ai-frontend ADR-003 (three-modes-platform-ui) — already superseded by ADR-054; this ADR continues that trajectory.

Extended by

Later ADRs that build on this one's five-mode contract:

  • ADR-060 — Infra mode (the fourth of the five modes) is the canonical home for catalog viewers, and project-page "Catalog" tabs are a direct consequence of ADR-059 composing on top of this five-mode shell.
  • ADR-062 — the design system's mode-tinting rules are defined against the five palettes established here; gyrum-ui inherits the mode tokens from this ADR rather than redefining them.
  • ADR-063 — the tenant chooser sits next to the mode chooser in the Platform UI chrome, extending this ADR's mode-pill contract to a second orthogonal axis (mode × tenant).

Ship PRs: ai-frontend #98 (Mode type), #99 (SideRail), #100 (palettes), #101 (e2e + this ADR).