Basics

Native / iframe bridge

For Flutter WebView, Electron, Tauri, Wails, Capacitor — not REST. Use bindHostBridge from @codemerge/integrate/protocol.
import { bindHostBridge } from '@codemerge/integrate/protocol';

const { host, dispose } = bindHostBridge(document.getElementById('editor')!, {
  targetOrigin: 'https://app.example', // optional when framed — see below
});

// Parent / native shell:
// iframe.contentWindow.postMessage({ type: 'ocm-load', value: '# Hi', format: 'markdown' }, origin);
// listen for { type: 'ocm-change', value, format } and { type: 'ocm-ready' }
// send { type: 'ocm-destroy' } on teardown

Message types: ocm-load, ocm-change, ocm-ready, ocm-destroy. ocm-load takes an optional format (html / markdown / text); without it the value is read in the host's format.

Origins

OptionDefault
targetOriginIn an iframe: the parent's origin (location.ancestorOrigins[0], else document.referrer). Otherwise, or when unreadable: '*'.
allowedOrigins[targetOrigin] when it is a concrete origin, else any (['*']).

In an iframe with the default messageTarget, messages are also accepted only when event.source === window.parent. Set targetOrigin explicitly when the parent sends Referrer-Policy: no-referrer (Firefox has no ancestorOrigins). WebView / Electron shells usually post from the same window — pass allowedOrigins: ['*'] if their origin is opaque.

For HTTP backends inside a normal browser app, prefer Persistence instead.