Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Flash Laravel Package

caffeinated/flash

Caffeinated Flash is a Laravel package for session-based flash notifications with a fluent API. It supports Bootstrap-style alert levels, multiple messages, and customizable templates, letting you queue success, error, warning, and info messages in controllers and render them in your views.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish in one pass:

composer require caffeinated/flash
php artisan vendor:publish --provider="Caffeinated\Flash\FlashServiceProvider"

The service provider is auto-discovered on Laravel 5.5+. Publishing gives you config/flash.php (session key, level list, view/markup settings) and the package Blade views you can override under resources/views/vendor/flash/.

Where to look first, in order:

  1. config/flash.php — confirm the session key and which view is rendered. Everything else in this package is a thin wrapper around session()->flash(), so this file is the whole mental model.
  2. The published Blade view — this is the file you will actually edit to match your design system.
  3. vendor/caffeinated/flash/src/ — small enough to read end-to-end in ten minutes; do it before you debug anything.

Place the render call once, in your main layout, above {{ $slot }} / @yield('content'):

{{-- resources/views/layouts/app.blade.php --}}
@include('flash::message')

First use case — the CRUD redirect you write a hundred times:

public function store(StorePostRequest $request)
{
    $post = Post::create($request->validated());

    flash()->success('Post created.');

    return redirect()->route('posts.show', $post);
}

The message survives the redirect because it lives in the session; the next request renders and consumes it.

Implementation Patterns

Fluent queueing in controllers. All four levels are chainable and can be called multiple times in one request — the package accumulates them and renders a stack:

flash()->success('Invoice sent.')->info('A copy was emailed to accounting.');

Move the vocabulary out of controllers. Wrap it in a small app-level service so severity choices are consistent and the package is easy to swap later:

class Notifier
{
    public function saved(string $subject): void { flash()->success("{$subject} saved."); }
    public function failed(string $subject): void { flash()->error("Could not save {$subject}."); }
}

Inject that instead of calling flash() in 40 controllers. If the package dies (see Gotchas), you change one class.

Pair it with a redirect, not a view return. The intended lifecycle is flash() → redirect(). If you return a view directly from the same request, the message is queued for the next request and appears at a confusing time. Use a redirect even when you could render directly, or use session()->now() for genuinely immediate messages.

Form validation stays separate. Validation errors belong in the $errors bag so @error and old() keep working. Use flash()->error() for domain/business failures (payment declined, duplicate SKU), not for field-level validation — otherwise users get a banner with no red outline on the offending field.

Custom markup via the published view. The shipped markup is Bootstrap-era. Copy it into resources/views/vendor/flash/ and rewrite against your design tokens:

@if (session()->has(config('flash.session_key')))
    @foreach (session(config('flash.session_key')) as $message)
        <div class="c-alert c-alert--{{ $message['level'] }}" role="alert">
            {{ $message['message'] }}
        </div>
    @endforeach
@endif

Match the array keys to whatever the package writes (dump the session key once to confirm — level/message are the usual shape).

Integration with a single page-level partial. If your app has multiple layouts (app, guest, admin), put the include in a shared partial partials/flash.blade.php and @include it from each layout. Avoid duplicating the loop; divergence between layouts is the most common source of "the message shows on the dashboard but not in admin."

Middleware for cross-cutting banners. For things like "Your trial expires in 3 days", a middleware that calls flash()->warning(...) on GET requests works, but scope it so it doesn't fire on AJAX/XHR or you'll accumulate duplicates in session for polling clients.

Testing. Use followingRedirects() and assert on the rendered output, or assert the session directly:

$this->post('/posts', $data)
    ->assertRedirect('/posts/1')
    ->assertSessionHas(config('flash.session_key'));

If your session driver is array in phpunit.xml, the flash data behaves correctly within a test but never persists between separate test requests — keep the multi-request assertion inside one test method.

Gotchas and Tips

The package is stale — verify it installs at all. Last release is 2021-03-24 and the newest documented change is "Laravel 8 support." Its illuminate/support constraint almost certainly caps at ^8.0, so on Laravel 9/10/11 composer require will fail or silently resolve to an old Symfony stack. Check first:

composer why-not caffeinated/flash

Don't fight it with --ignore-platform-reqs. If you're past Laravel 8, either fork and widen the constraint (the source is tiny — realistically a one-line composer.json edit plus a test run) or replace it with a 20-line service class over Laravel's native session()->flash('status', ...). Budget for that decision before you write flash()->success() in 200 places.

Two flash mechanisms in one app cause duplicate banners. If some controllers still use ->with('status', ...) and the layout renders both, users see two boxes. Grep for with('status' and consolidate.

The message may not be consumed. Some versions of the shipped view render the session data without forgetting it; if banners reappear on subsequent pages, explicitly forget the key after rendering your partial (session()->forget(config('flash.session_key'))). Test by navigating two pages after a create.

Bootstrap version drift in the shipped markup. Bootstrap 5 renamed data-dismiss → data-bs-dismiss, close → btn-close, and dropped alert-block. The pre-built view will produce dismissed-proof alerts with no close button. Always publish and own the view.

Escaping. Package views may use {!! !!} for message content. If you ever pass user-supplied text (a name, a filename) into flash()->success($input), that's an XSS path. Escape at the call site or fix the view.

Config caching eats edits. After changing config/flash.php on a deployed environment, run php artisan config:cache again. A stale cached session key means messages queue under one key and your view reads another — messages vanish with no error.

Session driver dependency. cookie driver has a ~4KB payload limit; you won't hit it with messages, but array (in tests) and database/redis behave differently across requests. If banners work locally and not in staging, check the driver before checking the package.

Livewire / Inertia break the model. In a Livewire component action, flash() writes to the session and the component re-renders without a full page load, so nothing appears until a real navigation. Use Livewire's own $this->dispatchBrowserEvent / session()->flash() with a full redirect for these. With Inertia, the message sits server-side and your JS never learns about it — pass it through shared props instead.

No support policy past Laravel 8. Pin the version in composer.json and add a note to your upgrade checklist; treat any future framework bump as "fork or replace" decision point.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route