61 lines
5.3 KiB
Markdown
61 lines
5.3 KiB
Markdown
# 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.
|