timnarr/kirby-snippet-cache

This plugin provides caching functionality for Kirby CMS snippets.

Maintainers

Package info

github.com/timnarr/kirby-snippet-cache

Type:kirby-plugin

pkg:composer/timnarr/kirby-snippet-cache

Statistics

Installs: 102

Dependents: 0

Suggesters: 0

Stars: 8

Open Issues: 0

1.0.0-beta.1 2026-03-24 15:52 UTC

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