masterro/laravel-flashes
masterro/laravel-flashes provides a clean, fluent API for setting and retrieving session flash messages in Laravel applications, making it easy to display success, error, warning, and info notifications in your Blade views.
composer require masterro/laravel-flashes
The package is a standard Laravel package: it ships a service provider (auto-discovered on Laravel 5.5+), a config file, and a set of Blade views for rendering messages. If auto-discovery is disabled, register the provider manually in config/app.php.
Then publish the assets:
php artisan vendor:publish
# pick the flashes provider from the list
Where to look first, in this order:
config/flashes.php — this is the control panel. It defines the available message types (typically success, error/danger, info, warning), which view renders them, and usually the CSS classes or framework (Bootstrap vs Tailwind) used for markup.resources/views/vendor/flashes/ (after publishing) — the actual markup. This is what you'll edit when your design system doesn't match the default.flash() helper vs. Flash facade vs. both) and the session key used.First use case — flash from a controller, render in the layout:
public function store(StorePostRequest $request)
{
$post = Post::create($request->validated());
flash()->success('Post created.');
return redirect()->route('posts.index');
}
In your app layout, render once, above the content:
<body>
@include('flashes::messages') {{-- exact include/component name comes from the config's view key --}}
@yield('content')
</body>
That's the whole happy path. The package is thin by design — one session bucket, one renderer — so treat it as a convention layer rather than a framework.
One render point, always. Put the include in your single layouts/app.blade.php. The most common failure mode with flash packages is rendering in both the layout and an individual page, producing doubled messages.
Multiple messages per request. Most flashers accumulate rather than overwrite, so you can stack them:
flash()->success('Profile updated.');
flash()->info('A verification email was sent.');
return back();
If your version overwrites instead, check the config/README for a push-style method before assuming a bug.
Redirect chains and reflash. Flash data is available for exactly one request. If your "redirect target" redirects again (common with auth gates or wizard flows), the message is gone. Call session()->reflash() in the intermediate controller, or session()->keep(['flash']).
Validation errors are not flash messages. Laravel already handles $errors via the error bag. Don't route validation output through the flasher — it duplicates state and loses field-level targeting.
Type-to-CSS mapping belongs in config. Adding a warning type should be a config entry plus, at most, a small partial. Keep the markup accessible:
<div role="alert" class="alert alert-{{ $type }}">
{{ $message }}
</div>
Inertia / SPA responses. Session flashes won't cross an XHR boundary on their own. Share them from HandleInertiaRequests::share(), or return them in the JSON payload and render client-side. Livewire is similar: for same-page updates prefer a browser event over a session flash, since there's no fresh request to consume it.
Testing. Assert on session rather than rendered HTML where possible:
$this->post('/posts', $data)
->assertRedirect('/posts')
->assertSessionHas('flash');
Wrap this in a small custom assertion if you flash from many endpoints — the session key shape is an implementation detail you don't want spread across fifty tests.
Facade for indirection. If a Flash facade is available, injecting/mocking it beats calling the global helper in jobs, listeners, or services where you want test isolation.
Helper name collision. laracasts/flash also defines a global flash() helper. Installing both produces a fatal "cannot redeclare function" error. Pick one flasher per project.
Cookie session driver truncates. The default cookie payload is small (~4KB before encryption overhead). Long flash messages or many stacked ones will silently vanish. Use file/redis/database sessions in production if you rely on this.
Config and view caching. After editing config/flashes.php or the published views, run php artisan config:clear and php artisan view:clear. In CI/deploy pipelines a stale config cache is the number-one cause of "it works locally."
Tailwind purge. Class names assembled dynamically from config (alert-{{ $type }}) are invisible to Tailwind's scanner. Either safelist the variants in tailwind.config.js or write literal classes into the partial.
Escaping. Default Blade {{ }} escapes output — keep it that way. Only reach for {!! !!} if you control every message string; never pass raw user input into a flash message, since it's rendered on the next page, which makes XSS easy to miss in review.
Duplicated markup after publishing views. Publishing copies into resources/views/vendor/flashes/; from then on the package's own view updates are ignored. That's intentional, but note it when upgrading.
Debugging. dd(session()->all()) right after the redirect request starts is the fastest way to confirm whether the message was written at all — distinguishing a flasher problem from a render/include problem.
Maturity risk. The package has very few stars and zero dependents, which means: pin an exact version ("masterro/laravel-flashes": "1.0.x"), read the source before adopting (it's small enough to audit in ten minutes), and expect no ecosystem support for new Laravel majors. If your risk tolerance is low, the entire feature is roughly thirty lines — a session array plus a Blade partial — and spatie/laravel-flash or laracasts/flash are more battle-tested alternatives. What this package buys you is convention and a pre-wired config, not capability.
Extension points worth knowing. The config file, the published views, and the container binding for the flasher class. If you need custom behaviour (grouping, auto-dismiss JS, toast positioning), subclass or swap that binding in a service provider rather than patching vendor files.
How can I help you explore Laravel packages today?