Skip to main content
This page describes the directives the backend template engine understands. Use them in the page builder via the corresponding backend blocks, or write them directly in coded templates.

Conditionals: @if, @else, @elseif, @endif

Show one block when a condition is true, optionally with else branches.
  • @if(condition) — Renders the following content only when the condition is truthy.
  • @else — Optional; rendered when the @if condition is false.
  • @elseif(condition) — Optional; additional condition; first matching branch is used.
  • @endif — Ends the conditional block.

Conditions

You can use:
  • Word operators (safe in HTML): eq, neq, lt, lte, gt, gte
    Example: @if(orders.length gt 0)
  • Symbols (where allowed): ===, !==, ==, !=, <=, >=, <, >
  • Logic: and, or, unary !
  • Property checks: @if(article.author_avatar), @if(related_articles && related_articles.length)
Example with @elseif and array length:

Loops: @foreach … @endforeach

Repeat a block once per element in an array.
  • @foreach(item in array) — item is the variable name for the current element; array is an expression that must evaluate to an array (e.g. posts, related_articles).
  • @endforeach — Required; ends the loop.
  • @each(item in array) … @endeach — Same loop under another name; either closer works.
  • @foreach((key, value) in object) — Loop over an object’s keys and values.
Inside the block you can use {{ item.property }}, @if, nested @foreach, and filters.

The loop variable

Inside every loop, loop describes the current pass: For example, an ItemList with a position and no trailing comma:
loop, like the item variable, exists only inside the loop.

Variables set inside a loop

A variable you @set inside a loop keeps its value after @endforeach, and each pass sees the value the previous pass left. Use it for counts and totals:
Because the value carries over, reset a per-item variable at the top of the loop body when only some items set it:

Variables: @set

Define a variable for use later in the template.
Use when you need a reusable value or a clearer expression. To put a quote of the same kind inside a string, escape it with a backslash, or use the other kind of quote around it:

Directives on one line

Directives work on a line of their own or inline, next to other directives and text. These two are the same:
Inline you can use @if( @elseif( @else @endif, @foreach( @endforeach, @each( @endeach, @set(, @setSessionItem( @clearSessionItem(, @component( and @yield(:
Two directives need their own line:
  • @extends(…) — On its own line, at the top of the file.
  • @block(…) — On its own line, directly after a tag (</style> @block("head")), or with its @endblock on the same line (<title>@block("title")About@endblock</title>).
In any other position they are printed as text, and ef lint warns about it. An @ that doesn’t start one of these directives is left as it is, so emails (support@example.com), handles (@yourbrand), CSS at-rules (@media, @font-face, @import) and @ in scripts need no escaping. A word such as @settings or use @set to is text too: a directive needs its (.

Components: @component

Include a reusable component by name, with optional arguments.
The engine looks up the component by name and renders it with the given arguments in context.

Inheritance: @extends, @block, and @yield

Use a base template and override only certain regions. @yield("name") and @block("name")…@endblock both define named regions in a base layout that child templates can fill. The difference: @yield has no default content (renders empty if not overridden), while @block can include default content as a fallback.

Base template (e.g. layout)

The base defines named blocks that child templates can override:

Child template

The child declares which base it extends and redefines one or more blocks:
  • @extends("pageSlug") — Must be at the top; use the base page’s slug.
  • @block("name") … @endblock in the child — Replaces the same-named @block or @yield in the base. Only the blocks you define are overridden; the rest of the base layout is used as-is.

@yield vs @block — when to use which

@yield("name") is a slot with no default content — nothing renders if the child does not provide an override. @block("name") default @endblock has optional default content that renders when no child override is provided. Example base layout using @yield for required slots and @block for optional ones:
Child template:
In the page builder, inheritance is supported with a read-only base layer: only the block regions are editable, and on save only the child source (extends + blocks) is stored.

Session storage

You can store and read simple values in the visitor’s session from templates. Use this for things like remembering a choice across requests (e.g. a selected option, a flag) without using the frontend. Rules:
  • Keys may only use letters, numbers, and underscores (a–z, A–Z, 0–9, _). Other characters are stripped.
  • Values are stored safely (encoded). You can pass strings or numbers; other types are JSON-serialized. There is a size limit per value (~64 KB).
  • Clearing: Passing null (or nothing) to setSessionItem removes the key, as does @clearSessionItem('key').
Session length and when it resets
  • Lifetime: Session data (including values you store with setSessionItem) lasts 3 hours from when the session was first created. The timer does not reset on each page load—so after 3 hours the session expires and all stored values are gone.
  • When it resets: The session is tied to the visitor’s session cookie. It is cleared when:
    • the 3-hour lifetime has passed,
    • the visitor clears their cookies,
    • or they use a different browser or device (new session).
  • Use session storage for short-lived, per-visit state (e.g. “has seen this step”, “selected option for this visit”). For long-lived or cross-device data, use a different mechanism (e.g. customer account, database).
Examples:

Summary

Next: Variables and filters.