Editor state and persistence

The CDK editor runtime revolves around State (@modula/editor).

State model

A State instance stores an ordered collection of Node blocks and a transaction history.

Key runtime concepts:

  • State.blocks: current ordered block collection.
  • State.transaction(...): atomic mutation unit.
  • State.undo() / State.redo(): history traversal.
  • State.apply(...): apply operation batches (useful for remote updates).
  • State.toJSON(): serialize current state for persistence.

Transaction operations

Transactions emit change events and record operations of type:

  • add
  • remove
  • change
  • metadata
  • move

Example:

editorState.transaction((tx) => {
  tx.add(new Node(Node.uuid(), 'text', { text: { title: 'Intro', body: '<p>Hello</p>' } }));
});

Save format

Use editorState.toJSON() to persist editor-native state.

Serialized shape:

type NodeJSON = {
  id?: string;
  type: string;
  data: Record<string, unknown>;
  meta?: Record<string, unknown>;
};

Persisted payload example:

[
  {
    "id": "a8f7f2f0-7f70-4a61-9f58-7b35039f3f78",
    "type": "text",
    "data": {
      "text": {
        "title": "An Epic Journey",
        "body": "<p>...</p>"
      }
    },
    "meta": {
      "showAbstract": true
    }
  }
]

Restore flow

const state = State.fromJSON(savedNodes);

fromJSON reconstructs runtime Node objects, preserving id, type, data, and meta.

Saving modules (versioned backend)

If you save to the Modula REST modules endpoint, send your module content to:

  • POST /api/modules/:id

with body:

{
  "data": { "title": "...", "subtitle": "...", "abstract": "...", "blocks": [] },
  "rev": "optional-previous-revision-id"
}

A stale rev can return 409 Conflict (optimistic concurrency).

Persistence best practices

  • Save only JSON snapshots, never runtime object references.
  • Keep id stable across saves to preserve move/change semantics.
  • Use optimistic concurrency (rev) for multi-client editing.
  • For autosave, debounce writes and keep explicit Save for user confidence.