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:
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>