# CHUNK #5 — Plot & Whiteboard **Duration:** ~3 days · **Prereqs:** CHUNK #2 (entity storage) · **Follows:** CHUNK #4 · **Unblocks:** CHUNK #9 (AI reasons over plot structure) **Purpose:** Give authors three ways to see and shape their story's structure — a beat board with genre templates, a configurable timeline, and a free-form whiteboard — all backed by React Flow 12 and all linked to chapters and entities. After this chunk, plot structure is first-class and the whiteboard handles 200+ nodes at 60 fps. --- ## Steps ### 1. Beat board (`apps/web/src/features/plot/`) 1. **Beat editor** (`BeatEditor.tsx`): a beat is a `PlotBeat` with `template`, `title`, `description`, `status` (`draft` → `revised` → `locked`), optional `chapterId` link, `order`, `notes`. Edit inline in a list or in a right-rail drawer. 2. **Templates** (`apps/web/src/features/plot/templates.ts`): ship four — **Three-Act** (Setup / Confrontation / Resolution), **Save-the-Cat** (all 15 beats), **Seven-Point** (Hook, Plot Turn 1, Midpoint, Plot Turn 2, Climax), and **Custom**. Selecting a template seeds N empty beats with the template's titles; the author edits from there. 3. **Board view** (`BeatBoard.tsx`): horizontal swimlanes per act/template-section, or a single ordered list. Drag to reorder; each beat shows status color, word count of linked chapter, and a "link to chapter" picker. Progress bar = % of beats that are `revised` or `locked`. 4. **Locking**: a `locked` beat is read-only until unlocked (with reason). Prevents accidental edits during a draft pass. ### 2. Timeline (`apps/web/src/features/timeline/`) 1. **TimelineView.tsx**: a horizontal time axis. Events (`TimelineEvent`) carry `when: {era, day} | date` (configurable: real dates OR a fictional calendar with named eras + day numbers), `title`, `description`, optional `chapterId`, and `links[]` (causal links to other events). 2. **Filters**: show/hide by character (events mentioning a character), by location, by era. Multi-select. 3. **Causal links**: draw an arrow from cause → effect; rendered as a separate layer behind the events. Click an event → open a read-only panel (full edit in the beat/entity system). ### 3. Whiteboard flow editor (`packages/boards`) 1. **Board model** (`packages/boards/src/types.ts`): `Board { id, projectId, nodes: FlowNode[], edges: FlowEdge[] }` where a `FlowNode` is a typed card — `character`, `world`, `chapter`, `note`, `image`, or `group`. Edges are typed (`leads-to`, `contrasts`, `causes`, `custom`). 2. **Node views** (`packages/boards/src/nodes/`): each node type renders a styled card with the entity's key fields (name, role, word count, etc.) and a drag handle. Groups are translucent containers that children snap to. 3. **Canvas** (`packages/boards/src/BoardCanvas.tsx`): React Flow 12 with: - **Minimap** (top-right), **zoom/pan** (mouse + keyboard), **auto-layout** (grid, force, or radial) via `@xyflow/layout`. - **Multi-select** (shift-click, marquee), **group/ungroup**, **align** (distribute edges). - **Keyboard**: `Del` delete, `Ctrl/Cmd+D` duplicate, `Ctrl/Cmd+G` group, arrow keys nudge. - **Persistence**: every node/edge change → autosave (Chunk 2 engine) with optimistic `rev`. 4. **Performance** (`packages/boards/src/perf.ts`): virtualize off-screen nodes, memoize node views, cap visible edges. **200 nodes at 60 fps** is the hard budget — a Playwright perf test seeds 200 nodes and measures frame time. ### 4. Cross-links 1. **Board ↔ chapters**: a `chapter` node links to a `Chapter` doc; click → opens it in the writer. 2. **Board ↔ entities**: `character`/`world` nodes link to entities; click → opens the entity editor. 3. **Import from beat board**: "Add beats to board" bulk-imports locked/revised beats as nodes. ### 5. Tests 1. Unit: template seeding (correct beat count + titles); board save/load round-trip (both adapters). 2. E2E: create a 6-node board, drag nodes, draw edges, save → reload → identical layout. 3. Perf: 200-node board at 60 fps (Playwright). --- ## Acceptance criteria (all must pass) - [ ] Select "Save-the-Cat" → 15 beats seeded with correct titles; edit one → saves. - [ ] Reorder beats by drag; progress bar updates (% revised/locked). - [ ] Lock a beat → editing is blocked with a reason prompt; unlock → editable. - [ ] Timeline renders events on a configurable calendar (real dates OR era/day); filters by character/location work. - [ ] Whiteboard: create nodes of every type, drag, group, align, draw typed edges, save → reload identical. - [ ] 200-node board renders at 60 fps (Playwright perf test in CI). - [ ] A chapter node opens the writer; a character node opens the entity editor. - [ ] Contract suite still green on both adapters. ## Definition of done Authors can structure a story three ways — beats, timeline, whiteboard — all linked to the prose and entities, and the whiteboard stays smooth at scale. ## Risks & fallbacks - **React Flow 12 API churn** → pin the exact version; wrap all calls in `packages/boards` so the app never imports `@xyflow/react` directly. - **200-node perf** → if force-layout is too slow, default to grid layout and make force-layout opt-in; document the node cap in `docs/BOARDS.md`. - **Drag-and-drop jank on low-end machines** → virtualize off-screen nodes; throttle autosave to 800ms.