edulazaro/wiretoast
Wiretoast is a framework-agnostic toast notification system for Laravel, Livewire and Alpine, with pure CSS themes, five semantic types, seven stacked positions, dark mode, progress bars, group mode, and zero JavaScript dependencies.
Architecture fit. Wiretoast is a thin presentation layer, not a subsystem. It ships as a Composer package with a single anonymous Blade component (<x-wiretoast />), a pure-CSS stylesheet, and a small vanilla-JS listener bound to the notify browser event. There is no service provider surface to configure, no queue, no database, no persistence, and no server-side rendering path — the only integration point is a browser event plus an optional Livewire $this->notify() helper. For a Laravel 11+/Livewire 3 application using Blade layouts, the architectural impedance is effectively zero. It also does not compete with a UI framework: themes are CSS variables, so it drops into Tailwind, Bootstrap, or hand-rolled layouts without a build-tool decision. That is the strongest part of the package's story.
Integration feasibility. Low. composer require plus one component tag in the layout, plus a two-line import in app.css/app.js for the Vite path. A developer can have a working toast in under an hour. The decision that actually matters — Vite bundling versus vendor:publish — should be made up front and documented, because the publish path copies assets into public/ that silently do not update on composer update.
Technical risk. The engineering risk is low; the supply-chain and longevity risk is the dominant concern:
| Risk | Severity | Notes |
|---|---|---|
| Bus factor = 1 | High | Single maintainer, 2 stars, 0 dependents. No evidence of a contributor base or governance. |
| Adoption signal | Medium | Zero dependents means no field-tested failure data beyond the author's own use. |
| Version constraint breadth | Medium | laravel >=11.0 (any future version included) is an unbounded claim Laravel 12/13 compatibility has not been proven against. |
| Accessibility unaddressed | High | README documents no aria-live, role="status", focus handling, or prefers-reduced-motion behaviour. Motion tokens exist (--wt-duration, --wt-easing) but reduced-motion support is not stated. For most teams this is a release gate, not a nice-to-have. |
| Test coverage undisclosed | Medium | Maturity signals list only README and releases; no CI badge or test suite referenced. |
| Release metadata | Low | Reported last release date (2026-07-31) warrants verification before it enters a dependency policy. |
Key questions for the maintainer / team.
$this->notify() dispatch a testable event, so we can assert at the event boundary rather than the DOM?Stack fit. Best fit is Laravel 11+ with Vite (the default), Livewire 3 for server-initiated toasts, and Alpine for client-only interactions. Fit degrades only at the edges: non-Vite or legacy build pipelines push you onto the publish path, and non-Livewire apps lose the PHP helper and must dispatch the browser event themselves.
Migration path. Treat this as a replacement for ad-hoc session()->flash() banners, not a redesign. Highest-value first target is a single Livewire action result — a save()/submit() method that currently flashes a banner. That proves the event wiring, the layout mount point, and the theme in one afternoon. Because the public API (notify(input, type, options)) is identical across PHP, Alpine, and JS, we should standardise internally rather than calling the package directly from forty call sites: one JS wrapper in app.js that pins default position/timeout, and one server-side trait (notifyError($e)) so copy and defaults live in one place. That wrapper is also the swap point if we ever replace the library — it converts a package dependency into a one-file dependency.
Compatibility. Coexists cleanly with Tailwind dark mode (the .dark ancestor class is honoured) and with any CSS framework, since themes are variable sets. The real compatibility hazards are internal, not external: (a) double-loading — importing via Vite and passing :assets="true" registers the listener twice and produces duplicated or instantly-vanishing toasts; (b) z-index and stacking-context collisions with existing modals and drawers; (c) CSP — the documented redirect-plus-toast pattern uses an inline <script>, which will fail under a strict script-src policy and needs a nonce or a data-attribute alternative.
Sequencing.
<x-wiretoast /> once in the base layout outside any Livewire component. Convert one success and one error toast. Verify dark mode and one custom theme via attribute-scoped variables (never by editing vendored CSS).assets= in layouts.timeout => 0 for errors the user must read. Explicitly forbid notify() inside render().Maintenance. Low ongoing cost, and — critically — low lock-in cost. The surface is a stylesheet and a small JS file; if the package is abandoned, forking or inlining it is a day of work, and the MIT licence permits it. The one maintenance obligation we must own is the publish-path staleness trap: if we choose vendor:publish, upgrades will not propagate and we will silently diverge from upstream. Recommendation: mandate the Vite path so composer update is the entire upgrade procedure. Budget roughly half a day per Laravel major version to confirm the unbounded version constraint still holds.
Support. No vendor SLA, no commercial backing, single-maintainer community support. Our internal answer must be "fork it," which means the owning team should be named before adoption, not after. Escalation is effectively via GitHub issues on the author's schedule.
Scaling. Negligible infrastructure impact — toasts render client-side, so cost scales with page views, not server load. The scaling concerns are UX-level: unbounded toast stacking on rapid-fire events (group mode is the mitigation), and timeout => 0 toasts accumulating into an unclearable wall if used indiscriminately. Bundle weight is small and, on the Vite path, amortised into the existing cached request. Enforce a convention: group mode for loops and bulk imports, persistent toasts only for blocking errors.
Failure modes to instrument for.
| Failure | Symptom | Detection / Mitigation |
|---|---|---|
| Double-load | Toasts duplicate or flash and vanish | Grep layouts for assets=; code review checklist |
| Stale published assets | Theme fixes never arrive after upgrade | Avoid publish path; pin and document if unavoidable |
| Redirect swallows toast | Success message never appears after POST | Session-flash bridge documented in the layout |
notify() in render() |
Render-loop toast flood | Code review; treat as a defect class |
| Queue/async silence | User waits with no feedback, then no toast | Pair with persistent inline state; poll then notify |
| CSP blocks inline script | Redirect toast silently missing | Nonce the bridge or use a data-attribute contract |
Ramp-up. Hours, not days. The README's reference table is four option keys deep — one read and a developer is productive. The live preview demo is the right place to make the theme decision, since theme choice is a design call, not a documentation call. The genuinely non-obvious knowledge (double-load risk, redirect behaviour, group mode) is a one-page team convention, not training.
Assessment and recommendation. Adopt on a pilot basis as a reversible, presentation-only convenience, contingent on clearing the accessibility question and confirming the event-dispatch surface is testable. At 2 stars and 0 dependents with a single maintainer, this is not a dependency to build a product strategy on — but the blast radius is small enough that the risk is bounded and the exit cost is near zero. Gate adoption on: (1) accessibility verification, (2) team assignment of fork ownership, (3) Vite-only asset loading written into the style guide.
How can I help you explore Laravel packages today?