Interesting use cases

Well, no, nothing directly comparing controllers & models, but I have it on my list. It’s a pretty long list …

Do you want us to try and help with the list ?


I’ve been working on an invoicing system for myself over past couple of weeks. My goal was to get a simple system running locally. From here I can add clients and different billing accounts. Also, I can bill in different currencies per invoice, I set an exchange rate and the panel will convert the foreign currency back to my own so that I can keep track of incoming invoices in my own currency (excluding VAT).


For the dashboard I took inspiration from many of our existing plugins/widgets for drafts and stats. These were used as a basis for creating an overview of existing invoice statuses and affairs, that is to keep track of drafts, pending, paid and overdue payments. Invoices are stored in content folders organised by year which I use to generate data for a graph that shows income five years back.

Content Structure & Controller

  • Billing accounts are added as children to my billing preferences including VAT-rate and my address details.
  • Clients and their details are stored under a clients folder.
  • Invoices are added as children under a folder for each given tax year.

The content folder structure works like this:


Much of the data is stored as structure fields and all pages reference each other with a unique id so that I can’t accidentally break a link between an invoice, its client and billing details. An invoice template takes care of accessing all the different data that the invoice needs. Here is my invoice.php controller that I use to access pages of data references by unique id’s:

# site/controller/invoice.php

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

	// Company Details
	$company = page('billing/');
	$companyAddressFormat = strtolower($company->addressformat());

	// Client
	$client = page(page('clients')->children()->findBy('autoid', $page->client()->value()));
	if($client) {
		$clientAddressFormat = strtolower($client->addressformat());

	$currency = page('billing')->currency();
	$vat = page('billing')->vat()->float();

	$billing = page(page('billing')->children()->findBy('autoid', $page->billing()->value()));

	return compact('company',





Using a model for the invoice.php template I perform the calculations for invoice subtotals and adding VAT based on the default VAT-rate.

Creating an Invoice

Creating an invoice is simple. You give it a title, invoice number and select a client from a dropdown menu and also which billing account details you wish to give the client along with an optional note that is displayed on the actual invoice (details regarding overdue payments etc.)

Currently I’ve built two structure fields for adding items to an invoice—either a quantity/rate (also for time based billing) and a fixed rate. The currency applied to the specific invoice is listed beside each inventory item.

At the moment I define my base currency under a billings page where I manage my own details (address, billing accounts, default VAT-rate etc.) I can assign a custom currency per invoice and its exchange rate that will calculate the amount earned in my base currency so that I have an overview of how much tax I’ll have to pay by the end of the year—this I do manually at the moment.

Now for the fun part. The system takes all the information I’ve linked to an invoice and generates it as a page, so I can just hit the preview button and print the page as a PDF and send it off to my clients. When it’s paid and can mark it off under the panel so I can keep track of incoming payments etc.

I’ve set up some basic CSS print styles that makes sure everything looks nice and simple when I print the PDF. Certainly having fun putting the whole thing together!



Looks awesome! I wanted to build such an invoicing system with Kirby for more than a year but never had the time.

Thanks :wink: Thanks again, @lukasbestle, for helping me out get in touch with Jimmy last week!

I am by no means a pro programmer, so there are definite improvements that could be made for further extendibility in terms of creating a model to generate estimates etc. Not quite sure what the next step is at the moment, but it functions quite well in its current form. Any ideas?

Well, such a system always needs to work for the one who uses it.

I would probably add all accounting stuff into it (including versioning with Git to have it conform to German law), but that’s definitely a very huge project (and maybe the reason why I never got to build it ;)).

Yes, I think it also applies here, I’m working in between Denmark and Norway. Manual backups are the way at the moment :smiley:

Perhaps I should write up a more detailed readme on everything I’ve included and how I’ve structured everything. Don’t know if anyone is interested in building git versioning for it or improving the build…?

The benefits of having your own invoicing system in Kirby is clear to me, you can build whatever module you need, be it for different statistics or adding a payment portal with stripe or paypal…

Manual backups wouldn’t be OK in Germany as you need to make sure that each accounting entry can’t be changed without traces. It’s all a bit difficult and in the end the administration probably won’t accept Git anyway because they have never heard of it. :wink:

I see, yes that does make it a lot trickier :dizzy_face:
Do any other options than git come to mind? Building a versioning system from scratch is a bit of an adventure. Do you think it would be worth taking the project that step further?

I would still go for Git, it’s well-known, pretty robust and at least better and more trustable than a homemade solution.

If that kind of tamper protection is required in Denmark/Norway, I’d definitely do it. Otherwise your whole accounting is going to be disregarded. :slight_smile:
But as long as you only track your clients and invoices, it should be fine (the invoices need to be archived of course). Just don’t start tracking your accounting entries. :wink:

In Denmark there is not such a requirement, not entirely sure about Norway. I operate from Denmark at the moment… Hurrah for now :wink:

Will have to look into this in greater detail. Unfortunately I’m not confident/skilled enough to implement git by myself.

Perhaps there should a whole new thread/git repo for further development sometime. Depends on interest I suppose.

Wondering about this auto-git plugin, does a log of changes to files suffice or does it need to be baked into the invoice itself in Germany?

Yes, Auto Git was what I thought of as well.
I don’t know if Git suffices at all, but if it does, a log should be enough. But: INAL. :wink:

I’m going to give it a go! #INAL&sons

1 Like

Checked out language in motion, great idea. Feel like actually trying to learn Japanese now :wink:
Nice description of the structure, however, was wondering, did you by any chance make a repo with the user model? Wanting to implement something like it into this invoicing project above to accept online payment. Would be fantastic to take a look at it, if it’s possible at all.

I’ve been building the same for roughly a year now, pretty much an hour here and hour there!

Oliver, thanks for taking a look at Language in Motion. I don’t have the user model on Github so I just sent you a message with a link to download the file. Hope you find it useful.

1 Like

strangest way i used kirby till now: i created a webpage for a architectural design contest once. sadly i can not share the clients name.

  • applicants could register, creating no-panel-access user accounts.
  • pagebuilder created the applicants folder with about 10 forms groups. optional forms could be created using add/remove tools in frontend.
  • blueprints files where parsed to create html forms automatically. so forms could be changed during test phase easily.
  • uniform plugin with ajax no page reloads on ‘save’) showed all 40 forms in a accordion-style as a web app.

Hi! Could you elaborate on your “no-panel-access” user accounts? I might be searching for a very similar application (Kirby with user registration / restricted area). How/Where did you save them? What amount of data accumulated (how many users…)? Thanks!

In Kirby, you can define users without panel access, they are stored in the standard user folder:

You can also set up your own registration form on the frontend, using Kirby’s user API.