Skip to Content
EditorData Model

Data Model

Documents are stored as Lexical node trees. The live node tree is the source of truth while the user is typing. Plain text and persisted JSON are snapshots. Everything else, including pending edits, template anchors, and sync payloads, references positions inside it.

Core Entities

  • Document nodes: block containers such as paragraphs and headings, plus inline marks such as bold, italic, and code.
  • Pending edits: changes proposed by an agent. They live outside the document until the user accepts them.
  • Template anchors: named regions defined by a template.
  • Editor snapshot: the plain text, selection offsets, cursor position, slash command context, SmartPhrase context, and context menu geometry emitted from a single Lexical update listener.

Persistence Shape

The app persists two synchronized views of the same document:

  • content: plain text used by workflows, search, exports, and legacy integrations.
  • jsonContent: serialized Lexical state used to restore decorators, template fields, suggestions, and editor metadata.

Typing does not regenerate jsonContent on every keystroke. The live Lexical tree updates immediately, a lightweight snapshot goes out to UI consumers, and content and jsonContent are written after the persistence debounce or an explicit flush boundary.

Pending Edit Structure

A pending edit is a proposed change that has not touched the note yet. It stores the exact range it applies to, the original text, the replacement text, the agent’s reason, and the agent that produced it. Because those details travel with the edit, the editor can show the preview, record the audit trail, compare it with other suggestions, or mark it stale without changing the document.

PendingEdit
interface PendingEdit { id: string; type: "insert" | "replace" | "delete"; start: number; end: number; original: string; replacement: string; reasoning: string; agent: string; }

For the full lifecycle, see the Editor Guide.