Skip to content

Helpers & variables reference

Everything available inside a template (.hbs): Ekit helpers, utility helpers, built-in Handlebars helpers and the variables provided by the rendering engine.


Ekit helpers

Helper Usage Result
#single {{#single ekdata.article}}…{{/single}} Renders the block with the record as this. Renders nothing when the value is empty; takes the first item of a list.
ekasset {{ekasset 'css/main.css'}} URL of a site asset (assets/ folder).
ekdbasset <img src="{{ekdbasset this.image}}"> URL of a file stored in a file field of a table. Empty when the field is empty.
ekmedia {{ekmedia 'photos/team.jpg'}} URL of a project media file, by its path in the project's media folder. For file fields, prefer ekdbasset.
ektrans {{ektrans 'HERO_TITLE'}} Translation of the key in the current language (i18n/<lang>.json). Returns the key itself when it is missing.
t {{t 'HERO_TITLE'}} Short alias of ektrans.
<link rel="stylesheet" href="{{ekasset 'css/index.css'}}">

{{#single ekdata.article}}
  <h1>{{this.title}}</h1>
  <img src="{{ekdbasset this.cover}}" alt="{{this.title}}">
{{/single}}

Text & formatting

Helper Usage Result
upper {{upper this.city}} PARIS
lower {{lower this.code}} fr-fr
substring {{substring this.name 0 1}} Characters from start to end (e.g. initials).
truncate {{truncate this.summary 120}} Cuts to the given length and adds .... The length is required.
default {{default this.subtitle 'No subtitle'}} The value, or the fallback when the value is empty.
split {{#each (split this.cities ',')}}<span>{{this}}</span>{{/each}} Text cut into a list (pieces trimmed, empty ones removed). The separator is optional (, by default).
trim {{trim this.code}} The text without the surrounding spaces.
join {{join this.tags ' · '}} A list joined into one text.

Dates

Two helpers are available, with different format syntaxes:

Helper Usage Format tokens
date {{date this.publishedAt 'DD/MM/YYYY HH:mm'}} DD, MM, YYYY, HH, mm — default DD/MM/YYYY
formatDate {{formatDate this.publishedAt 'd MMMM yyyy'}} date-fns tokens — default yyyy-MM-dd
year © {{year}} Current year

An empty or invalid date renders nothing (date).


Logic

Comparison helpers are used as sub-expressions, inside parentheses:

Helper Usage
eq {{#if (eq this.status 'published')}}…{{/if}}
and {{#if (and this.online this.featured)}}…{{/if}} — any number of values: all must be filled
or {{#if (or this.promo this.new this.sale)}}…{{/if}} — any number of values: one is enough
ternary <li class="{{ternary (eq view 'blog') 'active' ''}}">
lt lte gt gte {{#if (lt this.price 10)}}…{{/if}} — lower than, lower or equal, greater than, greater or equal. Numbers (also written as text, like "9") and dates (2026-10-09) are compared by value; an empty value is never lower or greater.

ternary is also useful in datasources, to build values from the URL:

sort:
  field: "{{ternary (eq query.sort 'price') 'price' 'title'}}"

Data & URLs

Helper Usage Result
json {{json this.tags}} JSON text of a value (for debugging or data attributes).
jsonUrl ?cursor={{jsonUrl cursors.articles}} JSON encoded for a URL — used for pagination links.
ekform {{#ekform "contact"}} … {{/ekform}} Site form: <form> tag with the right address, spam protection and language.
list {{#list this.tags}}<span>{{this}}</span>{{/list}} Renders the block for each item.
linked {{#each (linked @root.ekdata.contacts 'company' this)}}…{{/each}} Entries of a list whose relation field (company) points to the given record — for example the contacts of the company shown in the loop.

Relations between tables

A relation field is always a list of the linked entries, even when there is only one link. Each linked entry has its uid and the fields of its table:

{{#each ekdata.contacts}}
  <p>{{this.name}} — {{#each this.company}}{{this.name}}{{/each}}</p>
{{/each}}

To show the entries that point to the current record (the contacts of each company), declare both datasources and use linked. Inside a loop, other datasources are reached through @root:

{{#each ekdata.companies}}
  <h2>{{this.name}}</h2>
  <ul>
    {{#each (linked @root.ekdata.contacts 'company' this)}}<li>{{this.name}}</li>{{/each}}
  </ul>
{{/each}}

Passing data to JavaScript

Do not write {{{json …}}} inside a <script> tag: a value containing </script> would break the page. Use ekit.data instead — it is escaped safely.


Unknown helpers

Only the helpers of this page exist. A page that calls another one ({{formatMoney …}}) cannot be displayed: visitors get a "page temporarily unavailable" error, and the AI assistant never writes such a call.

Built-in Handlebars helpers

Helper Usage
#each {{#each ekdata.articles}}…{{/each}} — inside: @index, @first, @last
#if / else {{#if this.image}}…{{else}}…{{/if}}
#unless {{#unless this.online}}Offline{{/unless}}
#with {{#with this.author}}{{name}}{{/with}}
lookup {{lookup ekdata 'my-alias'}} — access a property whose name contains dashes
> {{> header}} — include a partial

Variables available in templates

Variable Content
ekdata.<alias> Data of each datasource: a list, a single record (uid / slug) or a Method response
this Current record inside #each / #single
lang Current language (en, fr…)
view Current view name
slug Slug of the URL (/en/blog/<slug>)
params params.lang, params.view, params.slug
query URL query parameters (?q=… → query.q)
queryString Current query string, including ? (empty when there is none)
i18n Translations of the current language (i18n.HERO_TITLE)
metas Values of the metas block of the front matter, variables resolved
record Record loaded by the page (uid / slug datasource)
cursors.<alias> / prevCursors.<alias> Pagination cursors of a list datasource
hasMore.<alias> / hasPrev.<alias> true when a next / previous page exists
total.<alias> / pages.<alias> Number of entries (filter included) and of pages — with count: true
page.<alias> Number of the page displayed (1 on the first page)

Inside a loop or a partial: @root

In {{#each}} and in partials, the context is the current entry: {{lang}} is empty there. Use {{@root.lang}} (and @root. for any page value), which works everywhere — for example <a href="/{{@root.lang}}/blog/{{this.slug}}/">.

SEO tags

The metas block is not written into the page automatically: the layout outputs it, so you keep full control over the <head>:

<head>
  <title>{{metas.title}}</title>
  <meta name="description" content="{{metas.description}}">
  <meta property="og:title" content="{{metas.og.title}}">
  {{#if metas.og.image}}<meta property="og:image" content="{{metas.og.image}}">{{/if}}
</head>