Appearance
Cache
Rendered sections are fragment-cached in published mode. Invalidation works by cache tag, so caching only happens on a taggable store — one whose driver extends Laravel's TaggableStore. On any other driver the tag probe fails and FilamentCraft transparently falls back to no-cache: pages render fresh, nothing breaks, and you get no speedup.
| Taggable — caching works | Not taggable — silently uncached |
|---|---|
redis, memcached, apc, array | file, database, dynamodb |
file is Laravel's default, so out of the box you get no fragment caching until you point this at a taggable store.
php
'cache' => [
'enabled' => true,
'store' => null, // shipped default: the app's default cache store
'ttl' => 3600, // fragment lifetime in seconds
'tag_prefix' => 'fc',
],'store' => null (the shipped default) uses the application's default cache store. If that isn't a taggable one, point this at a store that is — for example 'store' => 'redis'.
Draft renders are never fragment-cached: the editor re-renders from the DraftStore on every request, so what you see is always current. (The DraftStore is itself cache-backed, keyed per user and template — it just isn't part of the fragment cache.)
Invalidation is per site
Every cached fragment is tagged site:{id}. Publishing a template or region — or saving site settings — flushes that one tag, which evicts all cached fragments for the site; there is no per-template granularity. Invalidation is wrapped in a try/catch, so a cache hiccup never blocks a publish.
Opting a section out: cacheable()
The render path checks YourSection::cacheable() before touching the cache; return false for sections whose output depends on per-request state:
php
public static function cacheable(): bool
{
return false;
}Built-ins that opt out: Countdown (the remaining time and expired state are computed server-side at render time), the commerce sections (Cart, Checkout, ProductListing, ProductDetail), and Header — but only while a custom localeUrlsUsing() resolver is registered, because host locale URLs are path-dependent and the fragment cache is per locale, not per path.
Cache-key composition
A fragment's key hashes the section's settings and blocks, plus the render color scheme and render context, and appends the locale and the site's theme version:
{tag_prefix}:section:{siteId}:{sectionId}:{sha1(settings+blocks+scheme+context)}:{locale}:{themeVersion}That composition is the "why didn't my change appear" explainer: any settings edit, locale, theme-token change (theme version bumps), or color-scheme switch produces a new key automatically — stale output within the TTL can only come from data the key doesn't see (e.g. an external API a section reads at render time).
tag_prefix prefixes the key, not the tags
tag_prefix namespaces the cache keys so several apps can share one Redis instance. The invalidation tag is always site:{id}, unprefixed — if two apps share a store and a site id, flushes cross over; give them separate Redis databases instead.
