Live preview channels
The admin talks to a frame with the site (the visual editor, a design canvas) over
@manablox/live-preview. Besides the content messages every frontend handles, a plugin can
open its own channel on that connection: named messages with a payload, in both directions.
The designer of designed sites uses the channel website this way.
The messages
A channel is typed by a map of message names to payloads, one map per direction:
import type { PluginChannelMap } from '@manablox/live-preview';
export interface HelloMessages extends PluginChannelMap { toPreview: { greet: { name: string } }; toEditor: { clicked: { id: string } };}Keep the map in a package both sides can import without pulling in the other side.
The frame
The frame lists the channels it handles in plugins and opens them with plugin(id) on the
value connectPreview returns:
import { connectPreview } from '@manablox/live-preview';
const connection = connectPreview({ editorOrigin, onDocument, plugins: ['hello'] });const hello = connection.plugin<HelloMessages>('hello');const off = hello.on('greet', ({ name }) => show(name));hello.send('clicked', { id: 'button' });
// lateroff();connection();The returned value is still the function that disconnects the frame.
The admin
An admin plugin screen that frames the site opens the same channel on its editor channel:
import { createEditorChannel } from '@manablox/live-preview';
const channel = createEditorChannel({ iframe, previewOrigin, onReady });const hello = channel.plugin<HelloMessages>('hello');hello.send('greet', { name: 'Ada' });hello.on('clicked', ({ id }) => select(id));onReady(capabilities)gets the frame’s channels incapabilities.plugins.- A
sendbefore the frame is ready waits; only the last payload of each name is kept, and they go out in the order of their first send, before the queued document. - Once the frame is ready, messages for a channel it did not list are dropped.
on(name, handler)returns a function that stops listening.
On the wire
Every plugin message is { v: 1, kind: 'plugin', plugin, name, payload }. Both sides check
the origin (and the admin also the frame) of every message before a handler sees it. The
payload is whatever the other side sent, so check its shape where a wrong value would do
harm.
Content messages carry the same version. A side ignores message kinds it does not know.