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).

jsx
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.

Something unclear on this page? Tell us →