Editor API integration

This guide explains how to embed the CDK editor runtime in your application and connect the minimal contexts needed for block authoring.

What you need

  • A State instance from @modula/editor.
  • A block preset (for example from @modula/presets/default).
  • A blocks renderer/editor component such as Form from @modula/blocks.
  • Runtime contexts (i18n, streams, optional oEmbed, optional collaboration).

Minimal integration

import { Node, State, createPreset, setCollabSessionContext } from '@modula/editor';
import Form from '@modula/blocks/Form';
import { types } from '@modula/presets/default';

const preset = createPreset(types);
const initial = [new Node(Node.uuid(), 'title', { title: 'New module', blocks: [] })];
const editorState = new State(initial);
const blocks = editorState.blocks.toArray();

// If you are not using collaboration, keep the collab context null.
setCollabSessionContext(null);

Then render the form:

<Form width="48rem" {preset} {editorState} {blocks} locale="en" />

Required contexts in real apps

In production integrations, set these contexts before mounting the editor UI:

  • I18n context (setI18nContext) for labels and block UI strings.
  • Streams context (setStreamsContext) for upload/media workflows.
  • oEmbed service context (setOembedServiceContext) if blocks resolve external media URLs.
  • Collaboration session context (setCollabSessionContext) when realtime editing is enabled.

Loading existing content

Use State.fromJSON(...) when opening previously saved content:

import { State } from '@modula/editor';
import type { NodeJSON } from '@modula/editor';

const saved: NodeJSON[] = await fetch('/api/content/123/state').then((r) => r.json());
const editorState = State.fromJSON(saved);

State.fromJSON normalizes persisted nodes into runtime Node instances.

  1. Keep editor runtime state local in memory (State).
  2. Persist snapshots with explicit Save actions (or debounced autosave).
  3. Convert to your module/domain shape only at save boundaries.
  4. Keep media upload and collab transport as separate services from block rendering.

This keeps the editor deterministic and straightforward to test.