Guides
Annotations
Mark what editors can change.
In a JavaScript framework, let the leiho package write the attributes: field(), block() and entry() return an object to spread on the element (JSX, Astro, Svelte; v-bind in Vue).
import { field, block } from 'leiho';
<h1 {...field(page, 'hero_title')}>{page.fields.hero_title}</h1>
<section {...block(page, 'sections', i, 'Hero')}>…</section>field(page, 'intro', { html: true }) adds data-leiho-apply="html"; { refresh: true } adds data-leiho-refresh="save". In plain HTML or server templates, write the attributes below by hand.
| Attribute | Purpose |
|---|---|
data-wp-post="12" |
Container: the WordPress post ID for the fields inside |
data-wp-field="hero_title" |
Editable element: ACF field name, or _title / _thumbnail |
data-wp-field="cards.0.title" |
Dotted paths reach into repeaters, flexible content and groups |
data-leiho-apply="html" |
The value contains markup (an accent <span> in a heading): inject filtered HTML instead of text |
data-leiho-refresh="save" |
No live preview for this field; reload the page after saving (complex WYSIWYG rendering) |
data-leiho-section="Hero" |
Name a section in the Structure tree |
data-leiho-layout="sections.2" |
Bind a section to a flexible content row, so editors can add, move, duplicate and remove it |
data-leiho-managed="menu" |
Content managed elsewhere (menus, post lists, WooCommerce): clicking explains where to edit it |
data-leiho-edit-url="…" |
The wp-admin screen for that managed content |
One rule: always render an annotated element, even when its value is empty. {title && <h2 data-wp-field="title">…} breaks live editing, because an element missing from the page can't be filled in. Leiho flags such fields as "not on this page".
Client-side navigation (React Router, Next.js links, history.pushState) and re-renders are handled: the bridge re-scans the page and keeps unsaved edits applied.