# Implementation Plan
## Goal
Restyle the Claude Flow Electron app with:
1. Fix the window/tab title from "minimal" → "Claude Flow"
2. Add a "CLAUDE FLOW" wordmark to the header
3. Apply a cipherpunk aesthetic (full monospace UI font, sharper geometry, electric-blue accent, uppercase meta labels, focus glow)
4. Add light/dark mode with a text toggle (`[dark]` / `[light]`) persisted to `localStorage`
## Approach
Five files touched in order of dependency. No new npm packages. The CSS rewrite is the biggest change; the JS/TSX changes are small and surgical.
**Order of changes:**
1. `renderer/index.html` — title fix (trivial, isolated)
2. `renderer/src/styles/globals.css` — full restyle (all visual work)
3. `renderer/src/App.tsx` — add theme state, wire it down
4. `renderer/src/components/Header.tsx` — wordmark + toggle button
5. `renderer/src/components/DocumentPane.tsx` — dynamic CodeMirror theme
---
## Changes
### 1. Fix Window Title
**File:** `renderer/index.html`
**What:** Change `
);
}
```
---
### 5. Dynamic CodeMirror Theme in DocumentPane
**File:** `renderer/src/components/DocumentPane.tsx`
**What:** Three surgical changes to `MarkdownEditor` — add `theme` prop, update imports, update `useEffect`.
**5a. Update imports** — add `syntaxHighlighting` and `defaultHighlightStyle` to the `@codemirror/language` import:
```typescript
// BEFORE:
import { markdown } from "@codemirror/lang-markdown";
import { languages } from "@codemirror/language-data";
// AFTER:
import { markdown } from "@codemirror/lang-markdown";
import { languages } from "@codemirror/language-data";
import { syntaxHighlighting, defaultHighlightStyle } from "@codemirror/language";
```
**5b. Update `MarkdownEditor` props interface** — add `theme`:
```typescript
// BEFORE:
function MarkdownEditor({
content,
onChange,
disabled,
}: {
content: string;
onChange: (content: string) => void;
disabled: boolean;
})
// AFTER:
function MarkdownEditor({
content,
onChange,
disabled,
theme,
}: {
content: string;
onChange: (content: string) => void;
disabled: boolean;
theme: "dark" | "light";
})
```
**5c. Update the `useEffect` inside `MarkdownEditor`** — swap the theme extension and add `theme` to the dependency array:
```typescript
// BEFORE (inside useEffect):
extensions: [
lineNumbers(),
highlightActiveLine(),
drawSelection(),
history(),
keymap.of([...defaultKeymap, ...historyKeymap]),
markdown({ codeLanguages: languages }),
oneDark, // ← hardcoded
updateListener,
EditorView.editable.of(!disabled),
EditorView.lineWrapping,
EditorView.theme({ ... }),
],
// dependency array:
}, [disabled]);
// AFTER:
extensions: [
lineNumbers(),
highlightActiveLine(),
drawSelection(),
history(),
keymap.of([...defaultKeymap, ...historyKeymap]),
markdown({ codeLanguages: languages }),
theme === "dark" ? oneDark : syntaxHighlighting(defaultHighlightStyle), // ← dynamic
updateListener,
EditorView.editable.of(!disabled),
EditorView.lineWrapping,
EditorView.theme({ ... }),
],
// dependency array:
}, [disabled, theme]); // ← theme added
```
**5d. Update `DocumentPaneProps` interface and pass `theme` through** — add to the interface and forward to `MarkdownEditor`:
```typescript
// BEFORE:
interface DocumentPaneProps {
content: string;
onChange: (content: string) => void;
phase: Phase;
disabled: boolean;
showOnboarding?: boolean;
}
// AFTER:
interface DocumentPaneProps {
content: string;
onChange: (content: string) => void;
phase: Phase;
disabled: boolean;
showOnboarding?: boolean;
theme: "dark" | "light";
}
```
And in the `DocumentPane` function body, destructure `theme` and pass it to `MarkdownEditor`:
```tsx
// BEFORE:
export function DocumentPane({
content,
onChange,
phase,
disabled,
showOnboarding,
}: DocumentPaneProps)
// AFTER:
export function DocumentPane({
content,
onChange,
phase,
disabled,
showOnboarding,
theme,
}: DocumentPaneProps)
```
```tsx
// BEFORE (in JSX):
// AFTER:
```
---
## TODO
- [x] **1.** `renderer/index.html` — change `minimal` to `Claude Flow`
- [x] **2.** `renderer/src/styles/globals.css` — full replacement with new CSS (monospace body, electric accent, 2px radii, uppercase labels, light theme block, focus glow, `.app-wordmark`, `.theme-toggle`)
- [x] **3a.** `renderer/src/App.tsx` — add `type Theme` alias
- [x] **3b.** `renderer/src/App.tsx` — add `theme` state + `useEffect` + `handleToggleTheme`
- [x] **3c.** `renderer/src/App.tsx` — pass `theme`/`onToggleTheme` to `Header`, pass `theme` to `DocumentPane`
- [x] **4.** `renderer/src/components/Header.tsx` — full replacement (new props, wordmark, toggle button)
- [x] **5a.** `renderer/src/components/DocumentPane.tsx` — add `syntaxHighlighting, defaultHighlightStyle` import
- [x] **5b.** `renderer/src/components/DocumentPane.tsx` — add `theme` to `MarkdownEditor` props
- [x] **5c.** `renderer/src/components/DocumentPane.tsx` — dynamic theme extension + `theme` in dep array
- [x] **5d.** `renderer/src/components/DocumentPane.tsx` — add `theme` to `DocumentPaneProps`, destructure, forward to `MarkdownEditor`
---
## Risks / Considerations
**CodeMirror reinitialization on theme switch**: Adding `theme` to the `useEffect` dependency array means the entire editor is torn down and recreated when the theme changes. This is intentional and correct — CodeMirror extensions are baked into the `EditorState` at creation time and can't be hot-swapped. The existing `content` sync `useEffect` will immediately restore the document contents after reinit, so no text loss occurs. There is a brief visual flash on theme toggle; this is acceptable.
**`data-theme` initial state and flash of wrong theme**: The `useState` initializer reads `localStorage` synchronously, and the `useEffect` sets `data-theme` on first render. Because this happens before paint (Electron loads the renderer in a hidden window and only shows it after load), there should be no flash of the wrong theme in production. In dev the Vite HMR setup may briefly show unstyled content; this is not a concern for shipping.
**Monospace font rendering differences per OS**: "SF Mono" ships with macOS/Xcode; "Cascadia Code" ships with Windows Terminal; "JetBrains Mono" and "Fira Code" are user-installed. The fallback chain is safe — `Monaco` is widely available on macOS, and `"Courier New", monospace` are universal final fallbacks. No font files are bundled; this is system-font-only.
**`Theme` type duplication**: The `type Theme = "dark" | "light"` alias is defined in both `App.tsx` and `Header.tsx`. This is a minor smell. If it grows to more places, move it into `renderer/src/types.ts`. For this task (2 files) the duplication is acceptable.
**Light mode CodeMirror gutter background**: The `.codemirror-editor .cm-gutters` rule uses `var(--bg-secondary)` which will automatically pick up the light-mode value — no extra change needed there.
**`select` element styling in light mode**: Native `