nexus/MIGRATION-PLAN.md
Nexus Dev 43ca8d3047 docs(nexus): layout overhaul spec
Adds docs/specs/2026-04-11-nexus-layout-overhaul.md defining the
complete layout and information architecture redesign:

- 4-destination primary nav (Assistant, Studio, Projects, Settings)
- 56px left icon rail + 48px top strip as global frame
- Assistant as default landing (full-bleed chat, no side panels)
- Studio as 8-card workshop grid (Convert folded in as 8th workshop)
- Projects with per-project Builder tabs replacing global routes
  (Issues, Agents, Gates, Costs, Activity, Org become per-project;
   Routines moves to Settings; Goals folds into Overview; Inbox
   killed-replaced by assistant dot + cmdK)
- Promote-to-project transition (chat compresses to 30%, brainstormer
  rises into 70%, inset shadow ripple, 700ms)
- Voice and Cmd-K as global affordances; ChatPanel/PropertiesPanel
  killed as global rails
- Implementation phases 8-16 with parallel subagent dispatch pattern

Also promotes the previously untracked MIGRATION-PLAN.md into the
repo, and extends it with section 8b (structural overhaul summary
table linking to the spec) and section 11 (binding subagent dispatch
pattern for phases 8-16).

Approved 2026-04-11 in brainstorming session; all 25 decisions from
the discussion are captured in spec section 11.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:34:51 +00:00

31 KiB
Raw Blame History

Design System Migration Plan — Nexus UI → DESIGN.md (ClickHouse-inspired)

Status: DRAFT, awaiting review. Do not touch UI files until this is approved.


1. Executive summary

Migrate the Nexus UI from its current Tailwind v4 + Catppuccin (Mocha/Latte) + Tokyo Night setup to the new DESIGN.md aesthetic: pure black canvas, Neon Volt (#faff69) as the sole chromatic accent, Forest Green (#166534) as secondary CTA, Inter/Basier/Inconsolata typography, sharp geometry, border-based depth.

Scope in numbers (from codebase scan):

Category Count How it migrates
CSS variables in index.css 29 × 3 selectors Rewrite @theme inline block (single file edit)
Tailwind theme-token classes (bg-background, text-muted-foreground, border-border, …) ~1,250 instances Auto-migrate when CSS vars change — zero source edits
Raw palette utilities (bg-red-500, text-amber-600, …) ~274 instances across ~60 files Manual remap to semantic tokens — per-file work
Hardcoded hex fallbacks in TSX (e.g., #6366f1, #64748b) ~65 files Find-and-replace with token refs
Status / priority / agent-role color maps (lib/status-colors.ts, lib/agent-role-colors.ts) ~45 definitions Rewrite against new palette
hljs syntax highlighting blocks in index.css 3 theme blocks (Mocha, Tokyo, Latte) Delete, write one block matching DESIGN.md
Theme switching machinery (ThemeContext.tsx, Layout.tsx toggle) 2 files Simplify — drop Catppuccin/Tokyo cycle, keep light/dark binary
Font loading (Inter/Basier/Inconsolata) 0 currently Add font-face declarations (or CDN) — new work

Effort estimate: One careful pass, with the bulk of the mechanical work concentrated in ~3 files (index.css, lib/status-colors.ts, lib/agent-role-colors.ts) and a long tail in the ~60 files using raw palette utilities. The hardcoded hex cleanup is mostly in fallback expressions and is trivial once the token semantics are agreed.

Key design decisions the user must make before Phase 1:

  1. Light mode strategy. DESIGN.md explicitly says "no light/white backgrounds anywhere." I've drafted a light mode anyway (Section 5), but I'd like confirmation on the direction — or explicit permission to drop light mode entirely.
  2. Neon Volt on white is unreadable. In light mode, volt either gets reserved for border/active states (primary chromatic accent rotates to Forest Green) or we pick a darker neon-adjacent hue. See Section 5.
  3. Tokyo Night removal. The .theme-tokyo-night.dark selector is defined in CSS but never applied by the current ThemeContext (dead code). I propose deleting it — confirm.
  4. Font pipeline. Inter/Basier/Inconsolata are not currently loaded. Options: Google Fonts CDN, self-hosted woff2, or @fontsource npm packages. I'd suggest self-hosted woff2 for LAN/offline reliability, but that's 610 MB of fonts in public/. Confirm preference.
  5. Font weight 900 for display. DESIGN.md calls this out as core to the identity. Current Nexus has no 96px+ display type. Adopt for hero/landing moments or skip?

2. Current state vs. DESIGN.md (side by side)

Color philosophy

Dimension Current (Catppuccin Mocha) Current (Tokyo Night) DESIGN.md (ClickHouse)
Background #1e1e2e (dark purple-gray) #1a1b26 (dark blue-gray) #000000 (pure black)
Card #181825 #16161e #141414 or transparent
Primary #89b4fa (blue) #7aa2f7 (blue) #faff69 (acid yellow-green)
Destructive #f38ba8 (pink) #f7768e (pink) TBD — DESIGN.md omits red
Border #313244 #24283b rgba(65,65,65,0.8) (charcoal)
Accent scale Smooth pastels Smooth blues Binary: volt or green, nothing else
Overall vibe Cozy, muted, rounded Cozy, muted, rounded Cockpit, sharp, maximum contrast

Typography

Role Current DESIGN.md
Font family System stack (no explicit loads — Tailwind default) Inter + Basier + Inconsolata
Display weight Up to 700 at 2436px 900 at 7296px
Body weight 400 / 500 400 / 500 / 600 / 700
Labels Mixed case Uppercase + 1.4px tracking
Code Monospace (system) Inconsolata 600

Geometry

Current DESIGN.md
Radius scale sm:2px md:4px lg:0 xl:0 (already sharpish) Sharp 4px / comfortable 8px / pill 9999px — nothing else
Border style Solid 1px Solid 1px, charcoal rgba(65,65,65,0.8) — single workhorse color
Shadow Subtle layered shadows Border-based depth + inset "pressed" effect

Interaction

Current DESIGN.md
Link hover Muted highlight Volt (#faff69) — universal
Active text Opacity change Pale Yellow (#f4f692)
Button hover Subtle bg shift BG shifts to #3a3a3a, text to volt/pale

3. Token mapping — old vars → new vars (DARK mode)

The migration is primarily a rewrite of the @theme inline block in /opt/nexus/ui/src/index.css. Token names stay the same (so the ~1,250 Tailwind utility classes auto-migrate); only values change.

Token Current (Mocha) New (DESIGN.md dark) Notes
--background #1e1e2e #000000 Pure black, no compromise
--foreground #cdd6f4 #ffffff Pure white
--card #181825 #141414 "Near Black" from DESIGN.md §2
--card-foreground #cdd6f4 #ffffff
--popover #181825 #141414 Match card
--popover-foreground #cdd6f4 #ffffff
--primary #89b4fa (blue) #faff69 (volt) The brand inversion — single biggest visual change
--primary-foreground #1e1e2e #151515 Near-black text on volt
--secondary #313244 #166534 (forest) Secondary CTA becomes green
--secondary-foreground #cdd6f4 #ffffff
--muted #313244 #141414 Muted surfaces stay near-black
--muted-foreground #a6adc8 #a0a0a0 (silver) DESIGN.md §2 "Silver"
--accent #45475a #141414 Accent surface = muted surface in this system
--accent-foreground #cdd6f4 #faff69 Text on accent surfaces lights up volt
--destructive #f38ba8 (pink) #ef4444 (muted red) DESIGN.md doesn't specify — I picked a restrained red that doesn't compete with volt. Confirm.
--destructive-foreground #1e1e2e #ffffff
--border #313244 rgba(65,65,65,0.8) (charcoal) Workhorse — DESIGN.md §2
--input #313244 #141414 Input fields use near-black fill, charcoal border
--ring #89b4fa #faff69 Focus ring is volt
--chart-1 #89b4fa #faff69 Primary chart series = volt
--chart-2 #a6e3a1 #166534 Secondary = forest
--chart-3 #cba6f7 #a0a0a0 Tertiary = silver
--chart-4 #f9e2af #f4f692 (pale yellow) Active/pressed accent
--chart-5 #f38ba8 #ef4444 Destructive (if needed for alerts)
--sidebar #181825 #000000 Sidebar = pure black, no surface differentiation
--sidebar-foreground #cdd6f4 #a0a0a0 Secondary silver — nav items dim, active is volt
--sidebar-primary #89b4fa #faff69
--sidebar-primary-foreground #1e1e2e #151515
--sidebar-accent #313244 #141414
--sidebar-accent-foreground #cdd6f4 #ffffff
--sidebar-border #313244 rgba(65,65,65,0.8)
--sidebar-ring #89b4fa #faff69

New tokens to add (not in current system but needed for DESIGN.md fidelity):

New token Value Purpose
--volt #faff69 Direct brand-accent reference (for code that needs the literal brand color, e.g. logo, chart emphasis)
--volt-pale #f4f692 Active/pressed text color per DESIGN.md §2
--volt-border #4f5100 Dark olive ghost-button borders per DESIGN.md §2
--forest #166534 Direct secondary-CTA reference
--forest-dark #14572f Darker forest for border variant
--near-black #141414 Button backgrounds, elevated dark surfaces
--hover-gray #3a3a3a Button hover background
--silver #a0a0a0 Secondary/muted text
--charcoal-border rgba(65,65,65,0.8) Signature border
--charcoal-divider #343434 Subtler division

Radius

DESIGN.md is strict: 4px, 8px, 9999px. Current --radius-* tokens are already close — audit and lock:

Token Current New Notes
--radius-sm 2px 4px Bump to 4 (DESIGN.md "sharp")
--radius-md 4px 4px Keep
--radius-lg 0px 8px DESIGN.md "comfortable" for cards
--radius-xl 0px 8px Alias to lg; audit xl usage and collapse
--radius-full 9999px 9999px Pill unchanged

Audit task: grep for rounded-xl, rounded-2xl, rounded-3xl — these violate the DESIGN.md scale and need to come down.


4. Typography migration

Font loading

Currently: no explicit font loads — Tailwind falls back to system stack.

Proposed: self-hosted woff2 via @font-face in index.css, dropped into ui/public/fonts/. Rationale: LAN testing without internet; Nexus is meant to run offline-capable.

@font-face {
  font-family: "Inter";
  src: url("/fonts/Inter-VariableFont_slnt,wght.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Inconsolata";
  src: url("/fonts/Inconsolata-VariableFont_wdth,wght.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
}
/* Basier: not free — likely fallback to Inter for feature headings, or purchase license */

Decision needed: Basier is a paid font. Either:

  • (A) License Basier (one-time cost) — true to DESIGN.md
  • (B) Use Inter for both display and feature headings (skip Basier entirely) — simpler, free
  • (C) Sub in a free alternative (Manrope, Space Grotesk, Archivo) with similar character

I recommend (B) for the migration — DESIGN.md's Inter/Basier split is subtle and the rest of the aesthetic carries the identity. Can upgrade to real Basier later.

@theme additions

@theme inline {
  --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Inconsolata", ui-monospace, "Courier New", monospace;
  --font-display: "Inter", ui-sans-serif, system-ui, sans-serif;  /* weight 900 usage */
}

Tracking / weights

Audit component library (shadcn-like components/ui/) for heading weights and letter-spacing. Specifically:

  • Button text: 600700 weight
  • Section overlines: uppercase + tracking-[0.1em] (≈ 1.4px at 14px font)
  • Display heading: text-6xl md:text-8xl font-black (96px at weight 900)

5. Light mode derivation

DESIGN.md is dark-only by policy ("Don't use light/white backgrounds anywhere"). But the user explicitly asked for a light mode. I propose treating light mode as a legibility alternative, not a brand statement — it preserves accessibility without claiming design parity with the dark mode.

Design principles for the light variant

  1. Neon Volt is downranked. On white, #faff69 is invisible. In light mode, volt is reserved for border highlights and active states — never backgrounds, never text. The primary chromatic accent rotates to Forest Green (#166534), which DESIGN.md already treats as a primary CTA color.
  2. Canvas is near-white, not pure white. Pure #ffffff is harsh; #fafafa gives the eye something to hold. Matches "paper on desk" affordance.
  3. Charcoal inverts to silver. Border/divider workhorse becomes rgba(20,20,20,0.12) — faint, functional, same role.
  4. Text hierarchy inverts. Primary text #0a0a0a, secondary #6b6b6b (a light-mode counterpart to DESIGN.md's Silver #a0a0a0).
  5. Sharp geometry stays. Radius, fonts, weights, borders — identical. Only hue flips.

Light mode token values

Token Value Rationale
--background #fafafa Near-white canvas
--foreground #0a0a0a Near-black text
--card #ffffff Pure white cards sit above canvas
--card-foreground #0a0a0a
--popover #ffffff
--popover-foreground #0a0a0a
--primary #166534 (forest) In light mode, the CTA accent is forest green — volt is too unreadable
--primary-foreground #ffffff White on forest
--secondary #f1f5f1 Very pale forest tint for secondary surfaces
--secondary-foreground #0a0a0a
--muted #f4f4f5 Pale gray for muted surfaces
--muted-foreground #6b6b6b "Light silver" — readable but clearly subordinate
--accent #fafff0 Very faint volt tint for highlighted surfaces
--accent-foreground #4f5100 Dark olive text (volt-family) on the pale volt surface
--destructive #dc2626 Readable red on white
--destructive-foreground #ffffff
--border rgba(20,20,20,0.12) Inverted charcoal — workhorse
--input #ffffff
--ring #166534 Focus ring matches primary (forest)
--volt #4f5100 In light mode, --volt resolves to the dark olive (DESIGN.md's "Border Olive") so any component that references it directly stays readable
--volt-pale #8a8c00 Mid-tone olive for active states
--volt-border #4f5100 Same as current DESIGN.md spec
--forest #166534 Unchanged — forest reads on both backgrounds
--forest-dark #14572f Unchanged
--near-black #0a0a0a Repurposed as the darkest text color
--hover-gray #e4e4e7 Light hover background
--silver #6b6b6b Darker silver for light-mode legibility
--charcoal-border rgba(20,20,20,0.12) Inverted
--charcoal-divider rgba(20,20,20,0.08) Even fainter
--sidebar #ffffff
--sidebar-foreground #6b6b6b Muted nav labels
--sidebar-primary #166534 Active nav = forest
--sidebar-primary-foreground #ffffff
--sidebar-accent #f4f4f5 Hover bg
--sidebar-accent-foreground #0a0a0a
--sidebar-border rgba(20,20,20,0.12)
--sidebar-ring #166534

Trade-offs of this approach

  • Pro: Preserves DESIGN.md's dual-accent system (volt + forest) by promoting forest when volt can't perform.
  • Pro: Sharp geometry and charcoal border identity carry across modes.
  • Con: Light mode is objectively weaker brand-wise than dark — the neon-on-black drama is gone.
  • Con: Components that rely on volt as their primary affordance (e.g., "click me, I'm the CTA") look different in light mode.
  • Con: If Nexus is meant to be a cockpit, a light mode fundamentally undermines the atmosphere. The honest answer might be: don't ship a light mode.

User decision required: do I ship this light mode, drop light mode entirely, or iterate on the palette?


6. Raw Tailwind color utility remapping

The scan found ~274 instances of raw color utilities (bg-red-500, text-amber-600, etc.) that bypass the theme-token system. These need manual remapping.

Semantic categories and their new homes

Use case Current classes New strategy
Error / destructive (bg-red-*, text-red-*) 74 instances bg-destructive, text-destructive (theme tokens)
Warning / pending (bg-amber-*, text-amber-*, bg-yellow-*) 70 instances → New token --warning (proposed: #f59e0b dark, #b45309 light), then bg-warning, text-warning
Success / completed (bg-green-*, text-green-*, bg-emerald-*) 34 instances → New token --success = #166534 (matches forest); bg-success
Info / in-progress (bg-blue-*, text-blue-*, bg-cyan-*, bg-sky-*) 63 instances text-muted-foreground or a new --info token = #a0a0a0 (silver) in dark mode
Role / agent hues (violet, pink, teal, orange, indigo, rose) ~14 instances These are the hardest. In DESIGN.md's palette, everything non-volt/non-forest is neutral. Options: (a) collapse all role colors into silver/volt/forest variations, losing per-role distinction; (b) introduce a small "chart palette" of low-saturation grays and use pattern/icon differentiation instead of hue; (c) keep a small named-role palette as an exception. I lean toward (a) — use volt for the primary role, silver for the rest, rely on labels/icons for identity.
Status/neutral (bg-neutral-*, bg-zinc-*, bg-slate-*, bg-gray-*) 24 instances bg-muted, text-muted-foreground

Impact on lib/status-colors.ts and lib/agent-role-colors.ts:

These files are the primary home for the ~100 palette mappings. They define the source-of-truth dictionaries that most raw-utility usage pulls from. Rewriting these two files gets us ~60% of the raw-utility work done.

I'll draft the replacement dictionaries in Phase 2 (see Section 8) — that rewrite is the single biggest file-level change in the migration.


7. File-by-file scope

Must change (foundation — Phase 1)

File Lines of change Why
ui/src/index.css ~300 → ~250 (rewrite theme blocks, hljs, scrollbars) All token values, all three theme variants → two modes, new hljs palette
ui/src/lib/status-colors.ts Full rewrite ~30 status → color mappings need new palette
ui/src/lib/agent-role-colors.ts Full rewrite ~15 role → color mappings
ui/src/context/ThemeContext.tsx Simplify Drop "custom" theme type, drop Catppuccin/Tokyo cycle, keep light/dark binary
ui/src/components/Layout.tsx ~10 lines Drop theme cycle map (lines 6672), simplify toggle

Should change (sweep — Phase 2)

Files with raw palette utilities, ordered by instance count (high-impact first). From the scan I'd need to enumerate these precisely in the execution phase, but the top offenders are predictable:

  • Any "status pill" / "priority badge" / "agent role avatar" component — where most of the 274 raw utilities live
  • pages/OrgChart.tsx — 6 hardcoded hex status colors + raw palette usage
  • pages/Inbox.tsx#64748b fallback + raw classes
  • pages/Routines.tsx#64748b fallback × 3
  • pages/CompanySettings.tsx, pages/ContentStudio.tsx — brand color defaults
  • components/NewIssueDialog.tsx#6366f1 project color fallback × 2
  • components/MarkdownEditor.tsx#64748b fallback
  • components/VoiceWaveform.tsx — hardcoded #89b4fa (needs to become var(--primary) or --volt)
  • components/ThemePreviewPanel.tsx — 12 hardcoded hexes (this file IS the theme preview; needs full rewrite against new palette)
  • components/ThemePaletteGrid.tsx — Catppuccin green references

Complete file list to be produced during Phase 2 execution via a precise rg '(bg|text|border|ring)-(red|blue|green|amber|yellow|cyan|violet|pink|slate|zinc|neutral|sky|teal|emerald|indigo|rose|orange)-' ui/src with per-file counts.

May change (audit — Phase 3)

  • Typography usages: any text-*xl, font-bold etc. needing bump to font-black for display moments
  • Radius audits: rounded-2xl, rounded-3xl need to come down to rounded-lg (8px) or rounded-sm (4px)
  • Shadow audits: replace soft shadows with border-based elevation or inset "pressed" effects for active states

Do NOT change

  • .planning/, doc/, docs/, test fixtures, snapshots
  • packages/branding/ — has no colors, just vocabulary
  • Test files that assert current palette (note: ThemePreviewPanel.test.tsx has snapshot tests that will need updating, but snapshot updates are mechanical, not design work)

8. Migration sequence

Ordered phases. Each phase is independently committable and reviewable.

Phase 1 — Foundation (single commit)

What: Rewrite ui/src/index.css @theme block and all three theme selectors. Load new fonts. Simplify ThemeContext.tsx + Layout.tsx theme cycle.

Goal: After this phase, the app's ~1,250 theme-token class usages visually switch to the new palette with zero per-file edits. Raw utilities and hardcoded hexes will still look wrong — that's Phase 2.

Deliverables:

  • New ui/src/index.css (rewritten theme blocks + font-face declarations)
  • Fonts in ui/public/fonts/ (woff2 Inter + Inconsolata)
  • Simplified ThemeContext.tsx (binary light/dark, no Catppuccin/Tokyo)
  • Simplified Layout.tsx theme toggle button

Verification: load any authenticated page, visually confirm black canvas + volt accents on borders and CTAs. Expect ugly patches where raw utilities still show their old colors — that's expected at this phase.

Phase 2 — Status / role color rewrite (single commit)

What: Rewrite lib/status-colors.ts and lib/agent-role-colors.ts against the new palette. This cleans up ~60% of the raw-utility usage because those two files are the source of truth for most status/priority/role dictionaries.

Deliverables:

  • New color dictionaries
  • Any components that import from these files get their "wrongness" fixed automatically

Verification: inbox, org chart, agent cards all show volt/forest/silver status indicators instead of red/blue/green.

Phase 3 — Raw utility sweep (one commit per logical component group)

What: Per-file cleanup of the remaining raw palette utilities and hardcoded hex fallbacks. Group by feature (dashboard, org chart, inbox, settings) so each commit is reviewable.

Deliverables:

  • ~60 files touched, 274 utility instances replaced with theme tokens or new semantic tokens (bg-warning, bg-success, etc.)
  • ~65 hardcoded hex fallbacks replaced with var(--token) refs or text-muted-foreground equivalents

Verification: grep for raw palette utilities — should be zero matches (or only well-justified exceptions). Visual regression via manual QA of each touched page.

Phase 4 — Typography + radius audit (single commit)

What: Bump heading weights to 900 for display moments, enforce radius scale (4px/8px/9999px only), replace soft shadows with border-based depth.

Deliverables:

  • Hero/landing pages use display typography
  • rounded-2xl/rounded-3xl collapsed to rounded-lg or rounded-sm
  • Soft shadow-md/shadow-lg replaced with border + inset shadows for active states

Verification: visual compliance with DESIGN.md §3-§6 on representative pages.

Phase 5 — ThemePreviewPanel rewrite (single commit)

What: The theme preview / palette grid components currently showcase Catppuccin. They need a complete rewrite to preview the new system.

Deliverables:

  • ThemePreviewPanel.tsx showing new palette
  • ThemePaletteGrid.tsx or deprecation (if the grid no longer makes sense in a binary-mode system)

Phase 6 — hljs syntax highlighting (single commit)

What: Replace the three Catppuccin/Tokyo hljs rule sets in index.css with a single DESIGN.md-compliant rule set: neon and white on dark, terminal aesthetic per §4.

Deliverables:

  • .hljs-* rules rewritten in index.css
  • Light mode hljs variant derived

Phase 7 — Visual QA pass

What: Walk every top-level route, compare against DESIGN.md principles, capture screenshots for before/after, file any remaining issues. No code changes unless issues found.


8b. Structural overhaul phases (816) — see layout spec

Phases 17 above are a visual repaint of the existing structure. They do not change layout, navigation, information architecture, or what each page does.

A separate, larger overhaul to the layout and IA was approved 2026-04-11 and is captured in docs/specs/2026-04-11-nexus-layout-overhaul.md. That spec defines phases 816, summarized here:

Phase Title Wave
8 Frame skeleton (56px icon rail, 48px top strip, kill ChatPanel/PropertiesPanel/sidebar) 1 (alone, foundational)
9 Assistant mode (full-bleed chat at /assistant, History/Memory slide-overs, conversational home state) 2 (parallel)
10 Studio mode (8-card workshop grid, fold ConvertPage in, freeform prompt) 2 (parallel)
11 Projects + Builder mode (hero-stat cards, 7-tab Builder strip, demote 9 global routes to per-project tabs) 2 (parallel)
12 Promote-to-project transition (700ms compress + rise animation with inset shadow ripple) 3 (parallel)
13 Settings consolidation (single-column, Skills + Routines sections, drop nested settings routes) 3 (parallel)
14 Voice + ⌘K globalization (mic in top header, voice queues to Assistant inbox, universal command palette) 3 (parallel)
15 Mobile parity (bottom tab bar, project sub-tab strip, mobile takeovers for slide-overs) 3 (parallel)
16 Cleanup pass (vocabulary sweep, dead-code removal, visual QA) 4 (alone, sequential)

The dispatch pattern for phases 816 is documented in §11 below.

Phases 17 are independent of phases 816 and can ship first. The overhaul does not block visual QA — and conversely, the visual repaint produces tokens that the overhaul phases consume. Phases 816 should not begin until phase 4 (typography + radius audit) is at minimum committed, because the new frame relies on the locked-in radius scale and font weights.


9. Risks and decisions

Decisions required from you before Phase 1

  1. Light mode: ship the derived palette (Section 5), drop it entirely, or iterate on my draft?
  2. Basier font: license it, use Inter everywhere, or pick a free alternative?
  3. Destructive color: DESIGN.md doesn't specify a red. I propose #ef4444 (muted). Confirm or pick.
  4. Role hue collapse vs. preserve: for agent roles / chart series, do we accept a silver-only palette with pattern differentiation, or keep a small named-role palette as a controlled exception?
  5. Display weight 900: adopt for hero/landing moments, or skip the 96px Inter Black treatment?
  6. Theme toggle UX: if we drop Tokyo Night, is the toggle still light ↔ dark, or do we simplify further (e.g., single dark mode, light is an accessibility fallback only)?
  7. Tokyo Night removal: the .theme-tokyo-night.dark block in index.css is dead code (never applied by ThemeContext). Confirm I should delete it.

Risks

  • Visual regression: ~1,250 token-using elements will all shift on Phase 1. Expect surprise — Catppuccin is cozy and Nexus users may not be ready for cockpit-level contrast. Worth previewing on a throwaway branch.
  • Accessibility: volt on black (#faff69 on #000000) passes WCAG AAA for normal text, but volt on white fails for anything smaller than 18pt. That's why light mode downranks volt.
  • Chart/viz readability: with only 5 semantic chart colors (volt, forest, silver, pale, red), multi-series visualizations get crowded. Consider using the same hue with pattern/opacity differentiation, or accepting the "chart palette" as a documented exception.
  • Catppuccin Mocha nostalgia: if anyone on the team is attached to the Mocha look, DESIGN.md's aesthetic is going to feel jarring. Socialize early.
  • Component-library components (components/ui/*): these are shadcn-ish primitives. They use theme tokens heavily, which is good — they'll auto-migrate. But any that hardcode radius or shadow styles need individual audit.
  • Onboarding wizard + InviteLanding: just-touched files using the current palette. They'll shift visually in Phase 1 — worth a dedicated visual review since they're the first thing a new user sees.
  • Font loading flash: adding web fonts for the first time introduces FOUT/FOIT. Use font-display: swap and preload the most critical weights (Inter 400, 700, 900).

Out of scope (for this migration)

  • Custom user themes (the current "custom" theme type is seldom used; I propose dropping it)
  • Per-company branding overrides (covered by separate worktree-branding.ts system — untouched)
  • Print styles
  • High-contrast accessibility mode beyond normal WCAG

10. Open questions for the user

Answer these and I'll kick off Phase 1:

  1. Light mode: ship / drop / iterate?
  2. Fonts: license Basier / Inter only / free alternative (name one)?
  3. Destructive red: #ef4444 / other (specify)?
  4. Role hues: collapse to silver / keep small named palette / something else?
  5. Display 900: adopt / skip?
  6. Theme toggle: binary light/dark / dark only?
  7. Tokyo Night dead code: delete / keep as future option?

Once answered, I'll update this file with the resolved decisions and begin Phase 1 on a separate branch.


11. Subagent dispatch pattern (binding for phases 816)

Directive from user 2026-04-11: structural overhaul phases (816) MUST be implemented by dispatching subagents in parallel for any work that does not share files. Sequential implementation is wrong for work of this size. The implementation plan derived from docs/specs/2026-04-11-nexus-layout-overhaul.md will spell out the dispatch waves; this section is the standing rule.

Pattern:

  1. Read the spec before each wave. The spec (docs/specs/2026-04-11-nexus-layout-overhaul.md) is the source of truth for what to build. Don't infer from the code.
  2. Group phases into waves based on file overlap. Phases that touch disjoint files run in parallel. Phases that share files (or where one builds on another's output) run sequentially.
  3. Dispatch one subagent per phase per wave, in a single message with multiple Agent tool calls. Each subagent gets:
    • The phase number and title
    • The relevant section(s) of the spec verbatim
    • The specific files it owns (so two subagents in the same wave never touch the same file)
    • The atomic-commit requirement (one phase = one commit)
  4. After each wave, verify all subagents committed cleanly before dispatching the next wave. If a wave produces conflicts on any file outside its declared ownership, stop and re-plan.
  5. Use the superpowers:dispatching-parallel-agents skill for the actual dispatch. The skill enforces the message structure for parallel tool calls.

Anti-patterns explicitly forbidden by the user:

  • Doing phases 816 sequentially in the main session
  • Doing one phase yourself "to get started" and then dispatching the rest
  • Dispatching subagents for phases that share files (will produce merge chaos)
  • Using subagents for phase 16 cleanup (sequential by design — touches everything)

Wave structure for the layout overhaul:

Wave 1: [ Phase 8 ]                                  # foundational, alone
Wave 2: [ Phase 9 | Phase 10 | Phase 11 ]            # 3 subagents, parallel
Wave 3: [ Phase 12 | Phase 13 | Phase 14 | Phase 15 ] # 4 subagents, parallel
Wave 4: [ Phase 16 ]                                 # sequential cleanup, alone

This is captured here in MIGRATION-PLAN.md (rather than only in the spec) so that any future session opening this branch finds the directive even if it doesn't read the spec.