@paperboycms/preview
v0.1.4
Published
Framework-agnostic on-page-editing bridge for the Paperboy headless CMS preview iframe — click-to-edit, drag-drop blocks, live patch. Zero runtime dependencies.
Maintainers
Readme
@paperboycms/preview
The browser-side on-page-editing bridge for the Paperboy headless CMS preview iframe. Framework-agnostic, zero runtime dependencies.
It is the single source of truth for the message protocol between the CMS admin (parent window) and a frontend rendered inside the preview iframe — so frontends and the admin can't drift.
Frontend (inside the preview iframe)
Call initPreviewBridge() once, only in preview, and mark your editable DOM:
import { initPreviewBridge } from "@paperboycms/preview";
if (inPreviewMode) {
const teardown = initPreviewBridge();
}<h1 data-pb-field="heading">…</h1>
<div data-pb-field="contentarea" data-pb-area="contentarea">
<!-- each rendered block: -->
<section data-pb-block-index="0" data-pb-block-type="CardBlock">…</section>
</div>The bridge then:
- posts
paperboy:editwhen an editable region is clicked (with rect/click/caret), - posts
paperboy:dropwhen a shared block/page is dragged from the Assets pane onto adata-pb-area, - streams
paperboy:recton scroll/resize, appliespaperboy:patch(live swap) andpaperboy:focus, - injects its own styles and persists scroll across reloads.
Admin (parent window) — types only, no DOM
import { parsePreviewMessage, patchMessage, focusMessage } from "@paperboycms/preview/protocol";parsePreviewMessage(ev.data) narrows an incoming message to the typed union (or null for unknown/garbage — the protocol is additive-only and both ends ignore unknown types, so independently-deployed admin/frontends degrade gracefully).
Attribute contract
| Attribute | Meaning |
| --- | --- |
| data-pb-field | An editable field region (value = field name) |
| data-pb-area | A content area that accepts block drops (value = field name) |
| data-pb-block-index / data-pb-block-type | A rendered block inside an area |
⚠️ data-pb-area's value must be the contentArea field name — the bridge posts it back to the editor as paperboy:drop {field}, which looks the field up on the content type. A boolean-ish marker (data-pb-area="true") makes every drop fail; the bridge warns about it in the console. Prefer spreading pbAreaAttrs(field, preview) from @paperboycms/client instead of writing the attribute by hand (it also keeps public pages marker-free).
