Kirby is very versatile and can be used for things that are a little out of the ordinary. Let's assume that you need to create a Kiosk application for use in a showroom or museum setting. The app should run on Desktop computers as well as Android Tablets and iPads.
The space the Kiosk will be used in has very patchy or no internet connection, so the application needs to be entirely self-contained, and make no external internet calls at all.
This recipe will cover using Kirby to handle the content and imagery, and generating a static version via 11ty. From there, we can use Electron Builder to generate the desktop versions, and Capacitor to create the mobile device apps.
If you have not used Kirby headless before, please take a look at the Going Headless cookbook guide before continuing, as this will explain the basic principles.
To keep this guide simple, we will be using data from the Kirby KQL Sandbox which does not need any authentication. In reality, you will likely be using a local install of Kirby as a source for the data.
It would be safe to disable authentication if that is the case. If you are using a publicly accessible headless instance of Kirby, using authentication is strongly advised. Making use of DotENV is also recommended.
To begin with, we will need to set up 11ty in accordance with the documentation. You can also use the Kirby Eleventykit as a basis for this, which already has a simple connection setup. This guide assumes a basic understanding of 11ty.
With that out the way, we can make a start with getting our data from Kirby and into 11ty.
We will make a small site the pulls in the Photography section of the Starter Kit, along with the text and images to make a basic information site.
_data folder, create a
photography.js file with the following code in it:
This will enable us to generate a list of the photography pages on the main
index.html file of the project. You can do this by editing the
index.njk file to contain the following:
This uses the data pulled in from Kirby to generate a list of the available Photography articles. At this point (and after a little CSS!) we should have something like this in the browser:
So far, so good. The next step is to create the individual post pages. We can do this with a little more Nunjucks in a photography subfolder. This will give us our subpages based on the data coming in from Kirby.
So there we have the basics of our little site. We have made an index page, allowing us to click through to the desired article, and we have individual pages for each item. 11ty automatically generated all this from the JSON data provided to us by Kirby.
There is just one small problem. We need this app to run offline, without making any external calls. If you take a close look at the URLs for the images, you can see they are in fact being pulled in remotely:
We need to convert these into static assets within our projects file system, so that we can reference them from our code base rather than via a URL. Let's fix that!
Next, we need to update our
.eleventy.js file too with a shortcode that will store the images locally and generate WebP & AVIF versions for us at the same time.
Moving back to the Nunjuck's template for the index page, we adjust the call on the image shortcode:
The short code expects a
src for the image, in this case we are feeding it a poster thumbnail image via
item.poster.url. Next, we can set an
alt text value. Thirdly, we can set a folder name to store the images in, using
/assets/images as a base.
In this case, the images will be generated in an
/assets/images/home folder. Finally, we can pass a set of sizes to trigger the source set images.
The loop should now look like this:
If we build the project now, and take a look at the generated HTML, we can see that we do indeed now have local images with absolute URLS:
At this stage, we currently have a site running statically, that could be deployed to even very basic web hosting. Now we can tackle the next stage - let't turn this into a desktop application!
Now for the exciting stuff. We need to do a little prep before we can generate our app, since we need to create some icons, and a background for the Apple DMG file.
We need a little CLI tool to help us out here. Install it globally:
The next step is to create a 1024 x 1024 image to use as an icon. Store it in a folder called
icons/src in the root of your project. Create a folder
icons/output to store the generated icons.
We can run this through
electron-icon-builder to generate all the different sized icons and formats. Adjust the input path to match your absolute folder location on your harddisk.
For the DMG app backgrounds, we need to create two images, one at 540 x 380 with a name of
background.tiff and another at 1080 x 760 called
[email protected]. The latter will be used on Retina macs, and the file names are important.
Remember to leave room at the bottom of the image, as this is where the install icons will sit. Store these images in the output folder with all the icons created in the previous step.
Let's move on to configuring the build for the app, now that we have all of our assets ready. Install
electron-serve via yarn.
In the root of your project, create a file called
main.js with the following code inside:
This is a simple configuration for
electron. The details of this code are outside the scope of this article, but can be referred to in the Electron documentation if you wish to learn more.
There are two parts of this you may wish to alter. Most browsers prevent the auto-playing of video unless it is muted. The following line removes this restriction, allowing you to autoplay video with sound on without requiring user input.
The second part that may be altered is the
It is here that you can set the initial width and height of the application window, the favicon, as well as whether to show things like the address bar and status bar.
Finally, add the following to your
These settings control the Electron Builder build process to alter the output for various platforms. This is documented in the Electron Builder docs if you wish to alter the values.
It's finally moment of truth time! Let's add a couple of NPM scripts to
package.json so that we can easily kick off the build:
yarn desktop will generate a desktop app depending on the platform you are running the project on. If you are running on Windows, you will end up with a Windows installer in the
dist folder. If you are on Apple Silicon Mac you will end up with a DMG that will only run on another Apple Silicon Mac. Running
yarn macuniversal will generate an app that will work on both Apple Silicon and Intel based Macs.
yarn desktop or
yarn macuniversal depending on the platform you are running on. If all goes well, you will find an executable application inside the
dist folder. In my case, I am running on Apple Silicon and successfully get a DMG file allowing me to install the app.
After installing the app, we can finally see the result of all our hard work!
So that's the desktop application finished up. Let's take things further now, and generate mobile applications for iOS and Android from the same source files.
We will be using Capacitor to help us out with this, which in turn depends on Xcode and Android Studio. Please set these up in accordance with the Capacitor environment setup and installing Capacitor itself into your project before proceeding.
Secondly, we need to configure Capacitor. In the root of your project, create a
capacitor.config.ts file, containing the following:
Let's kick off with building the Android app. We need to add Capacitors Android package and the Android platform to make this happen.
You will now find that an
Android folder has been created in the root of your project, containing source code for your project. We can open this in Android Studio with the following:
The first time you do this, Android Studio should do a bunch of setting up due to the dependencies in the project. Just allow it to do its thing, which may take some time depending on your machine. However, once done, opening the project again later should be much quicker.
With an Emulator configured in Android Studio, we can go ahead and hit the green Play button on the main toolbar, which will launch the project and allow us to preview it on an emulated device.
Next up is creating an iOS version. The process is quite similar. First we need to add the Capacitor iOS Package:
Then generate the Xcode project in a similar fashion as we did before:
Finally, we can make generating the projects simpler by adding those commands to the scripts section of
There we have it! We now have means to create desktop and mobile devices applications, whilst leaning on the power of Kirby and 11ty to do the heavy lifting. Where to now?
Whilst out of the scope of this guide, from here you can build the distributable files in Xcode and Android Studio, and publish them via the respective app stores. I hope you found this guide useful, and I would like to see what you make with this!