Muhammad Yasir Amin

Loading websiteโ€ฆ

More from Muhammad Yasir Amin

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Subscribe on YouTube

How to Add Toastr Notifications in Laravel 13 with Vite and Blade

๐Ÿ› ๏ธ Laravel Tutorials5 min read

How to Add Toastr Notifications in Laravel 13 with Vite and Blade

Muhammad Yasir Amin

Muhammad Yasir Amin

Senior Full Stack Engineerโ€ขNov 7, 2026
How to Add Toastr Notifications in Laravel 13 with Vite and Blade

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

Code
npm install toastr jquery

Step 2: Import and expose Toastr

JavaScript
// 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

Code
npm run dev

Use 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?

JavaScript
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.

JavaScript
{{-- 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.

Shell
{{-- 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?

JavaScript
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.

PHP
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.

JavaScript
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 toastr is undefined when the code runs. The DOMContentLoaded listener 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?

  1. Open the browser console and type toastr.info('Hello'). A toast should appear. If not, check the asset loading.
  2. Submit a valid form and confirm the green success toast shows after the redirect.
  3. Submit an invalid form and confirm each validation message appears as a red toast.
  4. 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.

References

Article Index & Topic Tags
LaravelBladeViteToastr

YouTube Channel

Build Along With Me

Practical walkthroughs on Laravel, React, APIs and deployment workflows.

Muhammad Yasir Amin
Available for Contracts
Author & Solutions Architect

Senior Full Stack Engineer

Independent Senior Full Stack Engineer working on Laravel, React and Next.js applications, APIs and delivery workflows.

Laravel & PHP ApplicationsReact & Next.js InterfacesREST APIs & IntegrationsDatabase Queries & DebuggingDocker Development WorkflowsClear Scope & Handover
Discuss Your Next Step

What Does Your Application Need Next?

Share your current system, the problem you want to solve and what a useful result looks like. We can identify the right starting point and agree on a practical scope.

Technical Audit

Find the Next Useful Fix

Application Development

Scoped, Reviewable Milestones

Ongoing Support

Agreed Capacity and Priorities

Share your goals, current stack and requirements before the call.