Kirby CMS

Everything interesting about Kirby

Kirby is a flat-file CMS which is based on text files and assets organized in nested folders. That makes it really easy to work with.

They made it easy to connect to any datasource like a SQL database, REST API or spreadsheet and create virtual pages on the frontend.

Blueprint Gotcha

If your fields or section don't render or return weird errors, check if the the indentation in the yaml file is consistent. Don't mix tabs and spaces!


Block Editor

Layout blocks, similar to Tumblr or Gutenberg

Virtual Pages with an Existing Database

In Kirby it's easy to consume external data on the frontend. It's also possible to setup a database backend with Kirby's panels.

The basics of reading and writing to a database are described in the guide: Content from a database

What Kirby offers you here is extending and overwriting the Kirby Page object to read and write from the database instead of the filesystem.

The downside of this is, that it's realized in a very opinionated way. Kirby Pages expect a certain data structure that you have to simulate with your database model e.g. the reliance on the slug field1 as identifier or the status has to be in a certain way. A title has to exist in some way.

If you have tabular data, out of the box, Kirby lists your "virtual pages" just with the title field and an info field.

To create a sortable table the Kirby Pagetable Plugin solves this quite nicely. But there is a downside as well. Want to admin a table with 10000 records? As far as I can tell, pagination is done in the frontend, if the 10000 records make it through the wire without a timeout.

My conclusion for the first few tests is: for complex relational database interfaces (customers and orders etc. in an online-shop) use a dedicated system for that. I'm sure it's possible to build a complex database admin interface on top of Kirby's panels, it's just php, but I'm not sure if it's worth it.

It's definitely worth for a single table with a limited amount of data.


var_dump(db::trace()); should give you a complete trace of what’s happening.

var_dump(db::lastQuery()) shows the last query

var_dump(db::lastError()) shows the last error



Add additional fields to $page->content

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

    $page->content = new Kirby\Cms\Content(
                'foo' => 'bar',
                'abc' => 'xyz'
        ), $page->parent()

    // alternative

    return [
        'products' => [
            'foo' => 'bar',
            'abc' => 'xyz'

{{  $page->foo()->upper() }}

<!-- alternative -->

{{  $products->foo()->upper() }}

Debug with Clockwork

Installation Guide

Install Clockwork as extension in your browser Chrome or Firefox

Install Clockwork in your project

$ composer require itsgoingd/clockwork

Open Kirby's index.php and initialize Clockwork right in the beginning:


require __DIR__.'/kirby/bootstrap.php';

$clockwork = Clockwork\Support\Vanilla\Clockwork::init(
        'storage'            => 'sql',
        // sqlite database will be saved directly in the vendor folder
        'storage_database'   => 'sqlite:'.__DIR__.'/clockwork.sqlite',

        'register_helpers'   => true,
        'enable'             => true,
        'storage_expiration' => (24 * 60),

        'requests'           => [
            'except' => [
                // '/api/*/lock',
                // '/api/*/unlock',

        'filter_uris'        => [


All options are described here:

At the end of the index file, where you render the CMS, write the output in a variable, end the Clockwork process and then echo the Kirby output.

// echo (new Kirby)->render();
$output = (new Kirby)->render();

echo $output;

Next you go into your Kirby config.php file to setup a route for Clockworks API:

return [
    'debug'     => true,

    'routes'    => [

            'pattern' => '__clockwork/(:any)',
            'action'  => function ($all) {

    // this is just a neat way to see what hooks are called, in which order.
    'hooks'     => [
        '*' => function ($event) {

Now your php scripts you can measure processing time

clock()->startEvent('twitter-api-call', "Loading user's latest tweets via Twitter API")

// some long running process


and get some fancy bar graphs

or log variables

clock()->debug('writeContent', [$data,$this->getTableColumns()]);

and get insight in your code.


Use Laravel Eloquent in Kirby


If Laravel is part of your project, Kirby makes it easy to bridge the gap.

Laravels Query Builder and Eloquent ORM is pretty nice so the beebmx/kirby-db got you covered here - especially if you have a database that is administrated by an laravel app and happens to be multilingual using spatie/laravel-translatable. To get this data out and in your Kirby site, both packages are working together quite nicely.

And then, if you like template inheritance like in Twig or Laravel Blade templates, even that is possible, with afbora/kirby-blade.

Make sure you install it in the following order. At this time (2020-10-04) the blade templates are based on packages for Laravel 7 and translatable are pulling in packages for Laravel 8 if they are not restrained.

  1. afbora/kirby-blade: Enable Laravel Blade Template Engine for Kirby 3
  2. beebmx/kirby-db: Enable Kirby 3 database support for Illuminate\Database
  3. spatie/laravel-translatable: Making Eloquent models translatable

Blade Templates

Are easy to use and to extend and you can mix it with Kirby's snippets and templates.

The argument to use Blade is having a master layout and inheritance. Of course that comes with some technical debt in form of more laravel packages and memory and disc usage.

  1. you can connect the slug with your id field, but I'm not sure how well that works for writing operations.