Is it possible to "grow out of" a Kirby CMS?

When moving pages to an archive, make sure that old URLs are rerouted after moving, otherwise you end up with lots of invalid URLs.

Not sure if this helps with feeling confident in kirby’s performance but it it’s worth a look.

1 Like

Well if you try Kirbys search is just very basic. The mainstream databases have years of time put into making search good. When you start to get to territory of “scott white mountain bike” - when you are searching in titles, tags, anotations and fulltext together - you can’t setup ranking in good way. It also has problems if you are using accented characters and all kinds of other details.

Algolia plugin is exactly that, infact algolia is most probably going to give much better results than your database is ever going to - you would have to use something like elasticsearch or solr to get to that (and spend time setting it up properly)…

BUT - try to bill your client 50usd / month (600 a year) just for search when his last site had perfectly fine fulltext search done using mysql. It might be worth it to ecommerce (better results = more revenue) but on regular sites i guess not.

BTW i am not complaining, kirbys search is enough for lot of things. I don’t think there is any reason why it should be better - search is always going to be separate dedicated thing.


Can you elaborate on this a bit?

flat hirachy
panel subviews slow down if folder contains too many subfolders. for 1000 pages better create 20 x 50 than put 1000 in one folder. the panel subviews parse each contained folder – the more the slower. see more here.

this function gets all pages you have in content. this is not fast if you have a lot. usually you do not need all but a filtered set of them. if you have lots (like 500 or more) pages it might be faster to iterate of the childs yourself and use filterBy() etc. pseudo example…

// get all 20k exposes nested in 10k projects (root: project):
$allProjectMaybeSlow = site()->index()->filterBy('template', 'expose');
$allProjectsFaster = array(); // array
foreach(page('projects')->children()->filterBy('template', 'project')->children()->filterBy('template', 'expose') as $expose) {
   $allProjectsFaster[] = $expose;
$allProjectsFaster = new Pages($allProjectsFaster); // Pages Collection

if your content is static you could remove the impact of site()->index() by turning on caching. or just cache the result of your filter-query.

root of all evil
like always measure first and optimise only if needed.


about Algolia. as far as i can see from their pricing table they offer a free community plan for 10k records and 100k operations. so its not 50 bucks or nothing.

This is only useful if your clients can live with the Algolia logo on their site, though. The pricing seems to be around 50 bucks for all these services, it seems, not only Algolia.

As regards performance, I created a folder with 1000 subpages yesterday, with three images in each folder. Filtering these pages on frontend and searching seems really fast, the Panel lags a bit when accessing the parent, but still fast enough, I think. Will test this a bit more with more images, more content and more HTML after my vacation.


I just wanted to add my 2 cents to this :slight_smile:

I run my personal blog on Kirby, but since I’ve gone Indieweb, I’ve imported all Twitter and Instagram posts I ever posted. Recently I started to use Foursquare/Swarm, so I’m adding about 6 posts a day. At the moment of writing I have 8884 posts, in a folder structure with one folder per year, with folders per day of the year, with folders for every post (YYYY/DDD/N, I’m rewriting URLs to get /YYYY/MM/DD/N/optional-slug). On top of that I have views for only blogposts, photo’s, checkins, and every category/hashtag is searchable.

I have to admit that I got rid of the panel, but that is because I don’t like that it leaves empty fields written out in my content files. (I have a lot of optional fields.) But I do think my site could run with the panel. It might need one hook, but that’s all.

I use Kirby’s standard folder structure, but index it with a database. The database is just an index, so I can get rid of it at any time I feel like and regenerate it. The main content is stored in the .txt-file and if you visit a post-permalink, I don’t access the database at all. The database is only used for the feeds and the category/tag-searches.

Because of all my optional fields, I have quite a lot of template-logic, so I cache the HTML-files of the ‘entry’ snippet. (one permalink version and one feed version) The rest of the page is still rendered without cache, it’s just the entry part (the white block in my current design), and it’s still fast enough to do the caching on the first load after update. I use this caching moment to update the database/index.

So I do the following on page-load:

  • if there is a .html version, and the f::modified() of the .txt version is older, and the snippet is also not modified
    • return the cached html (stop here)
  • if the is no .html version or the .txt was modified
    • update the index/db
  • generate a new .html version from the snippet and return that.

This way I can update via Micropub, via the Panel, via $page->update() or even via FTP, and the db will be updated on next visit of that page.

The only caveat is that the post will not show up in the stream if no-one has visited it yet, so I have added an indexer::add($page) to my Micropub endpoint, and would have to add one on the (and why not also update) hooks. When updating via FTP I have to make sure to visit the page.

All in all, now my site is fast, and still has the benefits of Kirby’s very readable file system.

Please shoot criticism my way now :wink:


Can you elaborate on what information is saved in your database? Just pointers to URLs?

It’s quite dirty at the moment, not a real example of how one should be handling this, but it’s an SQLite database (using Kirby’s database class) with two tables: page and category.

Page has id (in the format 2017/179/1, which is $page->id()) and a couple of fields I like to track: lang, visible, private, published(date), (post)type, deleted.
Category has id, page_id and ‘category’, which is just the string. (And that’s not how one should do it, I know :wink: )

Maybe I can work it out in a proper plugin, but this is the file I keep in my plugins folder at the moment:

1 Like

you could add that you have created a plugin for using micropub with kirby.