Skip to content

Client API & protocol

@dremchee/uframe/embed mounts the standalone editor app into an iframe and controls it through a typed postMessage protocol. It is the integration path for any host framework.

Create an editor

ts
import { createUframeEditor } from '@dremchee/uframe/embed'

const editor = createUframeEditor({
  target: document.querySelector('#editor')!,
  src: 'https://uframe-app.netlify.app/embed/index.html',
  document: initialDocument,
  toolbarVisible: true,
  onChange: document => persistDraft(document),
  onSave: document => publish(document),
  onError: message => console.error(message),
})

target can be a container (the client creates an iframe inside it) or an existing <iframe>. The returned handle is ready to use immediately; commands issued before the iframe handshake are queued.

Options

OptionTypeNotes
targetHTMLElementMount container or existing iframe.
srcstringHosted editor index.html.
documentPageDocumentInitial single-page document.
pages / activePageIdPageDocument[] / stringMulti-page site and the selected page.
globalsGlobalSettings | nullShared site data for multi-page editing.
readonlybooleanHides editing affordances.
toolbarVisiblebooleanShows or hides the editor toolbar.
statePartial<UframeEditorState>Initial editor state, such as viewport and preview mode.
themeUframeThemeInitial light/dark document theme.
locale / messagesstring / UframeMessagesUI language and translation catalogs.
uiTheme / styleTokensEditorUiTheme / EditorStyleTokensSemantic editor UI styling.
pluginsstring[]ESM plugin URLs to load after the handshake.
schemaNormalizedSchemaLimits and extends the editable document schema.
dataContextResolveContextDynamic values available to blocks and bindings.
onReady() => voidIframe has completed its handshake.
onChange / onSave(document) => voidDraft changes and explicit save requests.
onPagesChange / onActivePageChangecallbacksMulti-page changes.
onGlobalsChange(globals) => voidShared settings changed.
onStateChange(state) => voidViewport, mode, and other public editor state changed.
onRequestAssetcallbackEditor requests an asset from the host.
onError(message) => voidRecoverable protocol or editor error.

For non-English UI, import a locale catalog separately; the base package ships English only. See Localization.

Control the mounted editor

ts
editor.setDocument(document)
editor.setPages(pages, 'home')
editor.setActivePage('pricing')
editor.setGlobals(globals)

editor.setReadonly(true)
editor.setToolbarVisible(false)
editor.setViewport('tablet')
editor.setEditBreakpoint('md')
editor.setState({ preview: true })
editor.openAddBreakpoint()

editor.setTheme('dark')
editor.setLocale('ru')
editor.setMessages({ ru: { 'toolbar.save': 'Сохранить' } })
editor.setUiTheme(uiTheme)
editor.setStyleTokens({ accent: '#14b8a6' })

editor.setSchema(schema)
editor.setDataContext({ user: { name: 'Ada' } })
editor.loadPlugins(['https://cdn.example.com/uframe/callout.js'])

editor.requestSave()
editor.destroy()

The underlying iframe is exposed as editor.iframe when host-level focus, layout, or lifecycle work is needed.

Supply assets from the host

The editor never needs direct access to your media API. React to an asset request, upload or choose a file in the host UI, and send the resulting URL back using the request ID:

ts
const editor = createUframeEditor({
  target,
  src,
  onRequestAsset: async ({ requestId, kind }) => {
    const asset = await selectAssetInHostApp(kind)

    editor.setAsset(requestId, {
      url: asset.url,
      alt: asset.alt,
      width: asset.width,
      height: asset.height,
    })
  },
})

Runtime plugins

Pass plugin module URLs on creation or load them later. The official AI plugin is built beside the hosted editor, so it can be enabled with a stable URL:

ts
createUframeEditor({
  target,
  src: 'https://uframe-app.netlify.app/embed/index.html',
  plugins: ['https://uframe-app.netlify.app/embed/plugins/ai.js'],
})

URL-loaded plugins must share the editor runtime. Co-building them with the embed app is the simplest option; otherwise configure a shared runtime/import map. For authoring blocks and Vue plugins, see Extending the editor.

Protocol and security

The iframe emits uframe:ready; the client answers with uframe:load. Further messages are namespaced with uframe: and include a protocol version.

Host → editorEditor → host
uframe:load, uframe:setDocument, uframe:setPages, uframe:setActivePage, uframe:setGlobals, uframe:setState, uframe:setMessages, uframe:setSchema, uframe:setAsset, uframe:loadPlugins, uframe:requestSaveuframe:ready, uframe:change, uframe:save, uframe:pagesChange, uframe:activePageChange, uframe:globalsChange, uframe:stateChange, uframe:requestAsset, uframe:error
  • Serve the editor from an origin you control, and allow it in your host CSP's frame-src directive.
  • The client passes the host origin in the iframe URL. Both sides validate the window and origin before accepting messages; replies are not sent to *.
  • PageDocument and GlobalSettings are plain structured-cloneable JSON. Treat untrusted document content as untrusted when rendering it outside the editor.