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

Livewire Spa Laravel Package

rahmanramsi/livewire-spa

Livewire SPA adds smooth single-page-app style navigation to Laravel Livewire apps, swapping components and updating the URL without full page reloads. Lightweight package for faster, seamless page transitions.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install the package: composer require rahmanramsi/livewire-spa. This is a pre-1.0 package (0.0.x), so pin the exact version in composer.json until you have verified the changelog.
  • Confirm you are on Livewire 3 (the package targets Livewire’s SPA/navigation features). Check composer show livewire/livewire.
  • Publish any config/assets if the package provides them: php artisan vendor:publish --tag=livewire-spa-config (verify the tag in the package README).
  • Add the package’s required scripts/styles to your layout. With the new Full HTML component in 0.0.5, you may instead use the package’s root component that renders the entire HTML document (<!DOCTYPE html>, <head>, <body>). If you use it, include @livewireStyles in the head and @livewireScripts before </body> inside that component.
  • First use case: replace a traditional Blade layout with a single root Livewire component that renders the current page. Create it with php artisan make:livewire SpaApp, then conditionally render page components inside it (@livewire($currentPage)). Use wire:navigate on links (or the package’s navigation helper) so clicks swap page content without a full browser reload.
  • Look first at the package README and the 0.0.5 PR (“Full html component”) to see the exact component name and required markup. The root/full-HTML component is now the primary integration point.

Implementation Patterns

  • Root SPA component: Use the full HTML component as the single root for your app. It owns <html>, <head>, and <body>. Inside the body, render the active page component dynamically. Keep the root component small—only global state, navigation state, and layout concerns.
  • Page resolution: Map the current URL to a Livewire component. A common pattern is a catch-all Laravel route that renders the root component, with the root reading request()->path() and resolving a component class/name. Direct visits and SPA navigations then share the same entry point.
  • Navigation: Use wire:navigate on internal links, or the package’s link helper if provided. For programmatic navigation, call the package’s navigate method or dispatch a Livewire event that the root listens for. Ensure external links and file downloads are excluded from SPA interception.
  • Layouts and nested components: Move head/body markup into the full HTML component. Page components should be fragments (no <html>/<body>), so they can be swapped. If you still need Blade layouts for non-SPA pages, keep those routes outside the root component.
  • State sharing: Keep cross-page state (auth user, cart count, theme) in the root component and pass it to page components as props. Use Livewire events ($dispatch, #[On]) for page-to-root or page-to-page communication.
  • Asset handling: Scripts and styles added by page components will not re-execute on SPA navigation. Load shared assets once in the full HTML component. For page-specific JS, use @script/@assets in Livewire 3 or dispatch a browser event after navigation (livewire:navigated) and initialize there.
  • Integration with existing routes: Keep Laravel routes for deep links and fallbacks. The root component should hydrate its state from the request so a direct visit to /users/1 renders the same page as an in-app navigation. Use wire:key on the dynamic page component to force a clean remount when the page changes.
  • Loading and transitions: Use wire:loading indicators around the page container. For smoother transitions, add CSS with wire:navigate’s progress bar or the package’s built-in progress if available. Test browser back/forward: the root must respond to history changes.

Gotchas and Tips

  • Pre-1.0 instability: 0.0.5 adds a full HTML component, which is a meaningful architectural feature. Expect API changes in 0.0.x. Pin the version and read the diff before upgrading; the full HTML component may change how layouts are expected to be structured.
  • Full HTML component conflicts: Do not use @extends/@section Blade layouts together with the full HTML component for the same route. The component replaces the layout. If you see duplicated <html> tags or missing Livewire scripts, you likely have both a Blade layout and the full HTML component rendering.
  • Missing @livewireStyles/@livewireScripts: In a full HTML component, these are easy to forget. Without them, Livewire requests fail and wire:navigate may not work. Put @livewireStyles in <head> and @livewireScripts before </body>.
  • Scripts not re-running: SPA navigation does not re-execute <script> tags in swapped content. Move initialization to Livewire’s @script or listen for livewire:navigated. Alpine.js components may need x-init or a re-init hook after navigation.
  • Deep-link hydration: Test direct URL access, refresh, and back/forward. If the root component always starts at the home page, deep links will break. Resolve the initial page from the request path and pass it into the root’s mount().
  • Duplicate Livewire instances: If you accidentally include the scripts twice (e.g., once in a Blade layout and once in the full HTML component), navigation can behave unpredictably. Inspect the page source and network requests.
  • Debugging navigation failures: Open the browser console and network tab. A failed SPA navigation often shows a Livewire update request returning HTML instead of JSON, or a JS error from a missing asset. Check that the root component’s response is a Livewire payload.
  • Authorization: SPA navigation only changes the client experience. Keep authorization checks in each page component and in Laravel policies. Hiding a link is not access control.
  • Extension points: Publish the config (if available) to customize the navigation selector, progress bar, or asset injection. Use Livewire lifecycle events (livewire:navigating, livewire:navigated) to hook analytics, scroll restoration, or third-party widget initialization.
  • Performance: Keep the root component lean. Lazy-load heavy page components and avoid loading all page data in the root. Use wire:key to avoid stale child state when switching between pages.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource