Studio v2 — Skeleton (Slice 1)
Date: 2026-04-16
Status: Approved
Owner: Lindsay
Part of: Sasha Studio Redesign (Rams-inspired hierarchical knowledge workspace)
Context
The Sasha Studio UI has grown into a dashboard of competing modules (Chats, Files, Workflows, Agents, Meetings, Admin, Docs, etc.). The approved redesign reframes the product as a hierarchical knowledge workspace where the tree of projects and folders is the spine, Markdown files and chats are sibling working artefacts, and everything else recedes.
This spec covers only the first slice of that redesign: a prototype workspace shell at a new route /studio/v2 that establishes the new frame (tree + breadcrumb + three-column layout) without yet implementing artefact viewers, the Studio drawer, or the Settings shelf.
The full redesign will be delivered as a series of slices after this one, each its own spec → plan → worktree → PR cycle.
Goals
- Prove the new frame can render alongside the existing classic UI without breaking it.
- Validate that the tree + breadcrumb + recede-secondary pattern delivers the intended spatial clarity, before investing in viewers or restyling.
- Establish the component boundaries, route conventions, and verification loop that subsequent slices will build on.
Non-Goals
- Opening files or chats in the Stage (viewer slices come next).
- Studio drawer content — Agents, Workflows, Meetings (their own slice).
- Settings shelf behind the avatar (its own slice).
- Visual restyling / new design tokens (deferred; reuse existing HSL tokens).
- Mobile layout (v2 is desktop-only during preview).
- Search functionality (the input is a placeholder).
- Any change to the classic UI or any backend endpoint.
Decisions (from brainstorming)
| Decision | Choice |
|---|---|
| Engagement shape | D — Prototype alongside classic at new route |
| First slice scope | ii — Workspace skeleton (tree + breadcrumb + empty stage/context) |
Shell behaviour at /studio/v2 |
b — Replace the shell entirely (no classic sidebar) |
| Tree structure | α — Two roots: Projects (with chats as flat leaves) + Knowledge (docs tree) |
| Styling | 3 — Reuse existing Tailwind HSL tokens; restyle in a later slice |
| Entry point | I — Direct URL only; no link from classic UI |
Architecture
Route
Add to claudecodeui/src/App.jsx inside the protected <Routes> block:
<Route path="/studio/v2" element={<StudioV2 />} />
ProtectedRoute already wraps the entire app, so auth is inherited.
Component tree
All new components live in claudecodeui/src/components/studio-v2/. No edits to existing components.
StudioV2 (new top-level; no classic shell)
├── StudioV2TopBar slim 40px top bar
│ ├── Sasha mark left; links to `/` (classic home)
│ └── AvatarMenu right; links out to existing settings routes
├── StudioV2Tree left rail, 280px, collapsible to 56px
│ ├── SearchInput placeholder (non-functional in this slice)
│ └── TreeBody
│ ├── TreeRoot: "Projects" from ProjectContextV2 via useProjects()
│ │ └── Project
│ │ └── Chat leaves from project.sessions[]
│ └── TreeRoot: "Knowledge" from docs listing endpoint
│ └── Folder / file leaves recursive
├── StudioV2Stage center, fluid width
│ ├── Breadcrumb permanent; derived from selection
│ └── StagePlaceholder "Select a file or chat to begin."
└── StudioV2Context right rail, 320px, collapsible
└── ContextPlaceholder heading "In this context." + "Nothing selected."
Component responsibilities
- StudioV2 — top-level layout, owns selection state, composes the four regions.
- StudioV2TopBar — stateless presentational.
- StudioV2Tree — fetches and renders the two roots; emits selection changes upward.
- StudioV2Stage — renders the breadcrumb and a placeholder; later slices will render viewers here.
- StudioV2Context — renders placeholder; later slices will display the active agent and referenced files.
- Breadcrumb — derived purely from the selected node's path; each segment is a clickable button that updates selection.
Each component's props and returned JSX should be small enough to hold in a single screenful. If a component grows past ~200 lines during implementation, split it.
Data flow
Projects root. Subscribe to existing ProjectContextV2 via useProjects(). For each project, render its sessions[] as flat chat leaves under the project node. No new backend work.
Knowledge root. Call the existing docs-listing endpoint (confirmed in server/routes/docs.js) once on mount, cache in component state, render as a folder tree. Reuse whatever fetch helper FileTree.jsx already uses for docs if it's easily extracted; otherwise make a direct fetch to the endpoint — do not refactor FileTree.
Selection state. Local to StudioV2 via useState:
type SelectedNode =
| { kind: 'project'; id: string; path: string[] }
| { kind: 'chat'; id: string; projectId: string; path: string[] }
| { kind: 'folder'; id: string; root: 'knowledge'; path: string[] }
| { kind: 'file'; id: string; root: 'knowledge'; path: string[] }
| null;
The tree's active highlight, the breadcrumb, and the context panel all derive from this single value.
No routing params are used for selection in this slice. The URL stays /studio/v2 regardless of selection — selection is in-memory only. URL-based selection will come with the viewer slices, once we know whether /studio/v2/file/... or /studio/v2?node=... fits better.
No write operations in this slice. Read-only.
Empty / loading / error states
- Tree loading. Inline skeleton rows (three shimmer lines under each root). No full-page spinner.
- Tree error. Inline message at the root node with a Retry button. The tree does not disappear.
- Stage, nothing selected. Quiet placeholder: "Select a file or chat to begin."
- Context panel, nothing selected. Heading "In this context." + muted "Nothing selected."
- Stage, folder or project selected. Breadcrumb renders. Stage body shows a muted "Select a file or chat inside this project." (project/folder selection doesn't open anything in v1.)
- Mobile viewport (< 768px). Single centred notice: "Studio v2 is desktop-only during preview." No layout attempted.
Verification (per commit)
Every commit on the slice branch must pass, in order:
npx vite buildfromclaudecodeui/— fail the commit if broken.npm run lintfromclaudecodeui/— enforces server-side rules (no-op for new client files, but run it anyway).- Playwright Chrome smoke test via
mcp__plugin_playwright_playwrightafter running the dev server locally:- Navigate to
/studio/v2(after logging in aslindsay). - Assert both tree roots ("Projects", "Knowledge") render.
- Click a project, assert it expands and shows chats as leaves.
- Click a Knowledge folder, assert it expands.
- Click a breadcrumb segment (once a selection exists) and assert selection updates.
- Navigate to
/— assert the classic UI still loads unchanged.
- Navigate to
Chrome troubleshooting. If Playwright fails to launch Chrome, kill the stuck Chrome session (pkill -f "Google Chrome") and retry once rather than looping.
Worktree & branch
- Worktree path:
../sasha-studio-v2(sibling to the main repo dir). - Branch:
studio-v2-skeleton, branched frommain. - Commits small and frequent, each passing the verification loop above.
- Ship as a single PR at the end of the slice.
Risks and mitigations
| Risk | Mitigation |
|---|---|
Knowledge tree fetch is entangled with FileTree.jsx internals |
If extraction is hard, call the raw endpoint directly — do not refactor FileTree in this slice. |
Classic ProjectContextV2 imposes side effects (e.g., auto-selecting a project on mount) that leak into v2 |
Read projects but do not call any selection mutators; if side effects appear, wrap v2 in a scope that avoids triggering them, or document and defer. |
Adding a new top-level component bloats App.jsx |
Mount StudioV2 via a single import + one <Route> line. All v2 logic lives under src/components/studio-v2/. |
Users stumble onto /studio/v2 and expect it to work |
Prototype notice in the top bar: "Studio v2 — preview. Unfinished." |
| Future slices (viewers, drawer, shelf) diverge from this frame | This spec is frame-only; each future slice gets its own spec and can reshape internals without touching the frame. |
Downstream slices (for context, not this spec's scope)
In likely order after this skeleton ships:
- File viewer in Stage — open a Markdown file in the Stage with shared chrome.
- Chat viewer in Stage — same, for chats; proves files and chats are siblings.
- Context panel content — active agent + referenced files display.
- Studio drawer — Agents / Workflows / Meetings behind a single icon.
- Settings shelf — Admin / Setup / Operations behind the avatar.
- Tree search (Cmd-K) — unified search across Projects + Knowledge.
- Visual restyle — Rams-like tokens; single accent, tighter type scale, generous whitespace.
- Remove guides/prompts from the classic UI entirely, once v2 reaches parity.
- Cutover —
/studio/v2becomes/and the classic UI is retired.
Each of these will be brainstormed and scoped separately.
