Library / SDK
usernotnull/tall-toasts avatar
usernotnull/tall-toasts

tall-toasts: one Toast global for Laravel, Livewire, and Alpine

A Toast notification library for the Laravel TALL stack. You can push notifications from the backend or frontend to render customizable toasts with almost zero footprint on the published CSS/JS 🔥🚀

572 stars39 forksPHPMIT

At a glance

What is it?
tall-toasts is a MIT licensed notification library for the TALL stack that renders a toast from PHP or from Alpine, with a JavaScript payload the README claims is under one kilobyte. It earns its place in a Tailwind project that already runs Livewire, and it will not fit a project that does not.
Who is it for?
Adopt tall-toasts if your application already runs Laravel with Livewire 2 or 3, Alpine 3, and Tailwind 2 or 3, and you are willing to add the package paths to your tailwind.config.js content array. Skip it if your frontend is not Alpine based, or if you need HTML in a toast, since the default path sanitizes the message and only the explicit doNotSanitize() call passes markup through.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A single global, callable from either side of the TALL stack

The design idea behind tall-toasts is small enough to state in one line: there is one toast object, and you can reach it from PHP or from the browser. The README describes it as a global that can be called from the backend, through controllers, Blade views, or components, or from the frontend, through JavaScript and Alpine components.

The naming carries the distinction. On the server side the helper is toast(). On the client side it is Toast. That split is deliberate and it is the reason you can recognise at a glance whether a message is being queued for a page render or dispatched immediately in the browser.

The library targets the TALL stack specifically: Laravel, TailwindCSS, Livewire, and AlpineJS. It is not framework agnostic, and it is not a design system. It is a delivery mechanism for short messages that the user should see once, plus a Blade view you can override. For teams already on that stack, that is exactly the gap it fills, since a toast that requires a separate JavaScript library tends to bring its own CSS and its own rendering conventions along with it.

The frontend API is a set of severity methods on Toast

From Alpine components and plain JavaScript, the entry point is a severity method plus a message, with an optional title. The README shows the full family, and every method accepts the same three argument shape.

js
Toast.info('Notification from the front-end...', 'The Title');

Toast.success('A toast without a title also works');

Toast.warning('Watch out!');

Toast.danger('I warned you!', 'Yikes');

Toast.debug('I will NOT show in production! Locally, I will also log in console...', 'A Debug Message');

A third argument overrides the display time. Passing 3000 shows the toast for three seconds, and passing 0 keeps it on screen until it is removed by hand.

js
Toast.success('This toast will display only for 3 seconds', 'The Title', 3000);

Toast.success('This toast will display until you remove it manually', 'The Title', 0);

One detail deserves attention. The debug level is explicitly documented as not showing in production, and as logging to the console locally instead. That means the severity map doubles as an environment switch, which is convenient until you want a debug entry to reach a staging environment, since the README does not describe a configuration key for forcing debug toasts on.

Server side, a toast is pushed or deferred to the next page

On the PHP side the same message becomes a fluent chain terminated by push() or pushOnNextPage(). The two differ in when the toast appears, and the difference is the reason the backend API is not a trivial mirror of the frontend one.

php
toast()
    ->info('I will appear only on the next page!')
    ->pushOnNextPage();

toast()
    ->info('Notification from the backend...', 'The Title')
    ->push();

A plain push() dispatches the toast to the browser as the current response is rendered. pushOnNextPage() holds it until the following request, which is what you want for a validation failure or a form rejection where the message belongs to the next screen rather than the current one.

The same chain also handles timing and content. A duration() call sets how long the message stays visible, and sticky() keeps it up until it is removed manually.

php
toast()
    ->success('This toast will display only for 3 seconds')
    ->duration(3000)
    ->push();

toast()
    ->success('This toast will display until you remove it manually')
    ->sticky()
    ->push();

The README also shows that a debug message can carry an object rather than a string, dumping a model with only selected attributes, which is a quick way to see what a factory just produced without opening a debugger.

Composer install plus a Tailwind JIT content change

Installation is a single Composer command, since the package is a standard Composer dependency.

bash
composer require usernotnull/tall-toasts

The requirement table is generous by design. PHP is listed at ^8.0, Laravel from ^8.0 through ^12.0, TailwindCSS at ^2.0 or ^3.0, Livewire at ^2.0 or ^3.0 as of the v2 line, and AlpineJS at ^3.0. Older documentation for the v1 line is kept in a separate README-v1.md file in the repository.

After installing, the stylesheet has to be rebuilt the way a Tailwind project normally does it.

bash
npm run dev

The part people miss is the Tailwind JIT configuration. If you run Just-in-Time mode, the package classes live in vendor and will not be found by the default content scan, so the config file has to point at them.

js
// use `purge` instead of `content` if using TailwindCSS v2.x
content: [
    './vendor/usernotnull/tall-toasts/config/**/*.php',
    './vendor/usernotnull/tall-toasts/resources/views/**/*.blade.php',
    // etc...
]

Without those globs the toast markup renders unstyled, and the README notes that changing the config means re-running the npm command. The same requirement applies to a Tailwind 2 project under the old `purge` key.

Alpine registration lives in your app.js entry point

The frontend global has to be wired into Alpine before any component can call Toast. The README instructs you to add the Toast component in your app.js, and its example begins by importing the Alpine and Livewire runtime from the vendor path.

js
import {Alpine, Livewire} from '../../vendor/livewire/livewire/dist/livewire.esm';

The README's example is cut off at that import, so it does not show the remaining lines that bind the Toast component to Alpine. What it does establish is the shape of the setup: the Alpine and Livewire ESM bundle is imported from the vendor directory, and the Toast component follows it in the same file.

This is worth flagging because it is a build step you own rather than something the package configures for you. The repository ships a dist/js/tall-toasts.js file that the README links to a size badge, and the root package.json defines a rollup based build with npx rollup -c and a watch mode. But the consumer side still expects your own app.js to bring the pieces together.

The payoff for that wiring is the size claim. The README states the JavaScript footprint is less than one kilobyte, brotli compressed, and attributes it to the frontend being a pure AlpineJS component with no external JavaScript libraries, while the backend handles most of the logic.

Tailwind purging is why the CSS cost stays near zero

The CSS argument is the more interesting half of the size story, and it depends on how the package stores its markup. The README says the styles come from default TailwindCSS classes, and that even if you override the default views, Tailwind's purging keeps only the styles and classes you have actually used. The claim is that it will not bloat your generated CSS or add extra files to download.

That is a structural property rather than a promise about a number, and it holds only while you stay inside the model: utility classes in Blade views that Tailwind can see. Two things break it. The first is a content configuration that does not scan the package views, which is the JIT case above. The second is any custom class you write that Tailwind cannot see, such as a class defined in a plain CSS file or one applied from a string built at runtime, since those entries will be purged away.

The view is also the extension point. The README says you have control over the view because you are overriding the Blade view, which lets you shape the markup with TailwindCSS classes and avoids fighting custom CSS overrides. The repository layout backs that up with a resources directory, a config directory, and a src directory alongside bootstrap and dist.

HTML in a message is sanitized unless you opt out

The backend API allows a message to carry markup, and the default is to strip it. The README demonstrates the escape with a danger toast containing a line break, an italic tag, and a styled span, and it does so by calling doNotSanitize() before push().

php
toast()
    ->danger('I warned you!', 'Yikes')
    ->push();

The sanitized path is the safe default, and it matters because a toast message is often built from user input or from a model field. A message containing something like a pasted product name would otherwise be able to inject markup into the page. Turning sanitization off is therefore a deliberate act, and the README does not describe a whitelist or a config switch for partial trust. There is a single global on/off decision, and the method name says plainly that you are taking responsibility for the string.

This is the main case where tall-toasts is the wrong tool. If you need rich, trusted HTML in a notification, the sanitization default will get in the way, and disabling it globally for one message means every other message in the same session also goes unfiltered.

MIT licence, published releases, and a fresh push

The project is MIT licensed, which is the permissive end of the scale and carries no source disclosure requirement for applications that use it. Nothing in the repository listing suggests a separate licence for the styles or the sample images.

Release history is published as GitHub tags rather than as GitHub releases. The tagged versions are v2.0.1 on 2023-09-20, v2.1.0 on 2024-03-21, and v2.2.0 on 2025-03-05. The last push to the default branch was on 2026-10-19, so work is landing on main after the most recent tag. If you pin a version in your composer.json you get the 2025-03-05 state of the code rather than the current main branch.

The repository is unusually well equipped for a package this size. Alongside the source there are quality tools configured in the root: phpunit.xml.dist, phpstan.neon.dist, psalm.xml.dist, phpcs.xml.dist, phpmd-ruleset.xml.dist, and .php-cs-fixer.dist.php. A CODE_OF_CONDUCT.md, a CHANGELOG.md, and an .editorconfig are present too, and the build is set up with rollup, babel, and eslint.

One caveat for a package that ships a prebuilt asset: the dist directory is committed to the repository, so the JavaScript that your browser loads is whatever was built and committed, not necessarily the result of running the build on your machine. The build scripts exist for maintainers, not for consumers who pull a tagged release.

Editorial conclusion

Adopt tall-toasts if your application already runs Laravel with Livewire 2 or 3, Alpine 3, and Tailwind 2 or 3, and you are willing to add the package paths to your tailwind.config.js content array. Skip it if your frontend is not Alpine based, or if you need HTML in a toast, since the default path sanitizes the message and only the explicit doNotSanitize() call passes markup through. Before installing, confirm the composer require step, then check that the Tailwind build still contains the toast classes after you add the vendor paths, and note that the latest tagged release is v2.2.0 while the last push was on 2026-10-19.

Frequently asked questions

How do I install tall-toasts in a Laravel app?

The package is installed with Composer using composer require usernotnull/tall-toasts. It needs PHP ^8.0, Laravel ^8.0 through ^12.0, TailwindCSS ^2.0 or ^3.0, Livewire ^2.0 or ^3.0, and AlpineJS ^3.0.

Why are my toasts unstyled after installing tall-toasts?

If you use Tailwind Just-in-Time mode, the package classes are inside vendor and must be added to your tailwind.config.js content array, pointing at './vendor/usernotnull/tall-toasts/config/**/*.php' and './vendor/usernotnull/tall-toasts/resources/views/**/*.blade.php', then rebuild with npm run dev. With Tailwind v2 use the purge key instead of content.

Can a tall-toasts message contain HTML?

Messages are sanitized by default, so markup is stripped. The README shows that the doNotSanitize() call before push() allows HTML through, and it applies to that message chain rather than to a single field within it.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. usernotnull/tall-toasts on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/usernotnull-tall-toasts.svg)](https://hysenlabs.com/projects/usernotnull-tall-toasts)

Was this useful?