Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Splade Laravel Package

tomatophp/splade

Splade brings a single-page-app feel to Laravel Blade without writing JavaScript, pairing Blade templates with Vue 3 and Tailwind. This TomatoPHP package provides the Splade integration, letting you build reactive forms, tables, modals and slideovers using simple Blade components.

View on GitHub
Deep Wiki
Context7

Getting Started

Splade is a pre-release (v0.0.1) Laravel package that layers SPA-style navigation and reactive Blade components on top of a normal server-rendered app. The published changelog for this release is only a link to the commit history, so treat v0.0.1 as an initial, unproven baseline — expect the API surface to move before v1.0.

Minimal setup:

composer require tomatophp/splade
php artisan vendor:publish --provider="Splade\ServiceProvider"   # or the splade:install command, if present
php artisan splade:install        # if the package ships an installer; otherwise publish config/assets manually

Then three wiring steps, in this order:

  1. Middleware — add the package's request handler to the web group (or to specific routes) so responses are turned into Splade JSON payloads when the client asks for them. Without it, everything still works but you get full page reloads and no SPA behaviour — the classic "why isn't it fast?" symptom.
  2. Blade directive — place @splade (or the documented equivalent) inside <head> of your layout. This emits the JS runtime, meta tags and the boot payload. Missing it is the second most common setup failure.
  3. Routes — register the package's internal endpoints (the ones handling partial reloads/defer requests) exactly as documented in the install stub.

Look first at config/splade.php after publishing: it controls the middleware list, Blade component templates (form/table/etc.), and SSR-related toggles. That file is the map of what you can override.

First use case: pick one read-only index page (e.g. /users) and convert just that one. Wrap the table in the package's table component and confirm that clicking a pagination link updates the DOM without a full reload (watch the Network tab for an X-Splade-style request header and a JSON body). Do this before touching forms — it isolates routing/middleware problems from validation problems.

Implementation Patterns

Progressive enhancement is the whole point. Keep controllers returning normal Blade views with normal Eloquent data. Splade should be able to fall back to a full page load at any time; if a page only works via the JS runtime, you've over-coupled it. This makes the package safe to adopt page-by-page rather than as a rewrite.

Forms. The form component takes a default/model binding and posts via standard Laravel routes:

<x-splade-form :default="$user" action="{{ route('users.update', $user) }}" method="put">
    <x-splade-input name="name" label="Name" />
    <x-splade-input name="email" type="email" label="Email" />
    <x-splade-submit />
</x-splade-form>

Server side stays idiomatic: FormRequest + $request->validated() + redirect()->route(...)->with('success', '...'). Validation errors and flash messages are transported by the package; you don't hand-roll JSON responses. Prefer Splade::flash() / Splade::toast() helpers where they exist over inline session manipulation, so the payload shape stays consistent.

Modals as a routing pattern. The highest-leverage pattern day-to-day: a modal is just a normal route whose view contains the modal component. Link to it with the modal-enabled link component and you get deep-linkable modals for free. Build create/edit flows this way and your controllers stay identical to the non-SPA version.

Tables. Wrap an index view in the table component and expose the paginator as a public property on the view/component. Sorting, search and pagination are then handled by the client without extra controller code — but make sure your query is filterable server-side too, since a hard refresh must produce the same result set.

Lazy/deferred regions. For expensive widgets (dashboards, counts, reports), use the defer component with a named route so the shell renders instantly and the heavy query runs in a second request. This is the cheapest perceived-performance win in the package and doesn't require changing the underlying controller much.

Cross-component communication. Use the event helpers rather than reaching into the DOM. Emit from the server on redirect, listen on the client. Avoid jQuery-style selectors; they defeat the reactivity model and break on partial reloads.

JS escape hatch. When you need custom behaviour, the package exposes a useForm-style composable for Alpine-style components. Keep bespoke JS in a small number of files and let Blade components do the rest — mixing both heavily in one view is where maintainability dies.

Testing. Existing feature tests keep passing because full page loads still work. Add assertions on the partial-response JSON for the two or three critical flows (login, a form submit with validation failure, a deferred region) so middleware regressions are caught.

Gotchas and Tips

  • v0.0.1 is a moving target. The release notes are empty beyond the changelog link, so there is no documented BC policy. Pin the exact version in composer.json ("tomatophp/splade": "0.0.1"), read the commit log before every bump, and keep the adoption surface small (a handful of pages) until the API stabilises.
  • It is a fork/lineage of an earlier Splade implementation. Namespaces, publish tags and component prefixes may not match tutorials you find online for the original package. Always confirm class names and tag names against vendor/tomatophp/splade/ rather than blog posts.
  • Middleware order matters. If the Splade handler runs before StartSession/ShareErrorsFromSession, validation errors and flash messages silently vanish on partial requests. Keep it at the end of the web group.
  • Config and view caches. After publishing config or overriding Blade templates, run php artisan optimize:clear. Stale bootstrap/cache/config.php is the usual cause of "my config change does nothing".
  • Debugging partial requests. A 419 means CSRF is missing from the emitted payload — usually a layout that doesn't include the token meta tag, or a custom fetch that bypasses the runtime. A 200 with an HTML body instead of JSON means the request-header check failed (middleware missing or the link was a plain <a>).
  • APP_DEBUG=true responses. Error pages come back as full HTML and can confuse the client-side router. Test failures with debug off to see the real UX.
  • Asset pipeline. Make sure the runtime is included through your Vite/Mix build, not a stray CDN tag, or you'll get duplicate Alpine instances ("multiple instances of Alpine detected") and components that initialise twice.
  • Extension points worth knowing: the published Blade templates (override per component rather than editing vendor files), the config's middleware array, and the Splade facade, which is macroable — register project-specific helpers there instead of scattering session()->flash calls.
  • Escape valve. Because every page is still a real route returning a real view, you can remove the middleware and be back on a conventional app in minutes. Keep that property intact: no controller should return Splade-only JSON by hand.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource