To add Toastr notifications in Laravel 13, install the toastr and jquery packages with npm, import them in resources/js/app.js, flash a message in your controller with with('success', '...'), and call toastr.success() from the layout when the session holds that message. This guide targets Laravel 13 and PHP 8.3 or newer with Vite.
What is Toastr?
Toastr is a small JavaScript library that shows non-blocking pop-up messages (toasts) for success, info, warning and error states. It depends on jQuery. Laravel does not ship it, so you add it yourself and connect it to flash messages.
Prerequisites
- Laravel 13 on PHP 8.3 or newer, with Node.js and npm.
- Vite, which is the default asset bundler in a new Laravel project.
- A layout Blade file that loads your assets with
@vite.
Step 1: Install the packages
npm install toastr jqueryStep 2: Import and expose Toastr
// resources/js/app.js
import './bootstrap';
import $ from 'jquery';
import toastr from 'toastr';
import 'toastr/build/toastr.min.css';
window.$ = window.jQuery = $;
window.toastr = toastr;
toastr.options = {
closeButton: true,
progressBar: true,
newestOnTop: true,
positionClass: 'toast-top-right',
timeOut: 4000,
};Toastr reads jQuery from the global scope, so assigning window.$ and window.jQuery before using it prevents the common "jQuery is not defined" error. Exposing window.toastr lets Blade views call it.
Step 3: Build the assets
npm run devUse npm run build in production. Make sure the layout contains @vite(['resources/css/app.css', 'resources/js/app.js']).
Step 4: How do you flash a message from the controller?
public function store(Request $request)
{
$data = $request->validate([
'title' => ['required', 'string', 'max:255'],
]);
Post::create($data);
return redirect()
->route('posts.index')
->with('success', 'Post created successfully.');
}
public function destroy(Post $post)
{
$post->delete();
return back()->with('error', 'Post deleted.');
}Step 5: Show the toast from the layout
Create one partial and include it in your main layout, just before the closing body tag.
{{-- resources/views/partials/toastr.blade.php --}}
@php
$types = ['success', 'info', 'warning', 'error'];
@endphp
<script>
document.addEventListener('DOMContentLoaded', () => {
@foreach ($types as $type)
@if (session($type))
toastr.{{ $type }}(@js(session($type)));
@endif
@endforeach
@if ($errors->any())
@foreach ($errors->all() as $message)
toastr.error(@js($message));
@endforeach
@endif
});
</script>The @js directive encodes the value as safe JavaScript, including quotes, which prevents broken scripts and script injection from message text. Never print flash messages inside a JavaScript string with plain {{ }} and manual quotes.
{{-- resources/views/layouts/app.blade.php --}}
@include('partials.toastr')
</body>How do validation errors become toasts?
When validation fails, Laravel redirects back and shares an $errors bag with the view. The partial above loops over $errors->all() and shows each message as an error toast. You can keep the inline error messages next to the fields as well.
How do you trigger a toast from JavaScript or AJAX?
fetch('/posts', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
body: JSON.stringify({ title: 'Hello' }),
})
.then(async (response) => {
const data = await response.json();
if (!response.ok) throw data;
toastr.success('Saved.');
})
.catch((error) => {
toastr.error(error.message ?? 'Something went wrong.');
});For a 422 validation response, error.errors holds the messages by field, so you can loop over it as shown for the session errors.
How do you set a custom title or options for one toast?
Every Toastr method accepts a message, an optional title and an optional options object that overrides the global options for that one toast.
toastr.warning('Your session expires soon.', 'Heads up', { timeOut: 8000 });
toastr.error('Payment failed.', 'Error', { closeButton: true, timeOut: 0 });A timeOut of 0 keeps the toast on screen until the user closes it. Use that only for messages that need attention, such as a failed payment.
How do you keep the partial easy to test?
A feature test cannot run JavaScript, but it can check that the flash data reaches the page. That is enough to catch a wrong session key.
it('shows the success message after creating a post', function () {
$this->actingAs(User::factory()->create())
->followingRedirects()
->post('/posts', ['title' => 'Hello'])
->assertSee('Post created successfully.');
});For a real browser check of the toast itself, use a manual test or a browser testing tool such as Laravel Dusk.
Common mistakes
- Not importing jQuery before Toastr, which gives a "$ is not a function" error.
- Forgetting to rebuild assets after the npm install.
- Loading the partial before the Vite script, so
toastris undefined when the code runs. TheDOMContentLoadedlistener helps here, but only if the module script has loaded. - Putting user input inside the message without
@js. - Showing the same message twice because both a toast and an inline alert render the session value.
How do you verify it works?
- Open the browser console and type
toastr.info('Hello'). A toast should appear. If not, check the asset loading. - Submit a valid form and confirm the green success toast shows after the redirect.
- Submit an invalid form and confirm each validation message appears as a red toast.
- Refresh the page. The toast should not appear again because flash data lasts for one request only.
FAQ
Does Toastr need jQuery?
Yes. Toastr is a jQuery plugin. If you want to avoid jQuery, choose a library that has no jQuery dependency.
Can I use Toastr with Livewire or Inertia?
You can. Dispatch a browser event or pass flash data as a shared prop, and call toastr in a listener. The setup differs from Blade, so follow the pattern of your stack.
Why does the toast not show after a redirect?
Check that the controller used with() on the redirect, and that the key matches the one in the partial.
Can I change the position?
Yes. Set positionClass in toastr.options, for example toast-bottom-right.



