Skip to main content

Handlebars in five minutes

Handlebars is the template engine behind Asgard's Template mode, letting you produce dynamic text with concise syntax.

The basics​

Handlebars inserts dynamic content with braces, and there are two forms:

Double braces versus triple braces​

Double braces {{}} — HTML escaped

Hello {{name}}! Your order number is {{orderNumber}}

Triple braces {{{}}} — not escaped

Hello {{{name}}}! Your order number is {{{orderNumber}}}
SyntaxPurposeHTML escapingExample
{{}}Ordinary text output✅ escaped{{content}} → <script>
{{{}}}Raw output❌ not escaped{{{content}}} → <script>

What to use in Asgard​

In Asgard, use triple braces {{{}}} in most cases, because:

  • It avoids unintended conversion: special characters are not mangled (< becoming &lt;, say)
  • It keeps data intact: the variable's content comes out as it went in
Hello {{{name}}}! Your order number is {{{orderNumber}}}

Output:

Hello Alice! Your order number is ORD20240115001

📖 Learning the syntax properly
The full Handlebars syntax is in the official documentation

Core syntax​

Inserting a variable​

Hello {{{user.name}}}! Your membership tier is {{{user.level}}}

Conditionals​

{{#if hasNewOrders}}
You have
{{{newOrderCount}}}
new orders
{{else}}
No new orders right now
{{/if}}

Loops​

• Products:
{{#each products}}
{{{@index}}}.
{{{name}}}
- NT$
{{{price}}}
{{/each}}

Asgard's built-in helpers​

Asgard provides eight helpers:

{{{history 0 -1}}}
<!-- conversation history -->

{{{historySize}}}
<!-- how many messages -->

{{{toJson user}}}
<!-- convert to JSON -->

{{{urlEncode searchKeyword}}}
<!-- URL encode -->

{{{xpathExtract xmlData '/root/item'}}}
<!-- XML lookup -->

{{{vecToStr vector '[' ']' ','}}}
<!-- vector to string -->

{{{isoNow 'Asia/Taipei'}}}
<!-- the time now -->

{{{isoToday 'Asia/Taipei'}}}
<!-- today's date -->

Worked examples​

A basic message template​

Hello
{{{user.name}}}!
System status:
• Messages: {{{historySize}}}
• The time now: {{{isoNow 'Asia/Taipei'}}}

{{#if hasUpdates}}
Recent messages:
{{{history -3 -1}}}
{{/if}}

A button template​

{
"type": "BUTTON",
"title": "{{{user.name}}}'s details",
"text": "Membership details:\n{{{toJson user}}}",
"buttons": [
{
"label": "See the history",
"action": {
"type": "MESSAGE",
"text": "Show the conversation history"
}
}
]
}

An API query​

• Search: {{{urlEncode query}}}
• Queried at: {{{isoNow 'Asia/Taipei'}}}

{{#if xmlResponse}}
• Results:
{{{xpathExtract xmlResponse '//item/title'}}}
{{/if}}

Choosing between Template and Expression​

SituationUseWhy
Text templatesTemplateConcise syntax
Complex computationExpressionThe whole of JavaScript
ConditionalsTemplateBuilt in
ArithmeticExpressionMore flexible

Quick checklist​

✅ Insert a variable: {{{variable}}}
✅ Conditional: {{#if condition}}
✅ Loop: {{#each array}}
✅ Asgard helpers: eight of them
✅ Object properties: {{{user.name}}} for nested access

Going further​

Standard Handlebars syntax plus Asgard's helpers is enough to build capable dynamic message templates.