# Design System — ReverbCode > Source of truth for the ReverbCode desktop UI (Electron + React 19 + Tailwind v4 > > - Radix/shadcn + xterm, in `frontend/src/renderer`). Read this before any visual > or UI change. Created by `/design-consultation` on 2026-06-09. ## ⚠️ Design direction — clone agent-orchestrator verbatim (SUPERSEDES emdash · 2026-06-10) By explicit user decision (2026-06-10), the renderer **clones the agent-orchestrator web app verbatim** in looks and design. This **supersedes the "match emdash" direction** documented in _Aesthetic Direction_ and the palette sections below — where they conflict, **agent-orchestrator wins**. Do not re-flag "this doesn't match emdash" in QA/review; flag divergence from **agent-orchestrator**. - **Reference (the user's own app):** `~/Projects/agent-orchestrator/packages/web/src` — `app/globals.css`, `app/mc-board.css`, `app/mc-sidebar.css`, `components/{ProjectSidebar,Dashboard,SessionCard,SessionDetailHeader,SessionInspector,StatusBadge}.tsx`. - **Palette (live in `frontend/src/renderer/styles.css` `:root`):** `--bg #0a0b0d`, `--bg-1 #15171b`, `--fg #f4f5f7`, `--fg-muted #9ba1aa`, `--fg-passive #646a73`, hairline white-alpha borders, accent `--accent #4d8dff`; status: working=orange `#f59f4c`, needs-you=amber `#e8c14a`, mergeable=green `#74b98a`, fail=red `#ef6b6b`. The sidebar rail is the cooler `#08090b`. - **Cloned surfaces:** the four-column gradient kanban board, the `ProjectSidebar` (brand + project disclosure + nested session rows + Settings menu footer), the session topbar (Kanban back button + identity + breathing `StatusBadge` pill), and the shared `DashboardTopbar`/`DashboardSubhead` chrome (Coding/Reviews tabs · "N working" pill · subhead) reused across board/review/PR/settings. - **Build with shadcn primitives** where a component fits (`components/ui/*`: dropdown-menu, select, card, table, tooltip, …); agent-orchestrator's own hand-rolled CSS components are structure/behaviour reference only. - The one carried-over divergence still holds: the **accent is refined blue**, and the **terminal keeps its own palette**. Everything else tracks agent-orchestrator. - **Approved divergence (2026-06-10):** on macOS, a titlebar cluster (sidebar toggle + back/forward history arrows, `TitlebarNav`) sits beside the traffic lights, VS Code-style — the web reference has no window chrome, so no analogue exists. - **Approved divergence (2026-06-10):** the session inspector rail is fully collapsible, built on the shadcn resizable primitive (`pnpm dlx shadcn add resizable`, react-resizable-panels v4 `collapsible` panel + imperative API, user-requested). The panel animates to 0% via a flex-grow transition while the content keeps a stable min-width (yyork-style, no mid-animation reflow). Toggled by a `PanelRight` icon button in the session topbar and ⌘⇧B; open state + split width persist. The AO reference keeps the rail always visible. - **Approved divergence (2026-06-12):** the shell topbar spans the full window width and the sidebar is pinned below it (`top-14`), so the sidebar's right border stops at the header instead of cutting through the macOS traffic-light strip (user-requested). The AO reference keeps a full-height sidebar with the header beside it. On macOS the header always pads past the lights + TitlebarNav cluster (`.is-under-titlebar-nav`, 180px). ## Product Context - **What this is:** ReverbCode is an Electron desktop app for supervising many parallel AI coding-agent sessions, backed by a Go daemon (`backend/`). The `ao` CLI is the thin client over the same daemon. - **Who it's for:** professional software engineers running multiple coding agents at once who need to delegate, watch, intervene, and ship PRs. - **Space/peers:** agent orchestration / parallel-agent desktop tools. Closest peers: **emdash** (the primary design reference), **PostHog Code**, Conductor. - **Project type:** dark-mode-primary desktop app; terminal-dense; keyboard-driven; runs all day. - **The one memorable thing:** leverage and speed — "I'm more in control here than babysitting N terminal tabs myself." ### Product flow (what the UI must serve) ReverbCode is **orchestrator-led**, which is the one thing that differs from emdash (a flat list of independent sessions). Grounded in the daemon (`backend/internal/session_manager/manager.go`, `docs/architecture.md`): - A **Project** is a registered git repo. - Per project there is **one active Orchestrator** session plus **N Worker** sessions. Both are the same underlying "session" (durable facts: `activity_state`, `is_terminated`, PR facts); they differ only by `Kind` (`KindOrchestrator` vs the default worker). A project may run the orchestrator on a different agent than its workers. - The **Orchestrator is the human-facing coordinator**: you talk to it; it spawns workers (`ao spawn`), messages them (`ao send`), tracks progress, and synthesizes results. It avoids implementing unless necessary. - A **Worker is a normal agent session** — nothing special-cased. It runs one focused task in an isolated git worktree + branch, with the agent CLI in a terminal as the conversation, producing a diff → commit/push → PR. It escalates to the orchestrator only for true blockers or cross-session coordination. - The daemon **observes** runtime + PR/CI/review facts and **derives** display status at read time: `working`, `needs_input`, `ci_failed`, `changes_requested`, `mergeable`, `approved`, `review_pending`, `pr_open`, `idle`, `terminated`, `merged`. Never store display status; keep session facts small. ## Aesthetic Direction > **Superseded (2026-06-10):** see the _Design direction — clone agent-orchestrator > verbatim_ banner at the top. The emdash framing below is retained for history; the > live look tracks agent-orchestrator (same flat near-black / hairline family, so most > of this still reads true). - **Direction:** match **emdash** exactly — flat, near-black, hairline-bordered, utilitarian. Industrial control surface, calm chrome, the terminal as the center of gravity. - **Decoration level:** minimal. Type + 1px hairlines do all the work. No gradients, glow, blobs, or emoji. - **Mood:** low-glare, dense, keyboard-native; signal-over-noise. - **Reference:** [emdash](https://github.com/generalaction/emdash) (primary, visual + structural), [PostHog Code](https://github.com/PostHog/code) (secondary). Tokens below were extracted from emdash's `src/renderer/index.css`. - **Deliberate tradeoff:** to _be_ emdash, we use the **system font stack** (not a custom typeface) and emdash's neutral palette. We diverge in exactly one place: the accent is ReverbCode's **refined blue**, not emdash's jade green. The terminal keeps green (it is the agent CLI). ## Typography System fonts only, like emdash — no custom/Google fonts, zero font payload. - **UI / body / display:** `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Helvetica Neue", sans-serif` (San Francisco on macOS). - **Mono / terminal / code / eyebrow labels:** `Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`. - **Eyebrow labels** (section titles, dialog titles, the rail "PROJECTS" header): mono, **uppercase**, `letter-spacing: .12–.14em`, `--foreground-passive`. - **Scale:** 14px base UI / sidebar (`text-sm`, weight 400) · 12px secondary + labels (`text-xs`) · 13px code/mono/terminal · 11px tiny · 10px micro + badges · 9px sidebar badge label. Buttons are `font-normal` (400), not bold. ## Color emdash's flat Radix-neutral near-black ramp carries the whole interface; color is rare and meaningful. Values are sRGB approximations of emdash's `color(display-p3 …)` tokens. ### Dark (primary) | Role | Hex | | ------------------------------------ | --------------- | | `--bg` canvas | `#111111` | | `--bg-1` surface | `#191919` | | `--bg-2` raised / hover / active row | `#222222` | | `--bg-3` | `#2a2a2a` | | `--fg` text | `#eeeeee` | | `--fg-muted` | `#b4b4b4` | | `--fg-passive` | `#6e6e6e` | | `--border` hairline | `#3a3a3a` | | `--border-1` | `#484848` | | **`--accent` (blue)** | **`#5b9dff`** | | `--needs-you` / in-progress (amber) | `#ffcc4a` | | `--success` / mergeable (green) | `#6cb16c` | | terminal green | `#7bd88f` | | `--error` (red) | `#d4544f` | | text selection | `#3f8ef7` @ 35% | | terminal bg | `#161616` | ### Light (supported, not primary) | Role | Hex | | ------------------------- | --------------------------------- | | canvas / surface / raised | `#fcfcfc` / `#ffffff` / `#ededee` | | text / muted / passive | `#1a1a1a` / `#666666` / `#9a9a9a` | | border | `#e3e3e5` | | accent (blue) | `#2563eb` | | amber / green / red | `#9a6b00` / `#1a7f37` / `#c0392b` | ### Accent rules - **Blue** = the live edge only: primary buttons, the active/selected session, focus rings. Never decorative. - **Amber** = an agent needs you (blocked / `needs_input` / `review_pending`). - **Green** = `mergeable`/success and terminal/agent CLI text. - **Red** = `ci_failed` / destructive. - These map 1:1 to the daemon's derived statuses. ### Status indicator (no text badges) Session status is a single ~14px glyph in one fixed slot, never a text pill/badge: - **Working / active** → an animated spinner (accent). - **Has an open PR** → a PR icon, tinted by PR state: mergeable/approved green, `ci_failed` red, review/`changes_requested` amber, plain `pr_open` muted. - **Otherwise** → a filled dot: `needs_input` amber (pulsing), idle/done muted gray. Precedence: **working spinner > PR icon > dot**. Implemented as `StatusGlyph` in `components/SideRail.tsx`; used in the orchestrator's Workers list. (Worker rows in the left rail stay name-only — no glyph.) ## Spacing - **Base unit:** 4px (Tailwind scale: 1=4, 1.5=6, 2=8, 3=12, 4=16, 5=20, 6=24). - **Density:** compact / desktop-tight. - **Control + row height:** `h-8` = 32px default; `h-7` = 28px small; `h-6` = 24px xs. - Inputs `px-2.5 py-1`; buttons `px-2.5`, gap 1–1.5. ## Layout - **Approach:** fixed three-pane app shell, opens into the workbench (no marketing/dashboard home). - **Panes:** `[ rail 240px ] [ center 1fr ] [ side rail 316px ]`. - **Rail (240px), top → bottom:** 1. **Orchestrator anchor** — pinned, single, visually distinct (blue 2px left bar, `--bg-2` fill, hub/`waypoints` icon, name "Orchestrator", a `5 agents · 2 need you` mono summary). This is ReverbCode's one addition over emdash. Default landing view. 2. `PROJECTS` eyebrow label + a `+`. 3. Project rows (folder icon + name) with nested **worker rows beneath**. Each project row has a hover-revealed **`+`** that opens the New-worker modal pre-scoped to that project (distinct from the `PROJECTS` header `+`, which registers a repo). 4. **Footer:** `Search ⌘K`, `Settings ⌘,`. (No Library.) 5. **Account** row pinned at the very bottom. - **Worker rows are name-only.** Just the session name, truncated. Status, branch, diff, and PR live in the panes and topbar, never in the row. Selection = `--bg-2` fill + a 2px blue left bar. (emdash itself shows a faint trailing timestamp; we omit it by choice.) - **Center = the conversation.** Orchestrator → its coordination terminal (delegate here; composer reads "tell the orchestrator what to build"). Worker → the agent CLI terminal (tabbed per agent, e.g. `claude-code (1)`), with a composer (model selector, worktree path, `Accept edits`). The terminal **is** the conversation; no separate chat surface. - **Side rail (316px):** orchestrator → a quiet **Workers** list (name + project + derived status). Worker → the **Git review rail**: `Changed N` → All files / Discard all / Stage all → file rows (`+adds −dels`, stage toggle) → `Commit message` + `Description` → **Commit & Push** (primary blue) → branch + `Create PR`. - **Border radius:** `sm` 4px (scrollbar) · `md` 6px (buttons, inputs, toggles) · `lg` 8px (rows, cards, panels) · `xl` 12px (modals) · `full` (badges/pills/dots). - **Icons:** **lucide** only. No emoji. ### Topbar - **Left (both):** `project / session` breadcrumb + pin; for the orchestrator, a hub icon - `Orchestrator`. - **Right — worker session:** a **PR/CI status pill** that is the action (`PR #156 · mergeable` green / `CI failed` red / `review requested` amber / `Open PR` when none) → **Changes / Files / Terminal** view toggles → **⋯ session menu** (rename, restart, kill, claim PR — the `ao session …` commands). - **Right — orchestrator:** **+ New worker** → Terminal toggle → **⋯ menu**. No diff toggles. ### Spawn-worker modal (mirrors emdash's Create Task) You mostly let the orchestrator spawn workers from its conversation; the manual paths (the topbar `+ New worker`, a project row's hover `+`, or `ao spawn`) open a modal that mirrors emdash exactly. Launching from a project row pre-fills the Project field: - Centered dialog, **12px radius**, `max-w` ~512px, `bg` canvas, `ring-1` at 10% fg, fade + zoom-95 enter. - **Header:** eyebrow mono-uppercase title `New worker` + `×` close. - **Body** (`gap` 15–16px): a **borderless large name field** (18px, auto-focus, slug rule "letters, numbers, hyphens") → **Project** selector → **Agent** selector (claude-code / codex / opencode / …) → a **"Based on"** bordered card with a segmented control `Branch · Issue · Pull Request` revealing a combobox → a **Prompt / Workspace** tab where Prompt is the worker's initial task (textarea). - **Footer:** right-aligned single primary **`Spawn worker`** (blue) with a `⌘↵` keycap, disabled until valid. ## Motion - **Approach:** minimal-functional. The one expressive exception: a status dot/spinner pulse on active/working sessions (opacity breathe) so "alive" is glanceable. Never animate text or layout. - **Easing:** enter `ease-out`, exit `ease-in`, move `ease-in-out`. - **Duration:** micro 80ms · short 160ms · medium 240ms · status pulse 1.8s loop · modal enter ~150ms fade+zoom-95. ## Implementation notes - The renderer (`frontend/src/renderer/styles.css`) currently uses **Inter** and a grayscale-blue theme. Migrate to this system: drop the Inter `font-family`, adopt the system stack, and replace the token values with the emdash neutral ramp + blue accent above. - Keep tokens as CSS custom properties under `:root` (dark) and `:root[data-theme="light"]`. - A faithful HTML reference of all of the above (both views + topbar + spawn modal, light/dark) is saved under `~/.gstack/projects/aoagents-agent-orchestrator/designs/design-system-20260609/`. ## Decisions Log | Date | Decision | Rationale | | ---------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | 2026-06-09 | Match emdash's visual language exactly | User direction; emdash is the demonstrated reference for this app's UI. | | 2026-06-09 | System font, not a custom typeface (e.g. Geist) | emdash uses the system stack; fidelity + native feel + zero font payload chosen over brand type. | | 2026-06-09 | Refined **blue** accent, not emdash's jade green | User's explicit pick; blue for primary/active/focus, terminal stays green. | | 2026-06-09 | Single global **Orchestrator** anchor, orchestrator-first default view | The one real difference from emdash; orchestrator is the human-facing coordinator you delegate to. | | 2026-06-09 | **Name-only** worker rows | User direction; status/branch/diff live in panes + topbar, not the row. | | 2026-06-09 | Removed **Library** from the rail footer | User direction; footer is Search + Settings only. | | 2026-06-09 | Topbar right = PR/CI pill + view toggles + ⋯ menu (worker) | Surfaces the actionable PR/CI state from the daemon; emdash/PostHog Code precedent. | | 2026-06-09 | Spawn modal mirrors emdash's Create Task | Consistency with the reference; mapped to `ao spawn` params. |