timnarr / kirby-snippet-cache
This plugin provides caching functionality for Kirby CMS snippets.
Package info
github.com/timnarr/kirby-snippet-cache
Type:kirby-plugin
pkg:composer/timnarr/kirby-snippet-cache
Requires
- php: >=8.1.0
- getkirby/composer-installer: ^1.2
Requires (Dev)
This package is auto-updated.
Last update: 2026-03-24 16:02:03 UTC
README
This plugin provides caching for Kirby CMS snippet output via a custom snippet component.
It may be useful if you can't use Kirby's overall page cache, but have snippets that do extensive queries or loop and transform a lot of data.
Installation
Download
Download and copy this repository to /site/plugins/kirby-snippet-cache.
Composer
composer require timnarr/kirby-snippet-cache
Usage
Enable the plugin and configure which snippets to cache in your config.php. Templates stay unchanged — no code modifications required.
return [ 'timnarr.snippet-cache' => [ 'cache' => true, 'include' => [ 'globals/header', 'globals/footer', ] ] ];
<?php snippet('globals/header') ?> <?php snippet('globals/footer') ?> // Fallback arrays work too <?php snippet(['articles/' . $page->postType(), 'articles/default'], compact('article')) ?>
Options
Set options in your config.php:
return [ 'timnarr.snippet-cache' => [ 'cache' => false, // Enable the plugin 'duration' => 0, // Global default duration in minutes. 0 = infinite. 'include' => [], // Which snippets to cache (see below) 'exclude' => [], // Which snippets to never cache (see below) ] ];
| Option | Default | Description |
|---|---|---|
cache |
false |
Set to true to enable the plugin. |
duration |
0 |
Global default cache duration in minutes. 0 = infinite. |
include |
[] |
Opt-in list of snippets to cache. See patterns below. |
exclude |
[] |
List of snippets to never cache. Takes priority over include. |
include
Controls which snippets are cached. Three formats are supported:
Wildcard — cache all snippets:
'include' => '*',
Indexed list — use global duration for all:
'include' => [ 'globals/header', 'globals/footer', 'blocks/*', // glob pattern: matches all snippets in blocks/ ],
Associative — custom duration per snippet (in minutes, or true for global default):
'include' => [ 'globals/header' => true, // uses global duration 'globals/footer' => true, 'blocks/*' => 30, // 30 minutes for all blocks/ snippets 'shuffle-teaser' => 60, ],
exclude
Snippets matching exclude are never cached, regardless of include. Takes priority over include.
Pattern array — same glob syntax as include:
'exclude' => [ 'form/*', // never cache any snippet in form/ 'globals/nav', // never cache this specific snippet ],
Callback — for dynamic logic:
'exclude' => fn ($name) => str_starts_with($name, 'form/'),
The callback receives the resolved snippet name and must return a boolean.
Glob patterns
Both include and exclude (when used as an array) support glob-style * wildcards via PHP's fnmatch(). Note that * matches across / boundaries — blocks/* also matches blocks/sub/snippet. Use more specific patterns if needed.
User-specific content and session data
The plugin uses the same automatic detection as Kirby's built-in page cache: if a snippet calls csrf(), $kirby->session(), or reads a cookie via Cookie::get(), Kirby internally flips $kirby->response()->cache() to false. The plugin checks this flag after rendering and skips storing the output if that happened — no configuration needed.
Warning
Automatic detection only works with Kirby's built-in methods. If a snippet accesses $_SESSION or $_COOKIE directly (bypassing Kirby's API), the plugin cannot detect this. Those snippets must be excluded manually via exclude.
Important
Regardless of whether automatic detection applies — always test any snippet that works with sessions, cookies, CSRF tokens, or user-specific data under realistic conditions (logged in, logged out, multiple users). Caching bugs in this area can cause sensitive content to leak across visitors and are difficult to catch without explicit testing.
No support for slots
⚠️ Snippets that use slots are never cached, because the slot content is dynamic PHP executed by the caller. These snippets fall through to Kirby's default rendering automatically.
Cache invalidation
The entire snippet cache is flushed automatically on any of the following events:
| Category | Hooks |
|---|---|
| Page content | page.update, page.changeStatus, page.changeTitle, page.changeSlug, page.changeTemplate, page.changeNum, page.create, page.delete, page.duplicate |
| Files | file.create, file.update, file.replace, file.changeName, file.delete |
| Site | site.update, site.changeTitle |
| Languages | language.create, language.update, language.delete |
Multi-language support
On multi-language sites, caches are stored per language. Each language gets its own cached output, so content is always served in the correct language.
License
MIT License Copyright © 2023-present Tim Narr