laragear/alerts
Laragear Alerts is a Laravel package for adding persistent, database-backed alerts to your app. Define targeted announcements, schedule when they appear, and track read or dismissed status with a simple API—ideal for in-app notices and user messages.
Install and confirm discovery
composer require laragear/alerts
Laragear packages ship with package discovery, so the service provider and Alert facade should register automatically. Verify with php artisan about (or php artisan package:discover) before writing any code — if the facade alias is missing, add it manually to config/app.php.
Publish the config first
php artisan vendor:publish --tag=alerts-config
This is the single most important step: the config file tells you which session key is used, whether alerts persist across redirects, and which view/component renders them. Read it before reading anything else.
Where to look first, in order
README.md — the usage surface is small; the examples are the API.config/alerts.php — keys, view path, session/flash behavior.src/AlertsServiceProvider.php — what gets bound, what gets published, what Blade components/directives are registered.src/Facades/...) — the full list of public methods, which is usually the entire contract.First use case: flash an alert after a form submit
use Laragear\Alerts\Facades\Alert;
public function store(StorePostRequest $request)
{
$post = Post::create($request->validated());
Alert::success('Post published.');
return redirect()->route('posts.show', $post);
}
Then drop the package's renderer into your layout once (resources/views/layouts/app.blade.php), inside <body>, above @yield('content') or right before </body> depending on whether you want inline or toast-style output. Match the component/directive name from the README — that is the only line of frontend wiring you need.
That's the whole loop: set on the backend, redirect, render in the layout. Everything else is variation.
Stack multiple alerts in one request
The value of this package over a single session()->flash('status', ...) is that you can queue several alerts of different severities and have them render in order:
Alert::success('Import finished.');
Alert::warning('3 rows were skipped.');
Alert::danger('1 duplicate email was merged.');
Use this in importers, bulk actions, and validation-adjacent flows where a form only shows one error but the operation produced several distinct outcomes.
Keep alert construction out of controllers
For anything nontrivial, put alert logic in an action or a small Alerts service so it's testable and reusable:
class PublishPost
{
public function __invoke(Post $post): void
{
$post->publish();
Alert::success("“{$post->title}” is live.")
->withLink(route('posts.show', $post)); // if supported by the builder
}
}
If the package returns a fluent builder from the facade (common in Laragear packages), chain options on the returned object rather than making multiple calls — it keeps one alert as one statement and makes it obvious which options apply to which alert.
Global alerts via middleware
For account-level warnings (unverified email, expiring subscription, impersonation banner), build a middleware that pushes an alert when a condition holds and let the layout renderer pick it up:
public function handle($request, Closure $next)
{
if ($request->user()?->isImpersonated()) {
Alert::info('You are viewing as another user.')->persistent();
}
return $next($request);
}
This is the pattern that saves the most repetition — you stop sprinkling alert calls across controllers.
Inertia / SPA integration
The package stores alerts server-side (likely session-backed). For Inertia, share them through HandleInertiaRequests::share() so the frontend owns rendering, and disable the Blade renderer to avoid double rendering:
public function share(Request $request): array
{
return [
'alerts' => Alert::all(), // check the facade for the read method
];
}
Then render with your own Vue/React toast component. The package effectively becomes a typed flash-bag rather than a view layer.
Livewire
Set alerts inside a component action and either let the layout renderer handle them on redirect, or dispatch a browser event from the renderer so a frontend toast library picks it up. Watch for the case where a Livewire action doesn't redirect — the alerts may accumulate across renders if nothing consumes them.
Testing
Assertions are the fastest way to lock in alert behavior:
Alert::shouldReceive('success')->once()->with('Post published.');
$this->post(route('posts.store'), $data)
->assertRedirect();
Where the package provides session-backed assertions (e.g. assertSessionHasAlerts), prefer them over mocking — they exercise the real serialization path.
Publish the views
To restyle, publish the view/component and edit the copy:
php artisan vendor:publish --tag=alerts-views
Keep the published file under version control and add a note in the README about which package version it was taken from — published views drift when the package updates.
It is a small package — read the source, not just the docs
41 stars means the README is the primary and possibly only reference. Budget 20 minutes to read src/ end-to-end. You will learn the exact method names, the fluent builder's options, and whether alerts are session-flashed or request-scoped. Do this before designing around it, because the API surface is likely a dozen methods, not a framework.
Session-flash vs. persist is the key semantic
Most bugs with this class of package come from assuming the wrong lifetime. Confirm:
If Alert::danger() set during an API call leaks into the next browser request from the same session, you have your answer and need to guard the calls.
Beware alerts in queued jobs and API responses
Session is not available in queued contexts (or is the wrong session). Any alert call inside a job, notification, or middleware running on api routes without a session middleware stack will either throw or silently vanish. Route those through events/broadcasting instead, and reserve this package for web requests.
Config cache hides your edits
php artisan config:cache is standard in production, so a config change that "doesn't work" locally after caching is expected. Clear with php artisan optimize:clear when debugging — and never read the config at runtime in a way that assumes fresh values.
HTML escaping
If alerts accept raw/HTML content, anything user-derived (names, titles, filenames) must be escaped before being passed in. Treat the alert message as an output sink: it's tempting to interpolate $post->title and forget that a title containing <script> now renders in the layout of every page the user visits next.
Double rendering
The most common integration mistake: rendering alerts both in the layout Blade component and in a Livewire/Inertia frontend, then wondering why every toast appears twice. Pick one renderer per application and delete the other.
Ordering is not guaranteed to be semantic
Multiple alerts may not render in severity order. If "error first, then warnings" matters to you, sort explicitly when reading them out rather than relying on insertion order.
Override, don't fork
Extension points are: the config file, the published views, and the container binding for the alert manager (if it's bound as a singleton/interface). If you need extra behavior — database-backed alert history, per-user read state — build it as a wrapper service that calls the package, rather than patching vendor/. Composer will overwrite your edits.
Version pinning and maintenance
Last release 2026-10-16 with a low star count means the package is maintained but thinly used. Pin the minor version in composer.json (^1.0 rather than *), add an alert-rendering smoke test to CI, and keep the integration surface small (a facade call in controllers + one Blade line in the layout) so replacing it with a homegrown flash-bag later is a one-hour job, not a refactor.
Sanity-check before committing
Write one feature test that hits a route, follows the redirect, and asserts the alert text appears in the response. That single test catches 90% of the failure modes above: not published, not rendered, wrong session driver, double-rendered, or escaped incorrectly.
How can I help you explore Laravel packages today?