Skip to content

Handlebars Engine

binja supports Handlebars template syntax through a dedicated engine.

Installation

Handlebars support is included with binja:

Terminal window
bun add binja

Basic Usage

import * as handlebars from 'binja/engines/handlebars'
const html = await handlebars.render('Hello {{name}}!', { name: 'World' })
// Output: Hello World!

Syntax

Variables

{{name}}
{{user.email}}
{{items.[0]}}

Unescaped Output

Use triple braces for unescaped HTML:

{{{rawHtml}}}

Comments

{{! This is a comment }}
{{!--
This is a
multi-line comment
--}}

Control Structures

if / else

{{#if user}}
Hello {{user.name}}!
{{else}}
Hello Guest!
{{/if}}

unless

{{#unless isAdmin}}
<p>You don't have admin access.</p>
{{/unless}}

each

{{#each items}}
<li>{{this}}</li>
{{/each}}

With index:

{{#each items}}
<li>{{@index}}: {{this}}</li>
{{/each}}

With else (empty):

{{#each items}}
<li>{{this}}</li>
{{else}}
<li>No items found</li>
{{/each}}

with

{{#with user}}
<p>Name: {{name}}</p>
<p>Email: {{email}}</p>
{{/with}}

Loop Variables

VariableDescription
@indexZero-based index
@firstTrue if first iteration
@lastTrue if last iteration
@keyKey for object iteration
{{#each items}}
<li class="{{#if @first}}first{{/if}} {{#if @last}}last{{/if}}">
{{@index}}: {{this}}
</li>
{{/each}}

Helpers

Built-in Helpers

binja’s Handlebars engine supports:

  • if, unless
  • each
  • with

Using binja Filters

All 84+ binja filters work in Handlebars:

const html = await handlebars.render('{{name}}', { name: 'world' })

For filters in Handlebars, use the context:

const html = await handlebars.render('{{upper name}}', {
name: 'world',
upper: (s: string) => s.toUpperCase()
})

Partials

{{>header}}
<main>
{{>content}}
</main>
{{>footer}}

Register partials:

import * as handlebars from 'binja/engines/handlebars'
// Coming soon: partial registration

Comparison with Jinja2

FeatureHandlebarsJinja2
Variables{{var}}{{ var }}
Unescaped{{{var}}}{{ var|safe }}
If{{#if}}{% if %}
Loop{{#each}}{% for %}
Comments{{! }}{# #}
Filtershelpers|filter

Migration from Handlebars.js

Handlebars.js
import Handlebars from 'handlebars'
const template = Handlebars.compile(source)
const html = template(context)
// After: binja
import * as handlebars from 'binja/engines/handlebars'
const html = await handlebars.render(source, context)

Performance

Handlebars templates in binja benefit from:

  • Same optimized runtime as Jinja2
  • Same 84+ built-in filters
  • Template caching
  • AOT compilation support