Getting started
So I love working with Livewire for backend-heavy stuff and rapid prototyping, but sometimes, let's be honest — there are things Vue does better. Like if you need a super reactive or animated component.
In this tutorial I’ll show you how I added Vue to a Laravel project that uses Livewire, without breaking anything 🚀
First, install Laravel with Livewire
If you don’t have it already, let’s start fresh:
laravel new livewire-vue-demo
cd livewire-vue-demo
composer require livewire/livewire
php artisan livewire:publish
Let’s add a simple Livewire component to make sure it's working:
php artisan make:livewire Counter
Now inside resources/views/livewire/counter.blade.php
:
<div>
<button wire:click="increment">+</button>
<h1>{{ $count }}</h1>
</div>
And in the class:
public $count = 0;
public function increment()
{
$this->count++;
}
Now Livewire is working. Time to Vue it up.
Add Vue to the mix
Install Vue (we're gonna use it via Vite):
npm install vue
Now go to your resources/js/app.js
file and add:
import { createApp } from 'vue'
import Example from './components/Example.vue'
const app = createApp({})
app.component('example', Example)
app.mount('#vue-root')
Create your Vue component
Inside resources/js/components
, create a new file: Example.vue
<template>
<div>
<h2>This is Vue inside Livewire</h2>
<input v-model="message" placeholder="Type something..." />
<p>You typed: {{ message }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('')
</script>
Add it to your Blade view
Now here’s the trick — we want to render Vue inside a Livewire view, but they shouldn’t conflict. Vue needs its own root element.
So inside counter.blade.php
(or wherever):
<div>
<button wire:click="increment">+</button>
<h1>{{ $count }}</h1>
<div id="vue-root">
<example></example>
</div>
</div>
Make sure this #vue-root
is outside of any Livewire-controlled part you want to update reactively, or Livewire might re-render and destroy your Vue app 😅
Compile and go
Run the build:
npm run dev
Visit the page and you should see your Livewire counter and Vue component living in peace together 🕊️
Real-world tip
If you want to pass data from Laravel/Livewire to Vue, you can do it like this:
<div id="vue-root" data-name="{{ $user->name }}">
<example :name="document.getElementById('vue-root').dataset.name"></example>
</div>
Or use Alpine to pass props directly.
TL;DR
- Livewire and Vue can work together if you separate their concerns.
- Mount Vue manually with
createApp()
on a safe DOM ID. - Don't put Vue inside Livewire dynamic parts unless you're OK with re-renders.
- Great for charts, inputs, animations, modals... anything dynamic.