For the complete documentation index, see llms.txt. This page is also available as Markdown.

Twig

Use the Twig templating language to format and transform CMS content.

Elements CMS supports the Twig templating language — a fast, secure, and flexible template engine widely used in modern PHP applications. Twig is what makes references like {{item.title}} work, and what powers everything from date formatting to control flow inside your CMS templates.

If you've ever written a template in Liquid, Jinja, or Handlebars, Twig will feel familiar. If not, the basics are quick to pick up — they're covered below.

The four building blocks

Twig has four kinds of syntax you'll use over and over:

  • {{ … }}output a value. Anything between the double braces is evaluated and printed.

  • {% … %} — a statement like an if, a for loop, or a variable assignment. Statements don't print anything by themselves.

  • {# … #} — a comment that's stripped before output.

  • |filter — a filter applied to a value. {{item.title|upper}} runs the title through the upper filter.

You can chain filters: {{item.title|striptags|upper}} strips HTML tags then uppercases the result.

Where Twig runs in Elements

Inside a Collection or Item drop zone, {{item.title}} and friends work natively in any Elements component — Headings, Typography, Text, Link, Image — without any extra setup. The component reads the reference and renders the value.

When you want to use Twig syntax that goes beyond a simple reference — control flow, filters, custom HTML — you have two options:

  • In a custom HTML or Code component, wrap the Twig in an @raw() directive. Without @raw(), the surrounding template engine treats {% %} and {{ }} as its own syntax and may interfere.

  • In a native Elements component's text field, simple references and filters work directly. Control flow doesn't.

@raw()
{% if item.featured %}
    <span class="badge">Featured</span>
{% endif %}
@endraw

Control flow

Conditionals

Loops

The {% else %} block inside a {% for %} runs when the collection is empty — handy for "no items" fallbacks.

Twig exposes a loop variable inside any loop with useful counters:

  • loop.index — the current iteration, starting at 1.

  • loop.index0 — the same, starting at 0.

  • loop.first and loop.last — booleans for the first and last iterations.

  • loop.length — the total number of items.

The most useful filters in CMS context

These come up constantly when working with Markdown content.

date — format a date

The format string uses PHP date tokens. Twig also offers a date_modify filter for relative date math.

default — fall back when a value is missing

If item.author is missing or null, the filter substitutes the fallback. Without |default, missing properties output nothing.

length — count items in an array or characters in a string

upper, lower, title, capitalize — change case

striptags — strip HTML

Useful when reusing the rendered body in a <meta> description or excerpt.

slice — take part of an array or string

split and join — break apart and reassemble

escape (alias e) — make a string safe for output

Twig auto-escapes most output, but if you've manually marked a value as |raw and need to re-escape part of it, |escape does the trick.

Chaining: a clean text excerpt

A common recipe — take the body, strip HTML, take the first 32 words, and add an ellipsis:

The ~ operator concatenates strings, equivalent to + in JavaScript.

Variable assignment

{% set %} declares a variable that's only in scope for the rest of the template. Useful when you'd otherwise repeat a long expression.

Working with arrays

Common pitfalls

My {{ … }} reference renders literally on the page. You're inside a code or HTML component without @raw(). Wrap the block in @raw() … @endraw so the outer engine doesn't pre-process the Twig syntax.

A property that exists in some posts but not others is breaking my template. Use |default or wrap access in an {% if %}. Twig errors on undefined properties unless you guard against them.

My HTML is being auto-escaped — < shows up as &lt;. Twig auto-escapes string output by default. Use |raw to opt out of escaping for a specific value (only for content you trust):

Be careful — anything user-supplied should stay escaped to prevent cross-site scripting.

Date filters output 1970-01-01. Your frontmatter date value is missing or unparseable. See Frontmatter for the supported date formats.

Useful resources

Last updated

Was this helpful?