I think the biggest point is to not use a completely flat structure.
Like, donβt do:
β content
ββ articles
ββ ...20k articles here
But have something like
β content
ββ articles
ββ 2024
β ββ dec
β β ββ ...45 articles here
β ββ nov
β β ββ ...30 articles here
.
.
.
(splitting it up into year / month is just an example; it could be anything.)
This way the router should remain fast even without cache.
If you need search (you probably do), Iβve had good results by creating an index in a sqlite db. You would then index that via page hooks.
Snippet from a plugin in a project:
'hooks' => [
'page.create:after' => $pageHandler = include __DIR__ . '/config/hooks/pageAfter.php',
'page.update:after' => $pageHandler,
'page.changeTitle:after' => $pageHandler,
'page.changeSlug:after' => $pageHandler,
'page.changeStatus:after' => $pageHandler,
'page.delete:after' => $pageHandler,
// ...
],
// somewhere in 'pluginfolder/config/hooks/pageAfter.php'
if($p->intendedTemplate()->name() === 'article') {
if(in_array($event->action(), [
'update',
'create',
'changeTitle',
'changeSlug',
'changeStatus',
])) {
if($p->isPublished() && $p->parents()->findBy('status', 'draft') === null) {
ArticleIndex::indexArticle($p);
}
} else if($event->action() === 'delete') {
ArticleIndex::removeArticle($p);
}
}
ArticleIndex is then a class managing the sqlite file, but you could of course also hook up another index like algolia, etc. If possible the index should contains all information you need to display search results snippets, otherwise youβd need to lookup each individual matching article by its uuid (not that bad, but neither particularly fast). Just make sure to keep the content folder the βsingle source of truthβ. The index should be volatile.
For the panel you would then probably also want to extend the default search: Panel search | Kirby CMS to exclude the articles from it and instead add your own from the index.
And thatβs pretty much it, I think.
Of course if youβre able to cache the most often hit pages (homepage with the latest articles?), thatβs better.