Mustache is a logic-less templating language used to dynamically render content. A template defines the structure and appearance of the output using placeholders. A JSON document provides the data that fills those placeholders.
The rendering engine processes the template and injects data from the JSON document, replacing tags like {{title}} with actual values such as Breaking News.
Example Template:
<h1>{{title}}</h1>
<p>Hi {{user.name}} {{user.lastname}}</p>
<p>{{summary}}</p>
JSON:
{
"title": "Breaking News",
"summary": "Latest updates from the newsroom.",
"user": {
"name": "John",
"lastname": "Smith"
}
}
Rendered Output:
<h1>Breaking News</h1>
<p>Hi John Smith</p>
<p>Latest updates from the newsroom.</p>
Marfeel Layouts use Mustache templating syntax with the Trimou rendering engine. Trimou extends Mustache through its Helpers API, enabling conditional functions, format adapters, and string manipulation. Read more about Trimou rendering engine.
Tip: Trimou syntax works in both HTML and CSS files. Use the same helpers to inject variables, conditionals, and logic into your stylesheets.
Basic Syntax
| Tag Type | Syntax | Purpose |
|---|---|---|
| Variable | {{name}} |
Print escaped data |
| Unescaped HTML | {{{html}}} |
Print raw HTML |
| Section | {{#items}} |
Loop and conditional block |
| Inverted | {{^items}} |
Render if false or empty |
Display Content Conditionally
Use # to render content when a value exists. Use ^ to render content when a value is false or missing.
{{#articleIsClosed}}
Subscribe to continue reading
{{/articleIsClosed}}
{{^articleIsClosed}}
Did you like this article?
{{/articleIsClosed}}
Conditional Helpers
if tag — Render content when a condition is met:
{{#if "2 eq 2"}} This is shown {{/if}}
{{#if "2 eq 1"}} This is not shown {{/if}}
isNull and isNotNull — Check whether a variable exists:
{{#isNotNull var}} This is shown if var is not null {{/isNotNull}}
{{#isNull var}} This is shown if var is null {{/isNull}}
ifs — Inline conditional that outputs content only if the value exists:
{{#ifs variable}}{{variable}}, {{/ifs}}fallback
This is useful for comma-separated values with fallbacks. For example, a font family with fallback:
{{#ifs customFont}}{{customFont}}, {{/ifs}}system-ui
Outputs CustomFont, system-ui if customFont is set, or just system-ui if not.
choose, when, and otherwise — Handle multiple conditions:
{{#choose}}
{{#when "2 eq 3"}} Not shown {{/when}}
{{#when "2 eq 1"}} Not shown either {{/when}}
{{#otherwise}} This is shown {{/otherwise}}
{{/choose}}
Combine Conditions with Variables
Use article data inside conditional expressions:
{{#choose}}
{{#when "section eq 'OPINION'"}}
{{section}} by {{author}}
{{og:description}}
{{/when}}
{{#otherwise}}
{{og:description}}
{{/otherwise}}
{{/choose}}
Access Array Elements
Use dot notation with the index number. Arrays are zero-indexed.
JSON:
{
"colors": ["black", "blue", "red"]
}
Template:
{{colors.0}} → black
{{colors.1}} → blue
{{colors.2}} → red
Iterate Over Arrays
Loop through arrays using the # operator or {{#each}} helper. Inside the loop, object properties are available at root level. Reference the entire object with {{this}}.
JSON:
{
"users": [
{"name": "John", "surname": "Doe"},
{"name": "Anna", "surname": "Smith"}
]
}
Template:
<ol>
{{#users}}
<li>{{surname}}, {{name}}</li>
{{/users}}
</ol>
Rendered Output:
<ol>
<li>Doe, John</li>
<li>Smith, Anna</li>
</ol>
Iteration Properties
Access metadata about the current iteration using the iter object:
| Property | Description |
|---|---|
iter.index |
Current position (starts at 1) |
iter.position |
Current position (starts at 0) |
iter.hasNext |
True if more items follow |
iter.isFirst |
True if first item |
iter.isLast |
True if last item |
Format Dates and Times
Datetime fields must be in ISO format: yyyy-MM-dd hh:mm:ss.
timeFormat — Format dates with a specific pattern:
{{timeFormat publishTime pattern="dd-MM-yyyy"}}
Available patterns: yyyy, yy, MM, MMM, MMMM, dd, H, HH, m, mm, s, ss, a (AM/PM).
prettyTime — Display relative dates:
{{prettyTime updateDate locale='es'}}
Outputs: 2 months ago or Hace 43 minutos depending on locale.
Manipulate Strings with Expression Language
Use Java Expression Language for string manipulation and custom transformations.
Basic syntax:
{{#setEl i="<expression>"}} {{i}} {{/setEl}}
Example — Resize an image URL:
If your image URL is https://domain.com/images/image_id?width=1200, reduce the width:
{{#setEl i="img.split('?')[0]"}}{{i}}?width=240{{/setEl}}
Reference Current Item in Loops
Inside loops, use #set to reference the current item in expressions:
{{#each items}}
{{#set item=this}}
{{#setEl i="item.doSomething()"}} {{i}} {{/setEl}}
{{/set}}
{{/each}}
Important: You cannot reference this directly inside Expression Language. Always assign it to a variable with #set first.
Declare Inline Variables
Define reusable variables with {{+varName}} and reference them with {{>varName}}.
Template:
{{+name}}John{{/name}}
{{+surName}}Doe{{/surName}}
{{+fullName}}
{{>surName}}, {{>name}}
{{/fullName}}
Signed: {{>fullName}}.
Rendered Output:
Signed: Doe, John.
Inline variables add whitespace before and after when rendered. Plan your layout accordingly.
Render Raw HTML
Variables escape HTML characters by default. Use triple braces to render HTML as-is.
| Syntax | Input | Output |
|---|---|---|
{{foo}} |
<b>bar</b> |
<b>bar</b> |
{{{foo}}} |
<b>bar</b> |
bar |
Calculate Averages
Use avgEl to calculate averages from arrays:
{{#avgEl "<data expression>" ["<mapper expression>"] [<decimals>]}}{{avg}}{{/avgEl}}
| Parameter | Required | Description |
|---|---|---|
| Data expression | Yes | The array to traverse |
| Mapper expression | No | Expression to apply per item (e.g., i.price) |
| Decimals | No | Rounding precision (HALF_UP) |
Examples:
{{#avgEl "data.products" "i.price" 2}}{{avg}}{{/avgEl}}
{{#avgEl "data.products" "i.name.length()" 0}}{{avg}}{{/avgEl}}
{{#avgEl "data.scores" 1}}{{avg}}{{/avgEl}}
Data Model
Each experience type—Recommender, Amplify, MarfeelPass—provides its own JSON model to the rendering engine.
The Layout Editor includes a JSON tab with example data for testing. The full data structure is available at data.experienceResponse.experience.data, with convenience aliases like recommendations for common paths.
Custom Fields are layout parameters you can configure per experience. Reference them with:
{{layoutProps.myVar}}
Read more about Custom Fields in the Layout Editor.
Going Deeper
- Layout Editor: The visual interface for building and testing layouts
- Amplify Layouts: Creating social media visuals
- Recommender Layouts: Customizing article recommendations