← Back to Internal system builders
See how it helps
Editor document model
Creates a single authoritative document model with structured commands instead of competing DOM and application state.
editor-document-model-commands
Team members using this skill
When is it useful?
Use when editing operations break structure, selection or block identity.
What does it help you do?
- Separates document, selection, interface and temporary interaction state.
- Defines schema rules and stable identifiers for document nodes.
- Applies edits through transactions with explicit validation and history behavior.
Try asking this
Design moving a nested list item through one command while preserving selection and undo. Move a child item out of its list, undo and redo. Stable identifiers, valid nesting and the intended text selection should survive every step.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Editor Document Model & Commands
Use this skill when designing or modifying the state architecture, schema rules, and mutation commands of a visual editor, block editor, or interactive workspace.
Single Authoritative Document Model (Haverbeke & Ousterhout)
- Never Let the DOM and Application State Compete as Primary Sources of Truth:
- Maintain a canonical, serializable document model (an immutable tree or normalized node map) as the single owner of content.
- The view is a projection of document state, and edits dispatch structured commands / transactions ($\text{State} + \text{Transaction} \to \text{State}'$). Never mutate the DOM directly behind the editor library's back.
- Strictly Separate the Four Editor State Layers:
- Document Content State: Blocks, inline nodes, marks, attributes, and hierarchy (persisted and tracked by undo/redo).
- Selection & Cursor State: Active block/text selection, anchor/head positions, and focus target (ephemeral, bound to document positions).
- View / UI State: Zoom, pan, collapsed panels, hover guides, active toolbars, and drag indicators (never persisted as document content).
- Persistence / Save State:
clean,dirty,saving,saved,error,conflict, and last-acknowledged revision version.
Schema Rules, Stable IDs & Structural Integrity
- Stable Block Identifiers: Assign every addressable block or canvas element a stable unique ID (
id). - Parent-Child & Content Constraints: Enforce explicit schema rules defining which block types may nest inside which containers, required child nodes, and allowed inline marks.
- Safe Duplication & Deletion:
- When duplicating or pasting a block subtree, mint fresh IDs for every cloned node and remap internal cross-references within the cloned subgraph.
- When deleting a node, clean up dangling references and ensure the document keeps at least one valid root block when required by the schema.
Transactional Command Pipeline
- Route every content modification—typing, block insertion, drag-and-drop move, inspector edit, paste, or slash-command transform—through explicit, composable transactions.
- Validate schema invariants before committing a transaction so invalid trees cannot enter editor state.
- Adapt to existing libraries (ProseMirror, Tiptap, Lexical, Slate, BlockNote) via their native extension, node, and command APIs rather than building a custom rich-text engine.
Checklist
- Is there a single authoritative document model separated from selection, view UI, and save state?
- Do all blocks carry stable IDs, with fresh IDs and remapped references generated on duplication?
- Are parent-child nesting rules and schema invariants enforced on every command and transaction?
- Do all edits flow through structured transactions rather than direct DOM or ad-hoc state mutations?
Included files 1
SKILL.md
