Since the large Kirby site question seems to keep popping up, here’s the stuff you can expect kirby 2 to handle and what not.
The website in question is about authors and their books.
Currently there are about 2’300 authors and 13’800 books published, in a “many to many relationship” (each author has many books, each book has many authors).
Each one of those is saved as a single page.
All books are subpages of a “books” page.
All authors are subpages of a “authors” page.
What Kirby does:
- Editing the pages in the panel: opening and saving a specific page in the panel actually works surprisingly fine. It opens only the file it needs to and no more. However, I disabled the “status” option because I don’t want the panel to go and rename my folders.
What Kirby does not:
Route to a single page: opening a page on the frontend is surprisingly slow because of how the routing works. I initially thought that having a route that exactly matches the folder name would be fast. It isn’t. Since page URLs can be localized, and that localization is saved in the content files, the default router needs to read all pages at each given level. E.g: a route to
- reads all first level pages to find “books”
- reads all subpages of books to find “1234” (and if you have 13000 subpages this becomes rather slow).
To overcome this issue I added my own dumber version of a router, that resolves to the text file on it’s own:
$books = new Page(site(), 'books'); $book = new Page($books, $id);
Note that if you use a model for that page, you need to instantiate that instead:
$books = new Page(site(), 'books'); $model = page::$models["book"]; $item = new $model($books, $id);
(this code obviously leaves some stuff out for clarity)
the previous point means you can’t no longer localize those urls, except if you come up with your own logic to map those urls to your filesystem. It may also break other features that are implemented in the default router.
Panel ui: I’ve created panel widgets to find, open and create new pages. You wouldn’t want the default panel to handle so many pages. Therefore I’ve hidden the authors and books container pages (set
hide: trueon the parent blueprints).
Search: Can’t expect it to work.
On the frontend you need your own search engine. I used a combination of mongodb and elasticsearch that I keep updated with hooks to index my pages.
In the panel you need to replace the search route with your own logic or your editors will probably kill your server while trying to use the search box.
Many to many relationships: the filesystem structure implies only a one to many relationship (“parent-child” if you prefer). So you need to save some kind of foreign keys in your content files. On my pages those are saved as array of ids on both sides of the relationship. E.g: adding a book to an author means adding the author id to the book and the book id to the author. I keep those in sync with hooks.
Expect trouble when deleting pages. Deleting a book means going through all its authors and removing the book id. However, the delete hook is run after the page has been deleted and you have no access to the page content. This means you have no straight forward way to get the list of authors from which it needs to be removed. I worked around this by searching trough mongodb to get the list of stuff I need to update, before I sync the changes to the index.
There are of course some other limitations, like you don’t want to use
$site->index() or the likes… Listing and paginating stuff might be slow; you want to get lists from a database. If you have many thumbnails (~100) on a single page it might be slower than expected, something in the “check if a thumb is already created” stuff is rather slow. I’ve worked around this by memcaching the parts that contain thumbnails.
Would I do it again? Probably not.
The project started when I thought the panel would be flexible enough to handle directly content from a database. But it is not (or at least I didn’t manage to do it - the fields are way to much coupled to the filesystem, which was unexpected). Having the panel save to the filesystem was a not desired, but essential, workaround.
Maybe Kirby 3 panel handles this better.