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(article)
  <h1>{{ article.title }}</h1>
@else
  <p>Article not found.</p>
@endif
  • @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:
@if(posts && posts.length)
  @foreach(post in posts)
    <article></article>
  @endforeach
@else
  <p>No posts yet.</p>
@endif

Loops: @foreach@endforeach

Repeat a block once per element in an array.
@foreach(post in posts)
  <article>
    <h3><a href="{{ post.details_url }}">{{ post.title }}</a></h3>
    <p>{{ post.excerpt | default:post.summary | default:'' | raw }}</p>
  </article>
@endforeach
  • @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.
Inside the block you can use {{ item.property }}, @if, nested @foreach, and filters.

Variables: @set

Define a variable for use later in the template.
@set(greeting = "Hello")
<p>{{ greeting }}, {{ name }}!</p>
Use when you need a reusable value or a clearer expression.

Components: @component

Include a reusable component by name, with optional arguments.
@component("header", { title: "Home" })
The engine looks up the component by name and renders it with the given arguments in context.

Inheritance: @extends and @block

Use a base template and override only certain regions.

Base template (e.g. layout)

The base defines named blocks that child templates can override:
<!DOCTYPE html>
<html>
<head><title>Site</title></head>
<body>
  @block("content")
    Default content here.
  @endblock
</body>
</html>

Child template

The child declares which base it extends and redefines one or more blocks:
@extends("layout")
@block("content")
<main>
  <h1>{{ article.title }}</h1>
  {{ article.body | raw }}
</main>
@endblock
  • @extends("pageSlug") — Must be at the top; use the base page’s slug.
  • @block("name")@endblock — Replaces the same-named block in the base. Only the blocks you define are overridden; the rest of the base layout is used as-is.
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.
CallPurpose
@setSessionItem('key', value)Store a value in the session. Use @setSessionItem('key', null) to clear that key.
{{ getSessionItem('key') }}Output the stored value, or empty if not set.
@clearSessionItem('key')Remove the key from the session (same as setting it to null).
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:
@setSessionItem('selected_plan', 'premium')
<p>You chose: {{ getSessionItem('selected_plan') }}</p>
@if(getSessionItem('seen_intro'))
  <p>Welcome back.</p>
@else
  @setSessionItem('seen_intro', '1')
  <p>First time here? Read this…</p>
@endif
@clearSessionItem('cart_note')
@setSessionItem('cart_note', null)

Summary

DirectivePurpose
@if(condition)@endifConditional block
@else / @elseif(condition)Else branches
@foreach(item in array)@endforeachLoop
@set(variable = expression)Set variable
@setSessionItem('key', value)Store (or clear with null) session value
{{ getSessionItem('key') }}Output session value
@clearSessionItem('key')Remove session value
@component("name", args)Include component
@extends("pageSlug")Extend base template
@block("name")@endblockDefine/override block
Next: Variables and filters.