Add PubScript master plan and 11 chunk work orders
This commit is contained in:
+62
@@ -0,0 +1,62 @@
|
||||
# CHUNK #3 — Writing Surface
|
||||
|
||||
**Duration:** ~3 days · **Prereqs:** CHUNK #2 (storage spine, autosave) · **Follows:** CHUNK #2 · **Unblocks:** CHUNK #6 (export), #7 (spellcheck), #9 (AI suggestions render over this editor)
|
||||
|
||||
**Purpose:** Build the actual writing experience: the TipTap 3 editor with the full node schema, the document tree, the font system, focus/typewriter modes, live stats, and Markdown import/export — performing well enough that a 100k-word project opens in under 2 seconds and typing never lags.
|
||||
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Editor package (`packages/editor`)
|
||||
1. `packages/editor/src/schema.ts` — TipTap extensions, all registered once:
|
||||
- Base: `Document`, `Paragraph`, `Text`, `Heading` (1–3), `Blockquote`, `HorizontalRule`, `HardBreak`, `Bold`, `Italic`, `Strike`, `Code`, `CodeBlock`.
|
||||
- **`SceneBreak`** (node) — a centered `* * *` divider, draggable, with a NodeView; splits scenes for stats and AI targeting.
|
||||
- **`Footnote`** (inline + a `FootnoteArea` block at doc end) — v1 simple: number, reference, definition.
|
||||
- **`CharacterMention`** (inline atom) — rendered as a styled chip linking to a character entity (inserted by autocomplete in Chunk 4; the node type lands here).
|
||||
- Markdown I/O: `prosemirror-markdown` with rules for scene breaks (`***`), mentions (`@Name`), footnotes.
|
||||
2. `packages/editor/src/Editor.tsx` — the headless wrapper:
|
||||
- `createEditor({ doc, onUpdate, decorations })` returning `{ view, state, dispatch, applyTransaction }`.
|
||||
- **Decoration pipeline:** `useDecorations(view, sources[])` — merges decorations from spellcheck (Chunk 7), AI suggestions (Chunk 9), and mentions into one `DecorationSet`, memoized, recomputed only on relevant transactions. This is the seam later chunks plug into — build it now, even with zero sources.
|
||||
- `applyEdit(range, before, after)` — the transaction used by "Accept suggestion".
|
||||
3. `packages/editor/src/perf.ts` — `measureTypingLatency()` (rAF-based) + a dev overlay showing ms/keystroke.
|
||||
|
||||
### 2. Writing view (`apps/web/src/features/write/`)
|
||||
1. `WritingView.tsx` — layout: document tree (left, from Chunk 2), editor (center), context rail (right: current chapter's linked characters/notes, collapsible).
|
||||
2. **Toolbar** — floating (appears on selection) + docked (top): headings, bold/italic/strike, blockquote, scene break, footnote, mention, undo/redo. Slash menu (`/`) for block insertion.
|
||||
3. **Keyboard map** (`packages/editor/src/keys.ts`): `Ctrl/Cmd+B/I/K`, `Ctrl+/` scene break, `Alt+↑/↓` chapter nav, `F2` focus mode.
|
||||
4. **Focus mode** — dims everything but the current paragraph band; **Typewriter mode** — auto-scrolls the active line to a fixed vertical position. Both toggle from toolbar + settings.
|
||||
5. **Stats bar** (footer): word count (chapter/book/project), session words, reading time; per-chapter counts in the tree.
|
||||
6. **Font system** (`packages/ui/src/fonts.ts`): bundle via `@fontsource` — **EB Garamond**, **Source Serif 4**, **Inter**, **Space Grotesk**, **JetBrains Mono** (+ weights). Settings controls: family, size (14–22 px), leading (1.3–2.0), measure (50–90 ch), margins. Apply via CSS variables on the editor root; persist in settings store.
|
||||
7. **Markdown I/O:** `exportMarkdown(doc)` / `importMarkdown(text)` in `packages/editor/src/markdown.ts`. Import dialog in the tree ("Import .md…") with a preview + conflict check; per-chapter and whole-project export (feeds Chunk 6).
|
||||
|
||||
### 3. Performance work
|
||||
1. **Lazy chapters:** only the open chapter's doc is in the editor; switching chapters swaps state without unmounting the view.
|
||||
2. **Virtualize the tree** for books with 500+ chapters (`@tanstack/react-virtual`).
|
||||
3. Add a Playwright perf test (`apps/web/e2e/perf.spec.ts`): seed a 100k-word doc (script generates 40k paragraphs), assert: open < 2 s; 20 keystrokes median latency < 16 ms (using the dev overlay's API); tree scroll at 60 fps.
|
||||
|
||||
### 4. Polish
|
||||
1. Placeholder states (empty book, empty chapter), save indicator already wired (Chunk 2).
|
||||
2. Accessibility: visible focus rings, `aria` on toolbar/tree, full keyboard operation of the tree.
|
||||
3. `docs/EDITOR.md` — node reference (for humans) + "how to add a node type" (for agents).
|
||||
|
||||
---
|
||||
|
||||
## Acceptance criteria (all must Pass)
|
||||
- [ ] Type a full chapter: no dropped keystrokes; latency overlay < 16 ms median on a 100k-doc.
|
||||
- [ ] 100k-word seeded project opens < 2 s (Playwright perf test in CI).
|
||||
- [ ] Scene breaks insert via `***` and slash menu; stats split by scene.
|
||||
- [ ] Footnotes render and export to Markdown correctly.
|
||||
- [ ] Font/size/leading/measure changes apply live and persist across reload.
|
||||
- [ ] Focus + typewriter modes work and are keyboard-toggleable.
|
||||
- [ ] Import a 50-chapter `.md` file → tree + docs correct; re-export round-trips (diff of re-imported Markdown is empty modulo whitespace).
|
||||
- [ ] Decoration pipeline: register a fake decoration source → renders; (Chunk 9 will replace it with real AI suggestions.)
|
||||
- [ ] A11y pass: toolbar fully keyboard-operable; contrast ≥ 4.5:1 in all four themes.
|
||||
|
||||
## Definition of done
|
||||
An author can sit down and *write* — fast, beautiful, with the story structure around them — and the editor exposes a stable decoration/edit API that spellcheck and AI plug into without touching core code.
|
||||
|
||||
## Risks & fallbacks
|
||||
- **TipTap v3 API churn** → pin the exact v3 release; wrap all v3-specific calls in `packages/editor` so the app never imports TipTap directly.
|
||||
- **Markdown round-trip loss** (footnotes/mentions) → keep a canonical ProseMirror-JSON store; Markdown is an *exchange* format, not the source of truth (document this in `docs/EDITOR.md`).
|
||||
- **Perf test flakiness in CI** → run perf specs on a dedicated runner with 3 runs, take the median; fail only on >2× regression.
|
||||
Reference in New Issue
Block a user