Template helper reference

Helpers are PHP functions available inside any build/ template. They fall into a few families: reading values, rendering editable elements, looping lists, querying the graph, embedding other nodes, and setting up the page. For why helpers are the only bridge to editability, see Template helpers in Build & customize.

Two pairs are easy to confuse: get_val/the_val read a bare value, while get_value/the_value render a full editable element.

Required in every page template

A page template must include three calls or the editor and structured data won’t load:

<?php ctxr_head($data); ?>      // in <head> — editor CSS + import map + atoms spec (visitors get PWA head only)
<?php the_schema($data); ?>     // in <head> — JSON-LD <script type="application/ld+json">
<?php ctxr_scripts($data); ?>   // before </body> — editor bootstrap, or the "Powered by ctxr" bar

the_skip_link() in the <body> is the accessibility convention, and the_hreflang() in the <head> emits locale alternates when a translation connector is active.

Reading values

Helper Signature Does
get_val get_val(string $name): mixed Reads a value from context by dot-path; null if it doesn’t resolve
the_val the_val(string $name): void Echoes the value, HTML-escaped
get_name get_name(array $data): string Display name with fallback chain: nameheadlinetitle@type · @path@id

Rendering editable elements

These emit data-inline-* attributes for editors and plain output for visitors.

Helper Signature Does
get_prop / the_prop (string $name, array $opts = []) Builds (or echoes) the data-inline-* attribute string; empty for visitors
get_value / the_value (string $name, array $opts = []) Renders <tag>value</tag> with edit attributes
get_richtext / the_richtext (string $name, array $opts = []) Renders a rich-text document model to safe HTML in an editable wrapper

Options: tag (default span, or div for richtext), class, edit-type (override the auto-detected atom type), item-type, orientation, and fields (for list properties). The atom type is otherwise guessed from the property name.

Lists

Helper Signature Does
get_list get_list(string $path): array Pure data: unwraps ListItem wrappers, injects _index/_prefix. Caps at 200 items
the_list / end_list the_list(string $path, array $opts = []): array Opens an editable <ol> and returns the items; close with end_list()
the_list_item / end_list_item the_list_item(array $item, array $opts = []): void Opens an <li> with list-item attributes; close with end_list_item()
loop loop(string $path, callable $fn): void Iterates a list, pushing/popping context per item; callback gets ($item, $index, $prefix)

Build internal links that stay inside the app shell and respect the current mode. Prefer these over a hand-written <a href>: a raw absolute or cross-space URL breaks the shell (opens outside the installed app) and ignores edit mode.

Helper Signature Does
get_href get_href(mixed $target = null, array $opts = []): string Context-aware href. Internal target (a node, an @path, or a path) → root-relative so the shell intercepts it (no full reload); on an actor surface (/edit·/live·/draft) it’s mode-prefixed so links keep you in the same mode; a genuinely external URL (other origin) is returned untouched. null resolves the current context item’s @path
the_href the_href(mixed $target = null, string $text = '', array $opts = []): void Renders <a href="…">text</a> using get_href; external links get target="_blank" rel="noopener". Options: class, title. E.g. the_href(null, 'View', ['class' => 'card-link'])

Querying the graph

These read the live graph from inside a template (delegating to the query service).

Helper Signature Does
query_by_type (string $type, ?callable $filter = null): array All live nodes of a type, optional fn(array): bool filter
query_by_identifier (string $propertyID, string $value): array Nodes found via the external-identifier index
query_by_appears_in (string $nodeId, ?string $kind = null): array Nodes that reference the given node; kind = curatorial / relational / null
query_more (string $type, string $parentId, string $cursor = '', int $limit = 25): array Pages relational items beyond the compiled limit; returns items, numberOfItems, _hasMore, _nextCursor

query_nodes still exists as a deprecated alias for query_by_type — use the latter.

Embedding other nodes

The get_* variant returns a string; the the_* variant echoes; the short alias equals the the_* variant (except node(), which resolves data).

Helper Signature Does
get_node / node (string\|array $input): array Resolves an @id string, id-stub, or array to a data array (no render)
get_block / the_block / block (string\|array $data, string $template = ''): string Renders a blocks/* template. Data first: block($data, 'place-card')
get_menu / the_menu / menu (string\|array $data, string $template = ''): string Renders a menus/* template
get_page / the_page / page (array $data, string $template = ''): string Renders a pages/* template
get_form / the_form / form (array $data, string $template = '', array $opts = []): string Renders a form: explicit template → build/forms/{type}.php → scalar introspection

A referenced block (one with an @id) gets data-block, data-node-id, data-node-type, data-node-is-live and data-node-is-draft injected on its root element. Template names must match ^[a-zA-Z0-9_\-]+$ and resolve under build/{blocks,menus,pages,forms}/.

Context stack

Helper Signature Does
push_context / pop_context push_context(array $data): void / pop_context(): void Push/pop a data frame on the render stack (managed automatically by block() and loop())

Page setup and assets

Helper Signature Does
ctxr_head ctxr_head(array $data = []): void Editor CSS + import map + atoms spec; visitors get the PWA head only
ctxr_scripts ctxr_scripts(array $data = []): void Editor bootstrap before </body>, or the “Powered by ctxr” bar on branded plans
the_schema the_schema(array $data = []): void Emits the JSON-LD script. get_schema() is a backwards-compatible alias (it echoes, despite the get_ name)
asset_url asset_url(string $path): string Cache-busted theme asset path (?v=mtime); /assets/ maps to build/assets/
ctxr_cdn_url ctxr_cdn_url(string $path): string Cache-busted platform CDN path

i18n and accessibility

Helper Signature Does
t t(string $key, array $args = []): string Translates a UI string with {var} substitution
the_skip_link the_skip_link(string $targetId = 'main'): void Emits a visible-on-focus skip-to-content link
the_hreflang the_hreflang(array $data = []): void Emits hreflang alternates per locale; no-op without translation alternates

PWA and render mode

Helper Signature Does
ctxr_pwa_head ctxr_pwa_head(): void Manifest link, apple-touch-icon, and the PWA register script
ctxr_cdn_url ctxr_cdn_url(string $path): string Cache-busted platform-CDN path (appends ?v= from the file mtime)
ctxr_mode ctxr_mode(): ?string The render mode from the URL: null (the live product / installable surface), 'edit', 'live', or 'draft'

You normally don’t call the PWA helpers directly. ctxr_head() already loads the manifest, service-worker registration and the live-page brokers (location, notifications, the permission modal, and the in-page navigation shell) once per page on the live surface — themes just call ctxr_head() and ctxr_scripts() and the PWA comes along. edit_head and edit_scripts are backwards-compatible aliases for ctxr_head and ctxr_scripts; prefer the ctxr_* names.