DocsSintaxTemplate Syntax

Template Syntax

Expressions, conditionals, loops with their auto-bound helpers, and whitespace control.

A sintax template is plain text with expressions and control blocks between {{ }} delimiters. This page covers the syntax itself. For the modifiers you can call inside an expression, see the reference categories in the sidebar, and for the Go API see the Quick Guide.

Expressions

An expression resolves a variable, optionally piping it through modifiers left to right.

{{ name }}
{{ name | trim | upper }}
{{ users | filter:'active',true | pluck:'email' }}

The head of a pipeline can also be a quoted string literal instead of a variable name.

{{ 'partial.tpl' | file | template }}

Referencing a variable that does not exist fails the render with ErrVariableNotFound rather than printing an empty string, so a misspelled key cannot silently produce a blank field. When absence is legitimate, catch it with default.

{{ nickname | default:'anonymous' }}

Conditionals

if renders its body when the condition is truthy. else is optional, endif is required.

{{ if active }}yes{{ else }}no{{ endif }}

The condition is a full expression, so modifiers work inside it.

{{ if role | eq:'admin' }}elevated{{ endif }}
{{ if count | gt:10 }}busy{{ endif }}

There is no elif. Chain a nested if inside the else branch instead.

{{ if score | gte:90 }}A{{ else }}{{ if score | gte:80 }}B{{ else }}C{{ endif }}{{ endif }}

Truthiness

A condition is evaluated by value, not by string form.

ValueTruthy when
boolit is true
stringit is "true", or non-empty and not "false"
numbersgreater than zero (zero and negatives are false)
[]anynon-empty
map[string]anynon-empty
missing variable or nilnever
anything elsenever

A missing variable is a special case here. In an output position it is an error, but as an if condition the question already carries its own answer, absent data is not true, so the condition reads as false and the render continues.

Loops

for iterates slices, arrays, and maps. endfor is required.

{{ for u in users }}{{ u | key:'email' | lower }}
{{ endfor }}

The two-variable form binds the position under a name you choose. For slices that is the index, for maps the key.

{{ for i, u in users }}{{ i }}: {{ u | key:'email' }}
{{ endfor }}

{{ for name, price in prices }}{{ name }} costs {{ price }}
{{ endfor }}

Auto-bound helpers

Inside the body, sintax binds helper variables derived from the loop variable's name. For a loop over u they are u_index, u_first, and u_last.

HelperValue
<var>_indexzero-based position, for maps the position in sorted key order
<var>_firsttrue on the first iteration
<var>_lasttrue on the last iteration
<var>_keythe map key, bound only for maps without an explicit key variable

They combine naturally with conditionals, for example to place separators between items but not after the last one.

{{ for u in users }}{{ u | key:'email' }}{{ if u_last }}{{ else }}, {{ endif }}{{ endfor }}

Iteration behavior

  • Maps iterate in sorted key order, so output is deterministic across renders.
  • The iterable is a full expression, so a pipeline can shape it in place, as in {{ for u in users | filter:'active',true }}.
  • A missing or nil iterable renders nothing instead of failing, matching how conditions treat absence.
  • Loops nest, and each body sees its own loop's bindings alongside the outer ones.
  • Pointers to slices and maps are dereferenced automatically.
  • Looping over a value that is not iterable, such as a number or a string, fails the render.

Whitespace control

Control tags that sit alone on their own line are trimmed automatically, the tag's line leaves no blank line behind in the output. This is why block examples on this page put {{ endfor }} on its own line without producing stray newlines.

For explicit control, Jinja-style trim markers strip adjacent whitespace. {{- eats whitespace to the left of the tag, -}} to the right.

{{ for u in users }}
  {{- u | key:'email' }}
{{ endfor }}