eightynine/filament-page-alerts
Filament Page Alerts adds dismissible alert banners to your Filament admin pages. Define messages, colors, and icons in PHP, target specific pages or show alerts globally, and let users dismiss them per session. Lightweight and easy to configure.
Install the package alongside an existing Filament panel:
composer require eightynine/filament-page-alerts
Before writing any code, open the installed package directory and read two files:
composer.json — confirm which Filament major version it supports (filament/filament constraint). This package targets the Filament 3.x page lifecycle; if you are on Filament 4, verify compatibility before adopting.src/ — locate the alert class (typically something like PageAlert or Alert) and any trait (e.g. HasPageAlerts). These are the two public surfaces you will actually use day-to-day.If the package ships a service provider with publishable config/views, run:
php artisan vendor:publish --tag="filament-page-alerts-config"
php artisan vendor:publish --tag="filament-page-alerts-views"
Most Filament plugins of this shape require registration in your PanelProvider:
public function panel(Panel $panel): Panel
{
return $panel
->plugin(PageAlertsPlugin::make());
}
First use case: a persistent warning banner on a dashboard or resource list that operators cannot miss — deprecation notices, "system read-only in 30 minutes", failed background job counts. Reach for this instead of Notification::make()->send() when the message must survive a page refresh and stay visible until dismissed.
Start by placing a single static alert on one page, confirm it renders, then move on to dynamic alerts.
Static, declarative alerts per page. The lowest-friction pattern is declaring alerts on the page class itself, usually by implementing a method that returns an array of alert objects:
protected function getPageAlerts(): array
{
return [
PageAlert::make()
->title('Scheduled maintenance')
->body('Saturday 02:00–04:00 UTC.')
->warning()
->persistent(),
];
}
Dynamic alerts driven by state. Because the method is evaluated during render, you can gate on application state:
protected function getPageAlerts(): array
{
$alerts = [];
if (! config('billing.enabled')) {
$alerts[] = PageAlert::make()->title('Billing is disabled')->danger();
}
if (auth()->user()->unreadFeedbackCount() > 10) {
$alerts[] = PageAlert::make()
->title('Feedback backlog')
->body('You have more than 10 items to review.')
->warning();
}
return $alerts;
}
Centralise via a base page class. Rather than duplicating the method across dozens of resources, create App\Filament\Pages\BasePage that implements the trait and merges a panel-wide set of alerts with page-specific ones. All resources extend it. This is the single highest-leverage pattern: one place to add a global banner, one place to throttle it.
Scope by page type. Alerts that make sense on ListRecords (bulk-state warnings) rarely make sense on EditRecord (a focused edit form). Implement the trait per resource group rather than globally on every page, so you do not create a banner that clutters every screen.
Pair with authorization. Wrap alerts in ->visible(fn () => auth()->user()->can(...)) if the package supports visibility callbacks — otherwise return [] early from the method. Never leak infrastructure detail into an alert shown to every role.
Dismissal workflow. Decide up front whether a dismissal is per-session (cheap, resets on logout) or stored per-user (requires a table or users.meta column and a listener on the dismiss event). The package may handle one or neither; if it only hides client-side, your "dismissed" state is lost on reload and users will re-report the alert.
Testing. Alerts returned from a method are trivially unit-testable: instantiate the page, call the method, assert the array shape. Prefer testing the method over the rendered Livewire output — component-level assertions on banner text are brittle.
composer.json and expect breaking API changes between minor releases. Read the CHANGELOG before every composer update.Livewire component. Keep database queries inside it to a minimum — cache counts in a static property or once().getPageAlerts to alerts or getAlerts between versions. If alerts silently do not appear, verify the method name against the installed src/ — a wrong method name fails with no error, only a missing banner.->plugin(...) is the most common "it's installed but nothing shows" cause. There is usually no exception, just silence.php artisan filament:assets (or vendor:publish --tag=filament-assets) may be needed after install and after every update.EditRecord pages can push form actions below the fold on smaller screens. Test on a laptop viewport, not just a large monitor.PageAlert subclass lets you attach actions (e.g. a "Review now" link). Prefer subclassing over editing the published vendor view, so updates remain mergeable.dd() it? (5) Are assets built?RenderHook::PAGE_START registering a Blade view — roughly 30 lines of code. Treat this package as a convenience, not a dependency you cannot replace.How can I help you explore Laravel packages today?