Template helpers

A template’s job is to turn a node into HTML. The helper API is how it does that — and, just as importantly, it’s the only bridge between your markup and the editor. When a template reads a value through a helper, that helper quietly emits the data-* attributes the editor needs to make the value editable. You never write those attributes by hand, and you can’t accidentally leave them out.

That’s the deal in one sentence: speak the helper conventions, and any markup you invent becomes editable for free; ignore them, and the value renders static. You decide what’s editable by choosing which helper to call.

Reading values

get_val('name')              // "Fikkie" — raw value, no escaping
the_val('geo.latitude')      // echoes the value, HTML-escaped

get_val / the_val give you the bare value (dot-notation walks nested objects). Use them for text that isn’t meant to be edited inline — an alt attribute, a computed class, a microcopy string.

Making values editable

<?php the_value('name', ['tag' => 'h1']) ?>
<?php the_value('description', ['tag' => 'p', 'class' => 'intro']) ?>

get_value / the_value wrap the value in a real element. For a visitor that’s just <h1>Fikkie</h1>. For an editor it’s the same element plus the inline attributes that let them click and type:

<h1 data-inline-name="name" data-inline-type="name"
    data-inline-value="Fikkie" data-inline-dirty="false">Fikkie</h1>

When you need the attributes on an element you’re building yourself, use the_prop — it emits just the data-* string (empty for visitors, so it’s always safe to include):

<figure <?php the_prop('image', ['type' => 'image']) ?>>
  <img src="<?= get_val('image.url') ?>" alt="<?= get_val('image.name') ?>">
</figure>

Composing blocks

block() renders one node inside another. Data comes first, template second — the data is required, the template optional (a node can name its own via @build):

<?= block($place, 'place-card') ?>   // explicit template
<?= block($stop) ?>                  // uses the node's own @build

block() manages the context stack and stamps the wrapper with node-identity attributes automatically, so a card is editable the moment it’s rendered.

Lists

get_list / the_list turn a nested array into rendered, editable items. the_list() emits the <ol>/<li> scaffold with add/remove/reorder wired up; for a visitor it collapses to plain markup.

<?php foreach (the_list('mainEntity.itemListElement', [
  'item-type' => 'Place',
  'fields'    => [['key' => 'name', 'label' => 'Naam']],
]) as $stop): ?>
  <?php the_list_item($stop); ?>
    <?= block($stop, 'stop') ?>
  <?php end_list_item(); ?>
<?php endforeach; ?>
<?php end_list(); ?>

The three list types (curated, relational, queried) are covered in Lists & relations.

Media

get_media / the_media render media the way the_value renders a value and the_list renders a list: speak the helper, get a correctly-resolved, editable element for free.

<?php the_media('image') ?>      // resolves the reference, renders an <img>
<?php the_media('video') ?>      // renders a <video>

A page never stores the file itself. When a page uses an image, it stores a small reference to the media node — an @id, a preview url, and the placement-specific overrides:

{
  "@id": "ctxr:img42",
  "url": "…",            // preview
  "_focus": { "x": 0.5, "y": 0.3 },
  "_decorative": false,
  "description": "…"     // optional placement alt
}

The shared fields — the file, name, caption, credit — stay on the node, so the same image can appear on many pages, each with its own focus point. the_media does the resolving: it follows the reference to its node, renders the right element per kind, applies the focus point as a CSS object-position, and sets the alt text — empty when the placement is _decorative, otherwise the placement description, otherwise the node’s name / description.

image and video are separate, schema-pure properties — image lives at the Thing level (any node can have one), video at the CreativeWork level — so a node can carry both. That makes the hero fallback a one-liner:

<?= the_media('video') ?? the_media('image') ?>   // video hero, image fallback

Use get_media(...) when you want the raw resolved data instead of rendered markup.

Rich text

the_richtext / get_richtext render a formatted-text property — headings, links, emphasis — as sanitised HTML.

<?php the_richtext('articleBody') ?>

In development. The inline prose editor that makes rich text editable in place (the step-2 editing surface) is being built. Today the_richtext renders correctly for visitors and is editable through the structured form; in-place prose editing arrives with the editor’s next layer.

Accessibility & i18n helpers

Small helpers cover the parts of a page that are easy to forget and important to get right:

<?php the_skip_link() ?>                  // "skip to content" landmark
<?php the_hreflang($data) ?>              // alternate-language <link> tags
<button><?= t('add_item', 'Add item') ?></button>   // translatable string

t() looks up a UI string for the current locale and falls back to the default you pass. The full translation story — including the four-rung ladder these helpers sit on — is in Internationalisation.

Why helpers instead of raw attributes

You could hand-write data-inline-* attributes. The reason not to: the editor’s contract evolves, and the helpers move with it. A template that reads through helpers stays editable across platform versions; a template that hard-codes attributes is frozen to the day it was written. The helper is the stable surface — the editing experience page explains what it’s stable against.