| name | desktop-uiux |
| description | Establishes a desktop design philosophy based on kickoff outputs, and generates a desktop design system/wireframes/Electron prototype. Recommended flow — /prd → /kickoff → /desktop-uiux |
| argument-hint | [PRD.md path (optional)] |
| disable-model-invocation | false |
| allowed-tools | Task, Read, Glob, Grep, Write, Edit, Bash, WebSearch |
Kit Preamble — desktop-uiux
Kit Script Root
Kit root: ${CLAUDE_PLUGIN_ROOT}
- Absolute path above → plugin install (substituted at load time; no project
scripts/ dir): prefix every kit script command with it, e.g.
bash <kit-root>/scripts/checkpoint.sh …. Absolute paths also work from worktrees.
- Literal
${…} placeholder above → standalone layout: run commands as written.
Project Context Detection
Run these checks silently at the start. Use results to adapt behavior:
[ -f issues.md ] — if true, this project uses the sprint system. Respect issue numbering and STATUS.md.
[ -f docs/sprint_state.md ] — if true and Status shows running, a sprint is active. Be aware of parallel work in worktrees.
[ -f docs/prd_digest.md ] — if true, read it for quick project context before starting.
Kit Rules
- Verify
gh auth status before any GitHub operation.
Prerequisites
/kickoff must be run first so that the following files exist:
docs/ux_spec.md (core input — IA, flows, screen inventory)
docs/requirements.md (functional/non-functional requirements)
docs/architecture.md (tech stack reference)
- The PRD file is supplementary reference. If kickoff outputs are missing, guide the user to run
/kickoff.
Algorithm
Phase 1 — Context Gathering
- Read kickoff outputs (required):
docs/ux_spec.md — extract screen inventory, IA, flows
docs/requirements.md — identify UI elements from functional requirements
docs/architecture.md — confirm tech stack, API endpoints
- Read PRD (
$ARGUMENTS or PRD.md) as supplementary context. If docs/prd_digest.md exists, read it for quick PRD summary.
- If
docs/ux_spec.md does not exist:
- Stop and tell the user: "Kickoff outputs are missing. Please run
/kickoff PRD.md first."
- Exception: if the user explicitly wants to skip kickoff, proceed with PRD only (warn about limited context).
- Check for existing shared assets:
docs/design_philosophy.md — check if already generated by web /uiux
docs/copy_guide.md — check if already generated by web /uiux
- Scan the project for existing desktop code:
- Glob for
**/electron/**, **/main.ts, **/preload.ts, **/electron-builder.*, **/forge.config.*, **/*.tsx, **/*.ts
- If found, read key files to understand current patterns, window management, and tech stack.
Phase 1.5 — Design Interview (conditional)
5.5) Check if docs/design_philosophy.md already exists AND contains a "Decision Matrix" section:
- If exists with Decision Matrix: Skip interview — reuse web decisions. Present to user for confirmation.
- If not exists or missing Decision Matrix: Run the Design Interview below.
Ask the user the following questions to anchor the design direction.
These answers become binding constraints for Phase 2.
Present all questions at once (not one-by-one) and wait for answers.
Also tell the user: "If any of these are hard to answer right now, just say 'skip'. You can also skip the entire interview."
a) Brand Personality: "If this product were a person, who would they be?"
(e.g., a luxury hotel concierge, a neighborhood cafe barista, a strict operating room nurse, a playful friend)
b) Emotional Target: "What one emotion do you want users to feel when they see the first screen?"
(e.g., trust, curiosity, relief, excitement, calm)
c) Anti-Reference: "What competing product or design should this absolutely NOT look like?"
(a feeling you want to avoid, or a specific product name)
d) Aspiration Reference: "Is there a product or brand you'd like to reference for design? (doesn't have to be the same domain)"
(e.g., Stripe's cleanliness, Nintendo's playfulness, Aesop's luxury)
e) Desktop Identity: "Should this app feel like a native part of the OS, or should it have its own distinct visual identity?"
(e.g., natural integration like a macOS native app vs distinct UI identity like Figma/Notion)
5.6) Handle user response:
Case A — User answers (partially or fully):
Record answers in memory — these become HARD CONSTRAINTS for Phase 2.
If the user skips individual questions, note them as "unconstrained" but still avoid generic defaults.
Case B — User skips the entire interview (says "skip", "pass", etc.):
- Do NOT silently proceed with generic defaults.
- Instead, the agent MUST auto-derive initial constraints from the PRD/UX spec:
a) Brand Personality → infer from target user personas and product category in PRD
b) Emotional Target → infer from the product's core value proposition
c) Anti-Reference → infer from competitor analysis in PRD (if any), otherwise mark "unconstrained"
d) Aspiration Reference → mark "unconstrained"
e) Desktop Identity → infer from product type (productivity tool → native feel, creative tool → branded)
- Present the auto-derived constraints to the user: "Since you skipped the interview, here's what I inferred from the PRD: [constraints]. Shall I proceed with these?"
- If approved, proceed with these as soft constraints (not hard).
- If rejected, re-offer the interview questions or accept corrections.
CHECKPOINT — MANDATORY — NEVER SKIP
Verify Phase 1 outputs: docs/ux_spec.md exists, PRD was read, interview answers (or auto-derived/reused constraints) are recorded.
If any required input is missing: STOP and report to user.
Phase 2 — Design Philosophy (conditional — CRITICAL before any code)
-
Check if docs/design_philosophy.md already exists:
- If exists: Read the file, present it to the user, and ask: "A design philosophy generated for the web version exists. Should I apply it to the desktop as well, or adapt it for desktop?"
- If approved: reuse as-is, proceed to Phase 3.
- If modification requested: create a desktop-adapted version, updating the philosophy while maintaining brand consistency.
- If not exists: Generate from scratch (same process as web
/uiux):
-
Analyze the product's identity from PRD and UX spec:
- Who are the users? What's the emotional tone?
- What category does this product belong to?
- Are there competitor/reference apps mentioned?
7.5) Reference Research — image-grounded only (NO WebFetch for visual extraction).
WebFetch returns parsed text, not pixels. Asking the model to extract hex values or sidebar proportions from a Dribbble URL via WebFetch is fabrication. Visual references MUST arrive as actual images.
Pick exactly ONE of three paths:
Anti-reference: WebSearch for anti-reference titles is acceptable. Anti-cues are written from the model's own knowledge.
Synthesis (when Path (a) or (b) ran — output goes into docs/design_philosophy.md "Reference Anchors"):
- 2–3 strong cues to adopt, each as: cue (≤12 words) — exact value or token (e.g.,
sidebar 240px @ #0E0F12, JetBrains Mono 13 + Inter 13, title bar 28px frameless with traffic lights inset 12/12) — source image path under docs/references/ OR user-provided image URL/path. Strong = present in the chosen images, specific enough that no Phase 5 implementer can fall back to a generic Electron/Material default. Fewer-and-deeper beats more-and-shallow.
- 1 literal quote (MANDATORY when Phase 1.5 interview was NOT skipped): a specific word, number, glyph, or shortcut drawn from the brand or domain that MUST appear verbatim in the rendered prototype. Format:
literal_quote: "<exact string>" — <where it appears>. Desktop-friendly examples:
literal_quote: "⌘K" — command palette trigger shown in the sidebar
literal_quote: "47.2-A" — sample order ID, mono on the order detail panel
literal_quote: "조용한" — set in 96pt Inter Display, splash screen
- Reject abstract concepts (
"luxury", "power user") — the literal quote is text/glyph/shortcut the prototype renders.
- 3–5 cues to explicitly avoid, each with one-line reason tied to the anti-reference.
- Each adopted cue must be specific enough that a Phase 5 implementer cannot fall back to a generic Electron/Material default. Prose-only cues are rejected.
- Never invent hex / font / sizing values without an image to point at. Mark uncertain extractions with
≈ and cite the source image.
Verbatim render check — Phase 5B is required to render the literal_quote string verbatim in at least one screen file under prototype-desktop/. The Phase 2 CHECKPOINT below verifies the field is populated; Phase 5B verifies it appears in rendered output.
-
Commit to a BOLD aesthetic direction with desktop lens:
- Apply the desktop design lens: information density, keyboard workflow, multi-window experience
-
Generate docs/design_philosophy.md:
- Named aesthetic (2-3 words)
- 2-3 paragraphs: how the philosophy manifests through space/form, color/material, scale/rhythm, composition
- Signature Move (MANDATORY — the single biggest anti-slop anchor): one specific, non-default desktop visual decision with exact numeric values or token names that MUST appear on every screen of the prototype. Must be:
- Numeric or token-named (px / % / deg / ms /
var(--token)) — never prose-only.
- Implementable in CSS or React via 1–3 properties on a reusable class/component.
- Visible on every screen/panel, not just splash or settings.
- Bad (rejected — too soft): "Information-dense", "Keyboard-first", "Pro tool feel"
- Good desktop examples:
- "Active row in any list/table gets
border-left: 3px solid var(--accent) and background: var(--accent-10) — never full-row highlight"
- "All panel headers use
text-transform: uppercase, letter-spacing: 0.08em, JetBrains Mono 11 — never sentence case"
- "Command palette:
clip-path: polygon(...) notched bottom-right corner, 480×320 fixed — never plain rounded rectangle"
- "Sidebar split:
grid-template-columns: 240px 1fr with a 1px hairline divider in --border-strong, no shadow"
- "Title bar: 28px frameless with traffic lights inset 12/12, app icon at 16px — never default window chrome"
- Reference Anchors section (from step 7.5 image-grounded research): 2–3 strong adopted cues each citing an image (path under
docs/references/ or a user-provided image URL/path), 1 literal_quote: field (mandatory unless Phase 1.5 was skipped), 3–5 avoided cues with reasons. If step 7.5 took Path (c) and skipped this section, omit it here too and proceed.
- What makes this design UNFORGETTABLE (should align with and reinforce the Signature Move).
-
Present the design philosophy to the user and ask for approval before proceeding.
- If rejected, iterate on the direction.
CHECKPOINT — MANDATORY — NEVER SKIP
Verify docs/design_philosophy.md exists with:
(a) a Signature Move that is numeric/token-specific (not prose-only);
(b) either a populated Reference Anchors section OR an explicit "Reference Anchors skipped (no image input)" line; AND
(c) when Reference Anchors is present, exactly 2–3 adopted cues (not 1, not 4+), each citing an image path, plus a literal_quote: field with a concrete word/number/glyph/shortcut (NOT an adjective like "luxury"). The literal_quote may only be omitted if Phase 1.5 interview was explicitly skipped — in which case literal_quote: (skipped — interview not run) must appear instead of the field being absent.
If any of (a) / (b) / (c) fails: STOP and fix before proceeding.
Phase 3 — Desktop Design System
- Generate
docs/design_system_desktop.md reflecting the chosen aesthetic:
- Color palette: TypeScript/CSS token objects. Dominant colors with sharp accents. Strong dark mode optimized for long work sessions, reduced eye strain.
- Typography: System fonts (SF Pro/Segoe UI/Ubuntu) or custom. Wider modular scale (1.25 or 1.333 — large screens can afford dramatic jumps). Monospace for code/data views. Minimum 12px allowed (desktop precision).
- Spacing: 4px-based scale (xs:4, sm:8, md:12, lg:16, xl:24, xxl:32, xxxl:48, xxxxl:64) + large-scale tokens for panel gaps, sidebar width, toolbar height
- Components: Desktop-specific — Sidebar, Split Pane, Command Palette, Context Menu, Toast/Notification, Data Table, Tree View, Tab Bar, Toolbar, Status Bar, Dialog/Modal, Breadcrumb, Dropdown Select
- States: default, hover, active, focus, disabled, loading (hover IS included for desktop!)
- MUST include: Text Input (focus/error/placeholder/character count), Keyboard Shortcut Badge, Resizable Panel, Search/Filter Bar
- MUST include: Data Table patterns (sortable headers, row selection, virtual scrolling, column resize)
- MUST include: Window chrome spec (title bar, traffic lights/window controls, frameless vs custom)
- Keyboard shortcuts tokens: Cmd/Ctrl modifier mapping per platform (
darwin→Cmd, win32/linux→Ctrl)
- Window chrome: Title bar customization (frameless or custom titlebar), traffic light / window control integration, draggable regions
- Motion tokens: Duration (micro 60-100ms to large 300-500ms, max 700ms), easing curves, transition types. Faster and more restrained than web — desktop is efficiency-first.
- GPU-composited only: All motion tokens MUST target
transform, opacity, or filter. NEVER animate layout properties (width, height, top, left).
will-change budget: Max 5 concurrent elements with will-change. Overuse creates GPU memory pressure. Apply on interaction start, remove on end.
- SplitPane resize strategy: Prefer CSS flexbox/grid
fr units over JS-driven width changes. If JS-driven, throttle via requestAnimationFrame.
- Dark/Light mode:
nativeTheme integration, system preference detection, manual override
- Platform tokens:
darwin/win32/linux keys for platform-specific values (fonts, shortcuts, window chrome, file paths)
- All values expressed as TypeScript objects AND CSS custom properties
- Ask the user if the design system direction looks right before proceeding.
Phase 4 — Wireframes & Interaction Spec
- Generate
docs/wireframes_desktop.md:
- Window layout architecture (single window vs multi-window, sidebar+content+panel structure)
- Screen inventory with window position and panel assignment
- Per-screen details: window context, panel layout, resize behavior, layout zones (sidebar/toolbar/content/panel/statusbar), components, states (default/loading/empty/error), keyboard focus order
- Numeric layout commitments (MANDATORY): per screen/window, declare exact CSS Grid/Flex values, not prose:
grid-template-columns or column ratios — e.g., 240px 1fr 320px (sidebar / content / inspector)
- Resize constraints — min/max widths per panel as exact px, snap zones in px
- Toolbar height, sidebar header height, status bar height as exact px
- Gap / gutter — e.g.,
gap: 1px (for hairline-divided panels) or gap: 16px (for spaced panels)
- Window chrome offsets — e.g.,
traffic lights at top: 12px left: 12px, custom title bar height 28px
- Density token — e.g.,
row height: 28px, cell padding: 6px 12px (compact) vs 40px / 12px 16px (comfortable)
- Per-window-size overrides at min-width / comfortable / max — list only the values that change
- Reject prose-only layout phrases ("information-dense", "spacious layout"). Re-state every layout description with at least one numeric value tied to a CSS property.
- Multi-window configuration: main window, auxiliary windows (settings, inspector, detached panels), window-to-window communication patterns
- Responsive behavior per window size (min-width, comfortable, max/full-screen)
- Generate
docs/interactions_desktop.md:
- User flows with trigger (click/keyboard shortcut/drag/context menu/system tray), steps with animation, system integration
- Keyboard shortcut map: complete mapping of all shortcuts, organized by category (file, edit, view, navigation, custom), platform variants (Cmd vs Ctrl)
- Command Palette flow: activation (Cmd+K), search/filter behavior, action execution, recent items
- Drag & Drop spec: file system ↔ app (drop zone styling, file type validation, progress feedback), intra-app drag (reorder, move between panels)
- Context menu spec: right-click menus per context (sidebar item, content area, table row, tab), keyboard activation (Shift+F10 or Menu key)
- Focus management: tab order, focus trap in modals/dialogs, focus restoration on close, skip navigation
- Window interactions: resize behavior (min/max constraints, content reflow), snap zones, multi-monitor support
- System tray integration: icon, tooltip, context menu, notification badge
- State management: loading (skeleton/spinner), empty, error (with retry), permission prompts
- App launch choreography (cold start): splash window (lightweight BrowserWindow) → main window create → skeleton UI → data hydration → interactive. Target: under 3 seconds to interactive.
- Background task lifecycle: system tray persistence, graceful shutdown, auto-update flow
- Accessibility: screen reader support, keyboard-only navigation, high contrast mode, reduced motion
Phase 4.5 — Copy Guide (conditional)
- Check if
docs/copy_guide.md already exists:
- If exists: Read the file. Check if it already has a
## Desktop Adaptations section.
- If no desktop section: append a
## Desktop Adaptations section covering:
- Menu bar labels (File, Edit, View, Window, Help — platform conventions)
- Keyboard shortcut hint text (tooltip format, menu item format)
- System notification copy (title, body, action buttons — OS notification constraints)
- Dialog copy (confirmation dialogs, destructive action warnings, save/discard patterns)
- Status bar messages (connection status, sync status, background task progress)
- Context menu labels (concise, action-oriented, with shortcut hints)
- Command Palette action labels (verb + noun pattern)
- If desktop section exists: review and update if needed.
- If not exists: Run the copywriter agent to generate
docs/copy_guide.md:
- Input:
docs/ux_spec.md, docs/design_philosophy.md, docs/wireframes_desktop.md, docs/interactions_desktop.md, PRD
- Output: Voice & tone definition, copy inventory per screen, patterns, glossary, desktop adaptations section
- Include FULL CONTENT of input documents in the subagent prompt.
- This step MUST complete before Phase 5 so the prototype uses real copy.
- Banned copy tells (enforce on every string): zero em-dashes (
—/–) — use -, comma, period, or colon; no filler verbs (Elevate, Seamless, Unleash, Next-Gen, Revolutionize); no generic person names (John Doe) or startup-slop brand names (Acme, Nexus, SmartFlow); no fake-perfect numbers (99.99%, round 50%) — use organic values. See "Specific AI Tells" in Anti-AI-Slop Rules.
16-a) Accessibility labels (REQUIRED): Ensure copy_guide.md includes aria-label for EVERY interactive element (buttons, inputs, menus, panels, dialogs). Also include keyboard shortcut announcements for screen readers.
CHECKPOINT — MANDATORY — NEVER SKIP
Verify docs/design_system_desktop.md, docs/wireframes_desktop.md, docs/interactions_desktop.md, and docs/copy_guide.md all exist.
Cross-check: every component in wireframes has a definition in design_system_desktop.md.
If any output is missing: STOP and generate it before proceeding.
Phase 5 — Electron Prototype
- Create the
prototype-desktop/ directory structure:
prototype-desktop/
package.json
tsconfig.json
.gitignore
electron/
main.ts (main process)
preload.ts (preload script)
src/
types/
index.ts (shared types)
theme/
tokens.ts
colors.ts
spacing.ts
typography.ts
components/
Sidebar.tsx
CommandPalette.tsx
SplitPane.tsx
ContextMenu.tsx
DataTable.tsx
... (as needed per design system)
screens/
... (one .tsx per screen from wireframes)
App.tsx
main.tsx (renderer entry)
index.html
- Generate
prototype-desktop/package.json:
- Required dependencies (MUST include all of these):
electron — runtime
react, react-dom — framework
typescript — language
vite, @vitejs/plugin-react — bundler
electron-builder or @electron-forge/cli — packaging
- Required dev dependencies:
@types/react, @types/react-dom — type definitions
electron-vite or vite-plugin-electron — Electron + Vite integration
- Scripts:
dev (development with hot reload), build (production build), preview (preview build)
- Bundle optimization: Configure Vite to externalize Electron built-in modules (
electron, path, fs). Use build.rollupOptions.output.manualChunks to split vendor libraries (react, react-dom) from app code.
- After generating package.json, run:
cd prototype-desktop && npm install to install dependencies
17-a) Generate prototype-desktop/tsconfig.json:
- Strict mode enabled
- JSX: react-jsx
- Module resolution: bundler
- Path aliases for
@/ → src/
17-b) Generate prototype-desktop/.gitignore:
- Standard Electron gitignore: node_modules, dist, dist-electron, out, .vite, *.log
17-c) Generate
prototype-desktop/electron/main.ts:
- BrowserWindow creation with appropriate defaults (width, height, webPreferences)
- Preload script path configuration
- App lifecycle (ready, window-all-closed, activate)
- Menu bar setup (platform-aware: darwin vs win32/linux)
- Optional: system tray setup if specified in wireframes
- Cold start optimization: Show a lightweight splash BrowserWindow immediately on
ready, then create the main window in background. Swap when renderer is ready (did-finish-load).
- Main process hygiene: NEVER run heavy I/O (file read, DB query, network) on the main process event loop. Offload to
utilityProcess (Electron 22+) or Node worker_threads.
backgroundThrottling: false only for windows that need real-time updates; leave default (true) for auxiliary windows to save resources.
17-d) Generate prototype-desktop/electron/preload.ts:
- contextBridge.exposeInMainWorld for IPC
- Type-safe API exposure
- Preload weight: Keep preload script minimal — only expose IPC bridge functions. Heavy logic belongs in the renderer bundle.
17-e) Generate
prototype-desktop/index.html:
- Minimal HTML shell for Vite + React entry
- Generate
prototype-desktop/src/theme/:
colors.ts — color palette from design system, dark/light mode tokens
spacing.ts — spacing scale + large-scale tokens (panel gaps, sidebar width)
typography.ts — font families, modular scale, platform-specific fonts
tokens.ts — re-exports all theme tokens + shadows, radii, motion config, keyboard shortcut tokens
- Generate
prototype-desktop/src/components/:
- Reusable components matching the design system
- Each component uses theme tokens, supports all 6 states (default, hover, active, focus, disabled, loading)
- Keyboard navigation support on every interactive component
- Context menu integration where specified
- Signature Move encoding (MANDATORY): the Signature Move from
docs/design_philosophy.md MUST be implemented as a reusable component/class/CSS-custom-property primitive. It must be importable from any screen — not duplicated per-screen.
19.5) PHASE 5A — Pilot screens & gate (multi-archetype, catches AI slop before full generation):
- Step 1 — Archetype classification & pilot pick:
- Classify every screen in docs/wireframes_desktop.md into one of these desktop archetypes: list/table, detail/inspector, form/settings, hub/dashboard, command-palette/overlay, editor/canvas, empty/cold-start.
- Pick TWO pilot screens from the two most-distinct archetypes present in the inventory (typically one consumption + one input, e.g., data table + settings, or editor + command palette). If only one archetype exists, fall back to a single pilot and note it.
- Step 2 — Pilot-only generation:
- Generate ONLY the 2 pilot .tsx files in prototype-desktop/src/screens/.
- Generate a TEMPORARY minimal prototype-desktop/src/App.tsx that routes ONLY between the 2 pilots (no full router yet).
- Ensure the Electron main.ts and preload.ts from step 17-c/17-d are wired so npm run dev launches the pilot view.
- Do NOT generate the remaining screens or the full router yet.
- Step 2.5 — PILOT GATE — observe → critique → specificity → auto-correct → user HOLD
Generator-as-judge fails: the same context that produced the pilot will not reliably catch its own slop. This block routes critique through a separate sub-agent context and runs up to 3 auto-correction cycles before presenting.
Desktop pilots run live in Electron (npm run dev). If Playwright + Electron is installed, screenshot the rendered window for the critique inputs. Otherwise critique runs against pilot .tsx source (degraded mode) — record pilot_degraded: no_playwright_electron in the critique log.
- **Step 2.5.0 — Neutral observation** (mandatory; BEFORE judgment).
For each pilot, write 5 plain factual statements about what renders (screenshot) or what the source would render (degraded).
**Banned vocabulary**: `signature move`, `aesthetic`, `archetype`, `philosophy`, `direction`, `taste`, `slop`, `generic`, `bold`, `restrained`, `premium`, brand names, the chosen aesthetic name. Use only colors, sizes, shapes, positions, counts, content categories.
Save to `prototype-desktop/src/screens/<pilot>.observations.md`.
- **Step 2.5.1 — Separate-context critique** (mandatory). Invoke `design-auditor` via the Task tool. **Do NOT inline-critique in the generator's context.**
Pass:
- the pilot screenshot path (if available) AND the pilot `.tsx` path
- `prototype-desktop/src/screens/<pilot>.observations.md`
- `docs/design_philosophy.md`
- `docs/design_system_desktop.md`
Ask for a 6-axis 1–5 score (Philosophy / Hierarchy / Execution / Specificity / Restraint / Variety), one cited evidence per axis referencing observation indices, and a list of slop signals.
Where ui-reviewer's scope applies (state coverage, copy usage), invoke `ui-reviewer` separately. Disjoint scopes (ISSUE-013) — surface both outputs.
Save the structured output to `prototype-desktop/src/screens/<pilot>.critique.md`.
- **Step 2.5.2 — Specificity check** (mandatory). Ask design-auditor:
*"Name 3 details visible in this pilot that ONLY make sense for THIS specific product / domain / user. Generic UI primitives don't count. Domain content does count (real entity names, the literal_quote from Reference Anchors, brand-specific shortcuts/units). Fewer than 3 → FAIL."*
The literal_quote (from ISSUE-012) counts as exactly **1** of the 3.
- **Step 2.5.3 — Auto-correction cycle** (hard cap N=3). If any score < 3, specificity FAIL, or slop signals fire:
1. Identify the patch layer (philosophy / system / layout / pilot only).
2. Apply the patch.
3. Re-observe → re-critique → re-specificity.
4. Increment cycle counter. Append to `prototype-desktop/src/screens/<pilot>.cycles.log`:
`cycle N: layer=<L> change="<summary>" scores=P5 H4 E5 S3 R5 V4 specificity=PASS|FAIL`.
5. **Hard stop at N=3.** After cycle 3, freeze and surface to the user with the full history.
Record final scores at the top of the pilot stylesheet/screen file: `/* pre-emit critique cycle=N: P5 H4 E5 S4 R5 V5 specificity=PASS */`.
- **Step 3 — PILOT GATE — present and HOLD for user**:
- Tell the user how to run:
```bash
cd prototype-desktop && npm run dev
```
- Share `prototype-desktop/src/screens/<pilot>.critique.md` and `<pilot>.cycles.log`.
- If Step 2.5 entered degraded mode (no Playwright/Electron), say so explicitly.
- Ask: "Please run the pilots and confirm:
(a) Is the **Signature Move** (`<paste exact text>`) visible and applied on both pilots?
(b) Do both pilots feel like `<aesthetic name>` and read as the same family across the two archetypes?
(c) Do the 3 product-specific details from the specificity check belong to *this* product?
(d) Any slop signals — Electron-wrapper-website feel, default OS chrome, generic Material/Fluent components, mobile-touch-sized targets?"
- WAIT for explicit approval before continuing to Phase 5B.
- **Step 4 — On rejection** (route to the correct layer):
- Signature Move wrong/absent → revisit Phase 2 step 9.
- Color / type / density tokens off → revisit Phase 3 design system.
- Layout reads as generic → revisit Phase 4 numeric layout commitments.
- Tokens are right but pilot implementation is generic → fix the pilot `.tsx` and components only.
- Do NOT proceed to Phase 5B with an unaddressed pilot rejection.
Phase 5B — Full Prototype (after pilot approval)
- Generate remaining screen files in
prototype-desktop/src/screens/:
- One .tsx file per remaining screen from wireframes (the 2 pilots are already done).
- Use the approved pilots as the visual template — match their component usage, density, Signature Move application, keyboard patterns. Do not re-explore the aesthetic mid-prototype.
- Uses design system components and theme tokens
- Implements all states: default, loading (skeleton), empty, error
- Uses actual copy from
docs/copy_guide.md
- Keyboard shortcut bindings per screen
- Code splitting: Secondary screens and heavy panels (settings, inspector) MUST use
React.lazy + Suspense to avoid loading everything upfront
- Signature Move per-screen check: every screen must reference the Signature Move's reusable primitive at least once.
- Replace the temporary App.tsx from step 19.5 with the full
prototype-desktop/src/App.tsx:
- Router setup (react-router or custom)
- Theme provider (dark/light mode with system preference detection)
- Keyboard shortcut global handler
- Window chrome / custom title bar integration
- IPC pattern: All renderer→main IPC calls go through a single typed API layer (from preload). Batch rapid-fire calls (e.g., window resize events) with debounce/throttle. NEVER send large objects over IPC — use references or chunked transfer.
- Memory cleanup: Register cleanup in
useEffect returns for event listeners, IPC subscriptions, and timers. Use AbortController for fetch calls.
- Generate
prototype-desktop/src/main.tsx:
- React DOM entry point
- Root render with StrictMode
Phase 5.5 — Prototype Verification (REQUIRED before presenting to user)
- Electron project setup check:
package.json has correct scripts (dev, build)
electron/main.ts exists with proper BrowserWindow setup
electron/preload.ts exists with contextBridge
index.html exists as renderer entry
tsconfig.json exists with strict mode
.gitignore exists
- Token compliance check:
- Scan all files in
src/screens/ and src/components/ for hardcoded style values
- Every color, spacing, font size, border radius, and shadow MUST use imports from
src/theme/
- Fix any hardcoded values found before proceeding
- Screen coverage check:
- Count screens defined in
docs/wireframes_desktop.md
- Count .tsx files in
src/screens/
- Every wireframe screen (except explicitly P2+ deferred screens) MUST have a corresponding screen file
- State coverage check:
- Every screen MUST implement at least default + one additional state (loading, empty, or error as applicable)
- Empty state MUST use copy from
docs/copy_guide.md, not placeholder text
- Keyboard navigation check:
- Every interactive component MUST be keyboard-accessible (tab focus, enter/space activation)
- Command Palette (Cmd+K / Ctrl+K) MUST be implemented if specified in design system
- At least 5 keyboard shortcuts from
docs/interactions_desktop.md MUST be functional
27.3) Contrast sweep (CRITICAL — catches the failures that ship most):
- For every
(color, background-color) pair on a screen, verify the WCAG ratio against its computed background: body text needs ≥ 4.5:1; large text (≥24px / ≥18px bold), icons, and focus rings need ≥ 3:1.
- Fail on any of: button text ≈ button fill (text within ~5% lightness of fill — the black-on-black bug);
--color-accent filling a text-bearing surface without a defined, verified --color-accent-ink; any dark panel (background lightness < 50%) that did not flip its text colour (ink-on-ink). Most-missed: text in a panel that switched background but inherited color; muted text on a tinted surface.
- List failing pairs as
file:selector, fix, and re-check before proceeding.
27.4) Slop-proof mechanics sweep (deterministic — grep .css/theme/screens):
- Flag and fix:
transition: all / transition-all; bare 1fr tracks on image-bearing grids (must be minmax(0, 1fr)); font-style: italic on heading/display selectors; a second position: sticky; top: 0; all-caps display with line-height < 1.0.
- Confirm present:
overflow-x: clip on html+body; input/select fields satisfy the 8-state rules (constant border-width, outline-based focus ring, reserved helper slot, multi-channel disabled) from Anti-AI-Slop "CSS mechanics (renderer)".
- Match patterns whitespace-insensitively (normalize spaces first, and ignore matches inside CSS comments):
transition:all ≡ transition: all, top:0 ≡ top: 0, overflow-x:clip ≡ overflow-x: clip.
- List violations as
file:line, fix, and re-sweep.
27.5) Signature Move check:
docs/design_philosophy.md must contain a Signature Move with numeric/token specificity (not prose-only).
- The Signature Move must be implemented as a reusable component/class/CSS-custom-property primitive under
src/components/ or src/theme/.
- Every
.tsx file in src/screens/ (including the pilots) must reference that reusable Signature Move primitive at least once.
- If any check fails: list violations, fix, and re-verify before proceeding.
27.6) Literal quote verbatim render check (skip if Phase 1.5 was explicitly skipped):
- Read
literal_quote: from docs/design_philosophy.md Reference Anchors.
- Grep
src/screens/*.tsx for the literal string. The string MUST appear verbatim in at least one screen file (inside a string literal, NOT inside a comment).
- If absent: name the screens that would naturally host it (per the anchor's "where it appears" hint), inject the quote into that screen, and re-grep. Do not skip by widening the search.
- Example:
literal_quote: "⌘K" MUST appear as the literal characters ⌘K — not Cmd+K, not interpolated from a variable, not inside {/* */}.
- Performance check:
- List/table item components MUST use
React.memo
- Event handlers passed to memoized children MUST use
useCallback
- Large data sets MUST use virtualization (e.g., react-window or tanstack-virtual)
- Secondary screens/panels MUST use
React.lazy + Suspense for code splitting
- Animations MUST only use GPU-composited properties (
transform, opacity, filter) — never animate width, height, top, left
will-change MUST NOT be applied to more than 5 elements simultaneously (excessive use increases memory)
- CSS
contain: layout style paint SHOULD be applied to independently-updating panels (sidebar, content, detail)
- SplitPane resize MUST use
requestAnimationFrame throttle or CSS-based resize (flexbox/grid) — never unthrottled mousemove
- IPC & memory check:
- Main process MUST NOT contain synchronous file I/O or heavy computation
- Preload script MUST be lightweight — only IPC bridge, no business logic
- Rapid IPC calls (resize, scroll, drag) MUST be debounced/throttled
- All
useEffect hooks MUST return cleanup functions for event listeners, IPC subscriptions, and timers
- Multi-window: auxiliary BrowserWindows MUST set
backgroundThrottling: true (default) unless real-time updates are required
- Bundle size check:
- Renderer bundle SHOULD be under 500KB gzip (excluding node_modules externalized by Vite)
- Vendor chunk (react, react-dom) MUST be split from app code via
manualChunks
- Electron built-in modules (
electron, path, fs) MUST be externalized, not bundled
30.5) AI Tell sweep (CRITICAL):
- Sweep every
.tsx/.css file in src/screens/, src/components/, and theme/style files for the banned tells in "Specific AI Tells" (Anti-AI-Slop Rules): em-dash (—/–) in any string literal, flex calc() column math, generic person/brand names, fake-perfect numbers, section-number eyebrows, decorative version labels, <div>-based fake product UI, decorative status dots, locale/time strips.
- List every violation as
file:line, fix it, and re-sweep. Zero tolerance on em-dash and div-based fake product UI — these must be 0 before presenting. Match CSS patterns whitespace-insensitively (height:100vh ≡ height: 100vh).
Phase 6 — Review & Iterate
- Present deliverables summary to the user:
- Iterate based on user feedback:
- Modify specific screens, adjust design system, add missing states
- Each iteration updates both docs and prototype files consistently
- If aesthetic direction needs major change, go back to Phase 2
Shared Registry Files
- None. This skill produces standalone deliverables — no
issues.md or STATUS.md updates.
- Since
/kickoff has already created issues, if additional UI/UX-related issues are needed, add them manually to issues.md or re-run /kickoff.
Error Handling
- If
docs/ux_spec.md not found: stop and suggest running /kickoff first (unless user explicitly opts to skip).
- If PRD file not found: stop immediately, report missing path.
- If
docs/ cannot be created: stop and report filesystem error.
- If existing desktop code uses a different framework (Tauri, CEF, native): adapt the prototype to match that framework instead of defaulting to Electron. Note the framework in
docs/design_system_desktop.md.
- If PRD is too vague for desktop UI design (no user stories, no features): ask the user targeted questions about screens and user flows before proceeding.
Rollback
- This skill is additive (writes new files/directories). No destructive rollback needed.
- Re-running
/desktop-uiux overwrites all outputs — safe to retry.
- Prototype directory (
prototype-desktop/) can be safely deleted if not needed.
Anti-AI-Slop Rules (CRITICAL)
These rules prevent Claude from converging on generic, forgettable desktop defaults.
Primary anchor — the Signature Move. The single most effective slop-blocker is the numeric/token-specific Signature Move defined in Phase 2 step 9 and enforced at the Phase 5A pilot gate (step 19.5) and Phase 5.5 step 27.5. Negative rules below are secondary; if the Signature Move is weak or missing, the rules below will not save the output.
NEVER:
- A web app wrapped in Electron with browser-like UI (address bar feel, no native integration)
- Touch-target-sized buttons on desktop (48px buttons waste screen real estate)
- Mobile hamburger menu on desktop (you have a full menu bar and sidebar)
- Pro tools without keyboard shortcuts (desktop users expect keyboard efficiency)
- Ignoring the system menu bar with only a custom in-app menu
- Single-window-only design when the content naturally benefits from multi-window
- Ignoring OS theme preferences (light/dark mode, accent color)
- Generic placeholder illustrations for empty states
- Electron apps that feel like a website in a frame
INSTEAD:
- Native window controls integrated with custom title bar (platform-aware traffic lights / window buttons)
- Information density that leverages the large screen — sidebars, split panes, data tables, tree views
- Keyboard-first interaction: every action reachable via shortcut, Command Palette for discoverability
- Multi-window support for workflows that benefit from side-by-side views
- OS theme integration via
nativeTheme — automatic dark/light switching
- System tray presence for background tasks, notifications, quick actions
- Context menus that match OS conventions while expressing app personality
- Desktop-appropriate component sizing: smaller click targets (24-32px), denser spacing, more visible information
Specific AI Tells (hard bans — sweep every screen before presenting).
Concrete signatures LLMs default to. Banned unless the brief explicitly calls for one.
Content & data:
- Generic person names ("John Doe", "Sarah Chan") or startup-slop brand names ("Acme", "Nexus", "SmartFlow", "Cloudly") → invent contextual, locale-appropriate, real-sounding names.
- Fake-perfect numbers (
99.99%, round 50%, 1,234,567) → organic messy values (47.2%, +1 (312) 847-1928).
- Filler verbs ("Elevate", "Seamless", "Unleash", "Next-Gen", "Revolutionize") → concrete verbs only.
- Em-dash (
—) and en-dash-as-separator (–): zero tolerance in all visible text (titles, labels, menu items, body, empty/error copy). Use a regular hyphen -, comma, period, colon, or line break. The single most-violated tell.
Fake product UI:
- NEVER fake a product surface out of styled
<div> rectangles (fake chart, fake terminal, fake data table) to fill a welcome/empty screen. Use a real screenshot, generated image, real component, or skip it.
- No fake version footers / sync stamps (
v0.6.2-rc.1, last sync 4s ago) as decoration (a real app-version readout in About/status bar is fine).
Decorative meta:
- No section-number eyebrows (
001 · Capabilities) or 01 / 4 pagination labels — name the topic in plain language.
- No version labels (
V0.6, BETA, EARLY ACCESS, ALPHA) as decoration unless the brief is explicitly a launch/preview.
- No decorative status dots before every list row/tab/badge (only for real semantic state, sparingly).
- No locale/time/weather strips (
Lisbon 14:23 · 18°C) or mono-caps decoration strips (BRAND. MOTION. SPATIAL.) as chrome.
- Ration the middle dot
· to max 1 per metadata line; never as a universal separator.
Typography & interaction tells:
- No italic headings.
font-style: italic on h1–h6 / display / wordmark / <em> inside a heading is a top tell. Emphasis = weight, accent colour, or a drawn underline. Italic only inside running body copy.
- No celebratory success toast for an action whose effect is already visible (silent success; reserve toasts for failures and invisible/background effects).
- Tooltip delays differ by input: hover delays 800–1000ms, keyboard focus shows at 0ms (never equal).
- Auto-rotating content (carousel, banner, ticker) must pause on hover AND focus (WCAG 2.2.2).
CSS mechanics (renderer) — deterministic, all mandatory:
- Multi-column / split-pane layouts: use CSS Grid (
grid-template-columns), NEVER flex percentage math (width: calc(33% - 1rem)), which breaks on gap rounding.
overflow-x: clip on BOTH html and body (use clip, not hidden — preserves descendant sticky/fixed); no horizontal scroll at any window width down to 320px.
- Any grid track holding an image uses
minmax(0, 1fr), never bare 1fr.
- Display headers set
overflow-wrap: anywhere; min-width: 0; all-caps display type uses line-height ≥ 1.0.
- At most ONE
position: sticky; top: 0 (the top chrome/toolbar); other sticky elements offset to top: var(--banner-height) with a lower z-index than the toolbar.
- Flex rows mixing height-different children set
align-items: center.
- No
transition: all / transition-all — name properties. Focus rings appear instantly (no transition on outline) and use outline, never border. Reserve overshoot easings for drag/physical interactions only.
- Input/select 8-state rules: constant
border-width across states (change outline/box-shadow/border-color); outline-based focus ring; input height == adjacent button height; reserve helper/error slot with min-height: 1lh; disabled = opacity + cursor: not-allowed + disabled/aria-disabled (never opacity alone).
Guidelines
- Electron + React + TypeScript first: Prototype targets Electron with Vite for fast development. Main/renderer process separation is mandatory.
- No mobile patterns: No bottom sheets, no swipe gestures as primary navigation, no hamburger menus. Use desktop idioms (menu bar, sidebar, split pane, context menu).
- Accessibility first: aria-label, aria-role, keyboard navigation, focus management, screen reader support.
- Multi-platform aware: Design for macOS, Windows, and Linux. Use platform tokens for OS-specific behaviors (Cmd vs Ctrl, traffic lights vs window buttons, system fonts).
- Realistic content: Domain-appropriate placeholder text, not lorem ipsum.
- Intentional design: Every choice (font, color, spacing, shortcut, animation) must serve the design philosophy. No defaults.
- Shared assets: Reuse
docs/design_philosophy.md and docs/copy_guide.md from web /uiux when they exist. Don't duplicate, extend.