Livewire users know the joy: no APIs, no frontend/backend separation, just define state and methods in PHP, and your Blade template becomes a reactive UI. But Livewire’s frontend is Alpine.js β limited in scope. If you want the Vue ecosystem (Vuetify, Pinia, Vue plugins), you have to switch to Inertia.js, which means .vue files, props passing, and client-side state management.
LiVue solves this: it brings Livewire’s server-driven architecture to Vue 3. PHP handles state and logic, Vue 3 handles DOM reactivity, and you write Vue directives directly in Blade templates.
How It Works
LiVue’s request lifecycle has five steps:
- A PHP Component class defines public properties (reactive state) and public methods (callable actions)
- Blade templates mix Blade syntax with Vue directives (
v-click,v-model,v-if,v-for) - Laravel renders complete HTML server-side; state is encrypted and HMAC-signed before embedding in the page
- Vue 3 hydrates the DOM on the client
- User interactions trigger AJAX calls; the server re-renders the component and diffs the DOM
Multiple server calls within the same tick are automatically pooled into a single HTTP request, reducing network round trips.

Installation
| |
Add to resources/js/app.js:
| |
You must add this alias to vite.config.js, otherwise Vue’s template compiler won’t be loaded:
| |
Add @livueStyles and @livueHead to your Blade layout:
| |
If inject_assets is true in the config (default), these directives are optional.
First Component: Counter
| |
This generates two files:
app/LiVue/Counter.php:
| |
resources/views/livue/counter.blade.php:
| |
Render it in any Blade view with @livue('counter') or <livue:counter :count="5" />.
The mental model is almost identical to Livewire: public properties are reactive state, public methods are frontend-callable actions. The difference is that templates use Vue directives instead of Alpine.
Directive Quick Reference
LiVue provides a full set of custom directives covering most interaction scenarios:
v-click: Call Server Methods
| |
Supports .prevent, .stop, .once, .debounce, .throttle modifiers.
v-model: Two-Way Binding
| |
v-submit: Form Submission
| |
v-loading: AJAX Loading State
| |
v-poll: Auto Polling
| |
Automatically pauses when the browser tab is not in the foreground.
v-intersect: Viewport Trigger (Infinite Scroll)
| |
Other directives include v-navigate (SPA navigation), v-dirty (unsaved changes warning), v-offline (offline state), v-sort (drag-and-drop sorting), and v-transition (View Transitions API).
Three Component Formats
Class-Based (Default)
The Counter example above: separate PHP class + Blade template.
Single File Component
PHP logic and template in the same .blade.php file:
| |
Generate with php artisan make:livue MyComponent --single. Best for simple components.
Multi File Component
A folder containing separate PHP, Blade, JS, and CSS files:
| |
CSS is automatically scoped using a data-livue-scope-{name} attribute. Best for complex components needing client-side JS logic.
Page Components: Full-Page Routing
LiVue components can serve as route controllers:
| |
| |
Supports description, robots, og:*, twitter:*, canonical, json-ld and other SEO-related tags.
Lifecycle Hooks
| Hook | Timing |
|---|---|
boot() | Every request (initial + AJAX) |
mount(...$params) | First render, receives props |
hydrate() | AJAX request, after state restoration |
dehydrate() | Before state serialization |
updating($key, $value) | Before property update, can modify value |
updated($key, $value) | After property update |
Property-specific versions are also available, e.g., updatingEmail(), updatedEmail().
| |
PHP Attributes Overview
LiVue makes heavy use of PHP 8 Attributes for configuration:
| |
#[Url] is especially useful β search page queries are reflected in the URL bar, so users can share search result URLs directly.
#[Lazy] combined with placeholder() enables skeleton loading:
| |
Vue Ecosystem Integration
This is LiVue’s biggest advantage over Livewire. Since it runs on Vue 3 under the hood, you can use Vue plugins directly:
| |
Pinia is built-in β just import { defineStore } from 'pinia' and go.
Use @script in Blade templates for client-side logic:
| |
Streaming: Real-Time AI Output
LiVue has built-in streaming support using NDJSON format. This is handy when integrating LLM APIs:
| |
| |
Real-Time Communication: Laravel Echo Integration
| |
Supports public, private, and presence channels.
Comparison with Livewire and Inertia
| LiVue | Livewire | Inertia.js | |
|---|---|---|---|
| Frontend | Vue 3 | Alpine.js | Vue/React/Svelte |
| Templates | Blade + Vue directives | Blade + Alpine | Standalone .vue files |
| Requires API | No | No | No |
| Vue Ecosystem | Full support | No | Full support |
| State Management | Server-driven | Server-driven | Client-side |
| Streaming | Built-in | No | No |
| Islands Architecture | Supported | No | No |
| Tab Sync | Built-in | No | No |
| Maturity | New project | Mature | Mature |
Recommendations:
- Already using Vue ecosystem (Vuetify, Element Plus, etc.) but don’t want full frontend/backend separation β LiVue
- Don’t need Vue, want the simplest reactive UI β Livewire
- Frontend team develops independently, needs full SPA control β Inertia.js
LiVue is currently at v1.4.8 and is still early-stage software. It’s worth trying on new projects, but factor in maturity before committing to it in production.
