# Phase 2 — Settings as a full-page grouped navigation _One PR, after phase 1._ ## Goal Replace the horizontal `PageTabs` bar on `/settings` with a left navigation grouped under small uppercase headings, one section per route, a search box that filters sections, and consistent row primitives — the structure in `reference/orca-settings1.png` / `orca-settings-agents.png` / `orca-settings-scrolled.png`, in AgentHub's own tokens. ## Non-goals - No new settings. Every control that exists today is kept, moved, and reachable from search. (One exception: the worktree-visibility toggles from phase 1 get their first proper home here.) - No theme change. No new dependency. - No change to any server setting route. ## 1. Routes `App.tsx`: `settings` → `settings/:section?`. `SettingsHub.tsx` reads `:section`; unknown or missing ⇒ redirect to `settings/general`. The old `?tool=` query is honoured for one release: `?tool=claude-code` ⇒ `/settings/agents/claude-code`, `?tool=ai-router` ⇒ `/settings/ai-router`, and `#ai-tools` ⇒ `/settings/agents` with the catalog modal open. Every in-app link that builds a settings URL (`AddLaneModal`'s AI Tools link, the Claude tab's cross-links, `Sidebar` nav) is updated to the path form. Section ids are stable strings (they are URLs and i18n keys): | Group (i18n `settingsNav.group.*`) | Section id | Content = today's component | | --- | --- | --- | | **General** | `general` | `Settings.tsx` sections: `lanesSection` (renamed "Workspaces": housekeeping) + `data` (import, remote sources, clear data) + `about` | | | `appearance` | `AppearanceSettings` | | | `notifications` | `Settings.tsx` `notifications` + `alertsHub` (`AlertsNotifications`, `WebhookSettings`) | | **Agents** | `agents` | `AiToolsSettings` inline (the modal's content as a page; `AiToolsModal` stays for the Add-workspace link) | | | `agents/claude-code` | `CcConfig` (its own sub-tabs stay inside the page) | | | `agents/codex` | `CodexConfig` | | | `agents/` | `AiToolConfig toolId` — one entry per installed, enabled tool without a `launcher` (same rule as today's `catalogTabs`) | | **Routing** | `ai-router` | `AiRouterConfig` | | | `pricing` | `PricingSettings` with a vendor filter for *all* vendors (today it is embedded per tool; keep those embeds too — this page is the all-vendors view) | | **Git** | `git-credentials` | `GitCredentialsConfig` | | | `worktrees` | **new** `WorktreeVisibilitySettings`: "Show untracked worktrees" switch; per-source rows `.claude/worktrees/*` (Show/Hide), AgentHub-managed (`LANES_ROOT`) (Show/Hide); writes the phase-1 localStorage key | | **Projects** | `projects/` | **new** `ProjectSettings`: read-only project card (root, main branch, worktree count), its workspaces (link to each), the per-project override of the worktree sources above (`hideSources` keyed by root), and "Forget all workspaces of this project" (loops `POST …/remove`, confirm modal listing them) | A tool section is hidden while that tool is disabled (same `aiTools.byId(...).enabled` check as today). ## 2. Layout ``` ┌ sidebar (app) ┬──────────────────────────────────────────────────────────┐ │ │ ← Back to Workspace │ │ │ [🔍 Search settings Ctrl+F] │ │ │ │ │ │ GENERAL │ General │ │ │ ⚙ General │ Workspace housekeeping, data, about. │ │ │ ◐ Appearance │ ───────────────────────────────────── │ │ │ 🔔 Notifications│ ┌ card ─────────────────────────────┐ │ │ │ AGENTS │ │ Housekeeping │ │ │ │ ▣ AI tools │ │ Run housekeeping [Dry run][Run]│ │ │ │ ✳ Claude Code │ ├───────────────────────────────────┤ │ │ │ ◎ Codex │ │ Data │ │ │ │ ▲ Antigravity │ │ Import history … │ │ │ │ ROUTING … │ └───────────────────────────────────┘ │ │ │ PROJECTS │ │ │ │ ◈ agenthub │ │ └───────────────┴──────────────────┴─────────────────────────────────────────┘ ``` - The settings nav is a second column **inside** the page (`w-56`, sticky, own scroll), not the app sidebar. The app sidebar stays as it is. - "← Back to Workspace" is a plain link to `/workspace` (keeps `?ws` from localStorage). - Content column: `max-w-3xl`, section title `text-2xl font-semibold`, one-line description `text-sm text-fg-muted`, hairline, then **one card per subsection** (`.card` as today). Do not nest cards. - Mobile (`< md`): the nav becomes a `