---
title: "Template syntax"
manual: "Handlebars"
version: "main"
permalink: "https://docs.typo3.org/permalink/cpsit/typo3-handlebars:migration-from-fluid-syntax@main"
source: "Guides/MigrationFromFluid/TemplateSyntax.rst"
rendered: "2026-09-29T09:05:57+00:00"
---

# Template syntax {#migration-from-fluid-syntax}

This page provides side-by-side examples of the most common Fluid constructs
and their Handlebars counterparts. The examples assume a content element with
the variables `header`, `bodytext`, `items`,
and `image`.

-   [Outputting a variable](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:outputting-a-variable@main)
-   [Raw / unescaped output](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:raw-unescaped-output@main)
-   [Conditionals](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:conditionals@main)
-   [Loops](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:loops@main)
-   [Scoping with {{#with}}](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:scoping-with-handlebars-with@main)
-   [Partials](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:partials@main)
-   [Dynamic property access](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:dynamic-property-access@main)
-   [Comments](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:comments@main)
-   [Escaping Handlebars delimiters](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:escaping-handlebars-delimiters@main)

## Outputting a variable {#migration-from-fluid-syntax-output}

Handlebars HTML-escapes every `{{...}}` expression by default.

**Fluid:**

```html
{header}
```

**Handlebars:**

```handlebars
{{header}}
```

## Raw / unescaped output {#migration-from-fluid-syntax-raw}

Use triple braces to output a value without HTML escaping. Reserve this for
content that has already been sanitized (e.g., a `parseFunc`-processed
RTE field).

**Fluid:**

```html
{bodytext -> f:format.raw()}
```

**Handlebars:**

```handlebars
{{{bodytext}}}
```

## Conditionals {#migration-from-fluid-syntax-conditions}

`{{#if}}` is truthy: empty strings, `0`, empty arrays, and
`null` are all falsy. For numeric comparisons, write a helper (see
[Helpers](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:migration-from-fluid-helpers@main)).

**Fluid:**

```html
<f:if condition="{header}">
    <h1>{header}</h1>
</f:if>

<f:if condition="{showTeaser}">
    <f:then><p>{teaser}</p></f:then>
    <f:else><p>{fallback}</p></f:else>
</f:if>
```

**Handlebars:**

```handlebars
{{#if header}}
    <h1>{{header}}</h1>
{{/if}}

{{#if showTeaser}}
    <p>{{teaser}}</p>
{{else}}
    <p>{{fallback}}</p>
{{/if}}
```

Use `{{#unless}}` as shorthand for a negated `{{#if}}`
without an else branch:

**Fluid:**

```html
<f:if condition="{hideDate}">
    <f:else><time>…</time></f:else>
</f:if>
```

**Handlebars:**

```handlebars
{{#unless hideDate}}
    <time>…</time>
{{/unless}}
```

## Loops {#migration-from-fluid-syntax-loops}

Inside `{{#each}}`, `{{this}}` refers to the current
item and `@index` holds the zero-based iteration counter.
`@first` and `@last` are boolean flags for the
boundary items.

**Fluid:**

```html
<f:for each="{items}" as="item" iteration="loop">
    <li class="{f:if(condition: loop.isFirst, then: 'is-first')}">
        {item.title}
    </li>
</f:for>
```

**Handlebars:**

```handlebars
{{#each items}}
    <li{{#if @first}} class="is-first"{{/if}}>
        {{this.title}}
    </li>
{{/each}}
```

Nested `{{#each}}` blocks access the parent scope via `../`:

```handlebars
{{#each categories}}
    <h2>{{this.title}}</h2>
    {{#each this.items}}
        <p>{{this.label}} (category: {{../title}})</p>
    {{/each}}
{{/each}}
```

## Scoping with `{{#with}}` {#migration-from-fluid-syntax-with}

`{{#with}}` sets a new scope root, similar to assigning a sub-object
and then using it directly. Inside the block, properties of the given object are
accessible without a prefix.

**Fluid** (using a variable alias via f:alias):

```html
<f:alias map="{addr: '{data.address}'}">
    {addr.street}, {addr.city}
</f:alias>
```

**Handlebars:**

```handlebars
{{#with data.address}}
    {{street}}, {{city}}
{{/with}}
```

## Partials {#migration-from-fluid-syntax-partials}

Handlebars partials are resolved relative to the configured partial root paths
in the same way as templates. The partial name is the filename without the
`.hbs` extension.

**Fluid:**

```html
<f:render partial="Teaser" />

<f:render partial="Card" arguments="{title: item.title, image: item.image}" />
```

**Handlebars:**

```handlebars
{{> Teaser}}

{{> Card title=item.title image=item.image}}
```

To pass the entire current context to the partial (as Fluid does with the
`arguments="{_all}"` attribute), just omit any arguments:

```handlebars
{{> Teaser}}
```

To pass a completely different context object, provide it as a positional
argument before any hash arguments:

```handlebars
{{> Card item}}
```

## Dynamic property access {#migration-from-fluid-syntax-dynamic-access}

Handlebars dot-path notation resolves nested public properties:
`{{user.address.city}}`. For getter resolution and dynamic key lookups
(where the key itself is a variable), use the built-in `get` helper:

**Fluid:**

```html
{object.{dynamicKey}}
{object.privateProperty.arrayKey}
```

**Handlebars:**

```handlebars
{{get object dynamicKey}}
{{get object 'privateProperty.arrayKey'}}
```

## Comments {#migration-from-fluid-syntax-comments}

Handlebars comments are stripped from the rendered output and never appear in
the HTML source, just like Fluid's `<f:comment>`. Use them for
template-internal notes.

**Fluid:**

```html
<f:comment>this comment is stripped from the output</f:comment>
```

**Handlebars:**

```handlebars
{{!-- this comment is stripped from the output --}}
```

## Escaping Handlebars delimiters {#migration-from-fluid-syntax-escaping}

To output a literal Handlebars expression in the rendered HTML, prefix it
with a backslash:

```handlebars
\{{header}}   {{!-- renders "{{header}}" --}}
```

Handlebars also supports
[raw blocks](https://handlebarsjs.com/guide/block-helpers.html#raw-blocks)
(`{{{{name}}}} … {{{{/name}}}}`). Note that a raw block invokes
a helper with the given name, which must be registered as
[custom helper](https://docs.typo3.org/permalink/cpsit/typo3-handlebars:custom-helpers@main) — the extension does not ship one.

> [!NOTE]
> **See also**
>
> [Escaping Handlebars expressions](https://handlebarsjs.com/guide/expressions.html#escaping-handlebars-expressions)
> in the Handlebars language guide.
