Design Notebook
Scaffold and run a design iteration notebook — a focused canvas that shows
one iteration at a time, with prev/next navigation, side-by-side comparisons
for divergent exploration, and a collapsible filmstrip drawer for visual
overview of every step.
Step 1: Choose Scaffold Path
Path A: Standalone project (no existing React framework)
Use this when the working directory is empty or has no React framework.
The template directory is at
relative to this SKILL.md file.
Use
commands to copy files — do NOT read and rewrite them.
bash
# Copy project config files
cp template/package.json template/tsconfig.json template/vite.config.ts template/index.html .
# Copy all source files
cp -r template/src .
# Copy AGENTS.md and symlink CLAUDE.md
cp template/AGENTS.md .
ln -s AGENTS.md CLAUDE.md
# Install dependencies and start dev server
npm install && npm run dev
Path B: Inject into existing React project
Each notebook gets a
slug — a lowercase-kebab-case name derived from
the user's topic (e.g. "nav redesign" →
). If the user
doesn't provide one, ask.
The harness (NotebookApp, chrome, state-explorer, etc.) is shared across
all notebooks. It lives in
src/design-notebooks/_harness/
and is copied
once. Each notebook only contains its own
,
, and
.
src/design-notebooks/
_harness/ ← shared, copied once from template/src
NotebookApp.tsx
chrome.tsx
state-explorer.tsx
types.ts
notebook.css
CLAUDE.md ← copied once
<slug>/ ← per notebook
main.tsx
index.css
types.ts ← re-exports from _harness/types
iterations/
index.ts
baseline/
The template directory is at
relative to this SKILL.md file.
Use
commands to copy files — do NOT read and rewrite them.
First notebook (sets up harness + first notebook):
bash
# Copy shared harness files
mkdir -p src/design-notebooks/_harness
cp template/src/NotebookApp.tsx template/src/chrome.tsx template/src/state-explorer.tsx template/src/types.ts template/src/notebook.css src/design-notebooks/_harness/
# Copy CLAUDE.md
cp template/AGENTS.md src/design-notebooks/CLAUDE.md
# Create the notebook
mkdir -p src/design-notebooks/<slug>/iterations
cp -r template/src/iterations/* src/design-notebooks/<slug>/iterations/
cp template/inject/main.tsx template/inject/index.css template/inject/types.ts src/design-notebooks/<slug>/
Additional notebooks (harness already exists):
bash
mkdir -p src/design-notebooks/<slug>/iterations
cp -r template/src/iterations/* src/design-notebooks/<slug>/iterations/
cp template/inject/main.tsx template/inject/index.css template/inject/types.ts src/design-notebooks/<slug>/
Then wire a framework-specific entry point using the slug (see table below).
Framework-specific entry point wiring:
| Framework | What to create | How to wire |
|---|
| Vite | design-notebooks/<slug>.html
at project root | Copy template/inject/entry.html
, replace with the notebook slug. Add to build.rollupOptions.input
in |
| Next.js App Router | app/design-notebooks/<slug>/page.tsx
that imports and renders NotebookApp from | No config changes needed — file-based routing |
| Next.js Pages Router | pages/design-notebooks/<slug>.tsx
that imports and renders NotebookApp from | No config changes needed — file-based routing |
| Remix | app/routes/design-notebooks.<slug>.tsx
that imports and renders NotebookApp from | No config changes needed — file-based routing |
| Astro | src/pages/design-notebooks/<slug>.astro
with <NotebookApp client:only="react" />
| No config changes needed |
For inject entry points (Next.js, Remix, Astro), create a page component that
imports
from
and renders
from
,
passing
and
from the notebook's
own
. For Next.js, add
directive.
Import paths: Check
/
for path aliases
(e.g.
,
). If the project has one configured, use it
(e.g.
@/design-notebooks/_harness/NotebookApp
). Otherwise use relative
paths from the entry point file.
Step 2: Set the Project Context
After scaffolding, ask the user what they're iterating on. Use their answer
to set the
metadata in
.
Populate the baseline (Path B only)
When injecting into an existing project, the baseline iteration MUST
render the project's actual components — do not rebuild or mock them.
- Import the real components into . The
project already has working UI; wrap it with any missing context
providers (e.g. theme, auth) so it renders correctly in isolation.
- Define 4-6 presets in that represent
the component's meaningful states (loading, error, empty, edge
cases, highlight modes). Look at the component's props and internal
state to identify what varies.
- Build fine-tuning controls in for any
continuous values (speeds, opacities, counts) or toggles.
The baseline must look identical to the live site. If it doesn't,
something is wrong.
Then begin the iteration workflow as described in AGENTS.md.
The Iteration Workflow
Once the notebook is scaffolded, follow the workflow documented in AGENTS.md
(which was placed in the project root during scaffolding). The core loop:
Refine or Diverge?
When the user requests a change, ask whether to refine the current iteration in-place or diverge into a new one. Small fixes (copy, spacing, colours) usually refine; new concepts or structural changes usually diverge.
Sharpen
Ask 2-3 clarifying questions before generating. Target: scope, tone,
constraints, reference points.
Diverge
Generate 3-4 variations as a
entry in ITERATIONS.
Each gets its own folder under
with
,
, and
.
Converge
User picks a direction. Mark with
, then generate next
iteration as a single entry building on the pick.
Repeat
Append to ITERATIONS, never delete. The notebook tracks all iterations
via filmstrip navigation.
Iteration Convention
Each iteration is a 3-file folder under
:
iterations/
baseline/
definition.ts # config, state shape, presets, resolvePreset
Content.tsx # the full mockup
controls.tsx # fine-tuning controls (FineTuning component)
v2/
definition.ts
Content.tsx
controls.tsx
When creating a new iteration,
copy the previous iteration's folder
(
cp -r iterations/baseline/ iterations/v2/
) and edit the copy.
Do not rewrite files from scratch — start from the last iteration and
modify what changed.
Each folder is a complete copy — duplicate components freely,
no shared primitives between iterations. However, iterations CAN
and SHOULD import components from the host project (Path B) — the
"no shared primitives" rule applies between iteration folders, not
between iterations and the project.
Register each iteration in
:
ts
import { baseline } from './baseline/definition'
import { v2 } from './v2/definition'
export const ITERATIONS: IterationDefinitionEntry[] = [baseline, v2]
Semantic Diffs
The
array describes
design shifts, not code changes.
Prefix with
(additions) and
(removals) for green/red coloring.
ts
changes: ['+ source citations', '+ favicon pills']
changes: ['+ guided questions from v4b', '− separate approaches']
Keep chips to 2-5 words. Name concepts, not implementation details.
Presets & State Explorer
Each iteration MUST define 4-6 presets as combo snapshots. This includes
the baseline — never ship an iteration with empty presets:
- Default / happy path
- Loading / in-progress
- Edge case (overflow, multi-turn)
- Error / degraded
- Empty / new
Build fine-tuning controls in
with a
component
that takes
props.
Working State
Before editing any
, add
to its
root
. Save immediately — HMR shows a shimmer overlay so the user
knows which iteration is being worked on. Remove when done.
Filmstrip & History
The filmstrip is a collapsible drawer toggled via the "History" button in
the header bar. It shows scaled thumbnails of all iterations with change
summaries on each card. Write summaries as past-tense outcomes:
- Single:
'Switched to dark palette, warm neutrals'
- Group:
'Tried 3 nav patterns: tabs, sidebar, floating'
- Converge:
'Picked sidebar nav, dropped tabs'