jeffersongoncalves/filament-page-cache
A Filament plugin that adds page caching to your admin panel, storing rendered pages so repeat visits load faster. Simple to install and configure, it helps cut database queries and improve performance in Filament-powered applications.
PageCachePlugin is a Filament panel plugin that exposes a "Page cache" admin page (list cached URLs, clear individual entries or the whole cache) inside your panel. Start here:
Install and register the plugin in the panel provider that should own the cache UI — usually your admin panel, not a public-facing one:
public function panel(Panel $panel): Panel
{
return $panel
->id('admin')
// ...
->plugin(PageCachePlugin::make());
}
Look first at the plugin class and the Page class, not the package README. PageCachePlugin is where panel-facing configuration lives (including the new navigationGroup()), and the Page class is a normal Filament Page — it is the thing you extend when you need different behaviour. The plugin registers the page, so most "how do I change X" questions resolve to either a plugin setter or a subclassed page.
Check the config file and cache driver early. The page is only a UI over Laravel's cache/response-cache layer; confirm which store is in use per environment before you start clicking buttons, because cache:clear in local will not tell you anything about production behaviour.
First use case: open the panel, find the "Page cache" entry, load a public page in another tab, and confirm it appears/clears from that screen. That two-minute loop validates the whole chain (route middleware, cache store, panel authorization) before you wire anything into deploys.
As of 3.1.0 the entry no longer has to live in the package's translated "Settings" group — you can place it in one of your own groups with navigationGroup(), which is the first thing most teams will want to change on a fresh install.
Place the page in an existing navigation group. This is the headline of 3.1.0 and matches how most panels are already organised:
PageCachePlugin::make()
->navigationGroup('Operations');
Pass a closure when the label is translated, so the translation is resolved at render time rather than at panel boot:
PageCachePlugin::make()
->navigationGroup(fn (): string => __('admin.navigation.settings'));
Reuse your app's existing translation keys. If your resources already use __('admin.navigation.settings'), use the same key here rather than a new one — Filament groups navigation by the resolved label string, so reusing the key is what actually merges the page into that group instead of creating a near-duplicate group beside it.
Multi-panel setups. Register the plugin only in panels where the cache UI belongs. If you have a admin and a ops panel that share navigation structure, either register it in both (accepting two entry points) or register once and gate access with canAccess()/policy rather than duplicating the page.
Feature-flag by environment or role. Wrapping registration keeps the page out of local/staging where it invites accidental cache clears:
->plugin(
PageCachePlugin::make()
->navigationGroup(fn (): string => __('admin.navigation.settings'))
)
…combined with the panel's ->when() or a config flag, and a policy on the page so only trusted roles can hit the clear-all action.
Prefer the UI for one-off invalidation, automate the routine case. Day-to-day, developers use the page to clear a single stale URL after a content fix; deployments and content publishes should clear programmatically (observer/saved hook, or a deploy step). Don't make "someone opens the admin and clicks clear" part of a release process.
Treat the page as a starting point, not a fixture. When you need extra columns, filters, or an audit trail of who cleared what, subclass the package Page and register your subclass — that is the intended extension path and survives minor upgrades better than patching the vendor view.
setLocale() in middleware, use the closure. A string will freeze the label in whatever locale was active during boot and can silently split your navigation group in two.__('admin.navigation.settings') in one place and 'Settings' in another produces two groups that look identical in English but diverge in other locales. Grep your resources for the key you intend to use before picking one.navigationGroup(), the page still lands in the package's translated Settings group — existing installs see no difference after upgrading to 3.1.0. This release is additive; no migration or config publish is required.navigationSort, navigationLabel, icon collisions) that weren't visible in the package's isolated group. Check the sidebar in a non-English locale too.How can I help you explore Laravel packages today?