A flash message is a one-time message stored in the session that survives only the next request. In Laravel 13 you set it with redirect()->with('status', 'Saved!') and show it in Blade with the @session directive. This guide shows the basics, a reusable alert component that supports several message types, and how flash data differs from validation errors.
Targets: Laravel 13 (PHP 8.3 to 8.5) and Blade. No JavaScript library is needed.
How do I flash a message after a redirect?
Chain with() to a redirect:
public function store(Request $request): RedirectResponse
{
$data = $request->validate([
'title' => ['required', 'string', 'max:255'],
]);
Post::create($data);
return redirect()->route('posts.index')->with('success', 'Post created successfully.');
}This stores success in the session for the next request only. After that request it is gone, so a page refresh does not show it again.
You can also flash data manually, which is useful in middleware or non-redirect flows:
session()->flash('success', 'Post created successfully.');How do I display it in Blade?
Use the @session directive. It runs only when the key exists and gives you the value in $value:
@session('success')
<div class="alert alert-success">{{ $value }}</div>
@endsession
@session('error')
<div class="alert alert-danger">{{ $value }}</div>
@endsessionPut this near the top of your main layout, for example resources/views/layouts/app.blade.php, so every page can show messages. The older way also works: @if (session('success')) ... {{ session('success') }} ... @endif.
How do I make a reusable alert component?
Create the component file resources/views/components/flash.blade.php:
@php
$types = [
'success' => 'alert-success',
'error' => 'alert-danger',
'warning' => 'alert-warning',
'info' => 'alert-info',
];
@endphp
@foreach ($types as $key => $class)
@session($key)
<div class="alert {{ $class }}" role="alert">{{ $value }}</div>
@endsession
@endforeachAdd one line to your layout: <x-flash />. Now any controller can use with('success', ...), with('error', ...), with('warning', ...) or with('info', ...) and the message appears with the right style. The class names above are Bootstrap classes; replace them with your own CSS or Tailwind classes.
What is the difference between flash messages and validation errors?
When validation fails, Laravel redirects back and flashes the errors in a special $errors variable, along with the old input for old(). Show them separately:
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endifHow do I keep a flash message for one more request?
Use reflash() to keep all flash data, or keep() for specific keys:
session()->reflash();
session()->keep(['success']);A common case is a redirect chain where the first redirect would otherwise consume the message.
How do I auto-hide the message after a few seconds?
Add a tiny script to the layout:
document.querySelectorAll('.alert').forEach((el) => {
setTimeout(() => el.remove(), 5000);
});Keep error messages visible longer, or until the user closes them, so people have time to read them.
How do I check that it works?
- Submit a form that redirects with
with('success', ...)and confirm the alert appears. - Refresh the page. The alert should disappear.
- Submit invalid data and confirm that validation errors appear instead.
In a feature test you can also assert the flash data:
$this->post('/posts', ['title' => 'Hello'])
->assertRedirect('/posts')
->assertSessionHas('success', 'Post created successfully.');Common mistakes
- Flashing on a non-redirect response: the data is for the next request. Redirect after saving.
- Printing with {!! !!}: use
{{ }}so user-supplied text is escaped. - Forgetting the session middleware: flash data needs sessions, which web routes provide. API routes do not.
- Different keys in controller and view:
successandstatusare not the same key. - Putting the alert only on one page: put it in the layout.
FAQ
Can I flash an array or object?
Yes, you can flash arrays. Keep it small, because it is stored in the session.
Why does the message show twice?
You probably render both an @session block in the layout and another one in the page. Keep one place.
Does this work with Inertia or Livewire?
The session part is the same. With Inertia you share flash data as props, and in Livewire you can dispatch events or use session flash and render it in the component.



