Kirby 3 Component for semantic templates with Handlebars and Mustache

Installs: 180

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 0

Open Issues: 1


3.0.9 2019-12-20 09:02 UTC

This package is auto-updated.

Last update: 2020-01-20 09:10:23 UTC


Release Stars Downloads Issues Build Status Coverage Status Maintainability Demo Gitter Twitter

Kirby 3 Component for semantic templates with Handlebars and Mustache

Commercial Usage

This plugin is free but if you use it in a commercial project please consider to


  • unzip as folder site/plugins/kirby3-handlebars or
  • git submodule add site/plugins/kirby3-handlebars or
  • composer require bnomei/kirby3-handlebars

Usage as Template Component

  • Put your handlebars templates in the site/templates/ folder.
  • Prepare data in controllers stored at site/controllers/* to be available in the templates.
  • In case you do not have a handlebar template with matching name it will fallback to the required default.hbs file.


Title: Home


{{ title }} of <i>{{ c }}</i>.
{{#counting}} <br> - {{ label }} {{/counting}}


return function ($site, $page, $kirby) {
    return [
        'title' => $page->title(), // Home
        'c'=> 'Cassia',
        'counting' => [
            ['label' => 1],
            ['label' => 2],
            ['label' => 3],

Note: kirby, site, pages and page can not be used as top-level data keys. They will be overwritten by Kirby Objects and later pruned by the plugin for serialization.


Home of <i>Cassia</i>
<br>- 1
<br>- 2
<br>- 3


Partials are stored at /site/template/partials. Think of them as reusable blocks injected into your handlebars templates before they get compiled. That is why partials need no cache files.


Title: 🍕


{{> @piece-of-cake this }}

Note: @ and this are used by the JS version of Handlebars in Fractal to denote a partial and forward the data. Both will be automatically removed on PHP compilation by this plugin.


Piece of {{ cake }}


return function ($site, $page, $kirby) {
    return ['cake' => $page->title()];


Piece of 🍕

Rapid Localhost Development

See tests on how to install Fractal and point it to the the /site/templates-folder.

cd test/fractal;
npm install;
npm run dev;

Or create a static build

npm run build;

Usage without Component

Maybe you just need to parse some handlebars and not use the template component. Disable the component with the bnomei.handlebars.component config setting and just use the provided helper functions. The hbs()/handlebars() take the same parameters like the Kirby snippet() function.


Render unto {{ c }} the things that are {{ c }}'s, and unto {{ g }} the things that are {{ g }}'s.


    // echo template 'render-unto'
    // data from site/controllers/home.php merged with custom array
    hbs('render-unto', ['c'=> 'Caesar', 'g'=>'God']); 

    // return template 'render-unto'
    $string = hbs('render-unto', ['c' => 'Cat', 'g' => 'Dog'], true);

Render unto Caesar the things that are Caesar's, and unto God the things that are God's. Render unto Cat the things that are Cat's, and unto Dog the things that are Dog's.

Performance & Caching

LightnCandy is extremely fast and lightweight since its compiled to raw PHP just like Blade Templates. Templates are only precompiled to native PHP on modification. This could be disabled with the lnc setting but you really should not.

Build-In Cache

Render output is not cached by default. You can activate it using the render setting. The render cache is devalidated if either template or data is modified. But since a hash of the data is created every time this has a slight performance impact.


return [
    'bnomei.handlebars.cache.render' => true, // default: false        

Lapse Plugin

  • A faster and more robust solution would be to utilize the Lapse Plugin inside the controllers.
  • It can automatically and efficiently take care of tracking the modification of Kirby Objects without creating a data hash.
  • Further more Kirby Objects will automatically be stored as array/string/int/float/bool/null. For example you do not have to call ->value() on every field.


return function ($site, $page, $kirby) {

    $collection = collection('mycollection');
    $data = Lapse::io(
        // will create key from array of strings and/or objects
        ['myhash', $page, $page->children()->images(), $collection, $site],

        // this will only executed on modification 
        function () use ($site, $page, $collection) {
            return [
                // will not break serialization => automatically store ->value() of fields
                'author' => $site->author(),
                'title' => $page->title(),
                'hero' => $page->children()->images()->first()->srcset()->html(),
                'count' => $collection->count(),
    return $data;


bnomei.handlebars. Default Description
component true if false no templating will be handled by this plugin and you need to use the hbs()/handlebars() functions.
no-escape true By default data sent to template will NOT be escaped. This way your templates can render data formated as html. You can use Kirbys Field Methods $field->kirbytext(), $field->html() or the Kirby\Toolkit\Str-Class functions to escape your text properly. Alternatively you can set it to false and use {{{ var }}} triple mustaches.
dir-templates callback returning kirby()->roots()->templates()
dir-partials callback returning kirby()->roots()->templates().'/partials'
extension-input hbs
extension-output lnc hbs compiled to php
render false cache render based on hash of data
files true cache paths of template and partial files
lnc true cache compiled php



This plugin is provided "as is" with no guarantee. Use it at your own risk and always test it yourself before using it in a production environment. If you find any issues, please create a new issue.



It is discouraged to use this plugin in any project that promotes racism, sexism, homophobia, animal abuse, violence or any other form of hate speech.