live_vue: putting Vue components inside Phoenix LiveView with shared state
End-to-end reactivity for Phoenix LiveView and Vue
At a glance
- What is it?
- live_vue is an Elixir library that lets a Phoenix LiveView render Vue components and keep both sides in sync, with server-side rendering, lazy-loaded components, props diffing over the WebSocket, and composables for uploads and forms. It started as a fork of LiveSvelte and is tied to Phoenix 1.8 and above for its installer.
- Who is it for?
- live_vue fits a Phoenix team that has decided to use LiveView for the server side and Vue for the complex parts of the client, and who can accept a build step and a second framework in the same application. It is the wrong choice if you want one framework, since the point of the project is running two at once, and it is the wrong choice if you are on Phoenix below 1.8, because the Igniter installer only works for 1.8 and later.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 32 days ago.
- What is it written in?
- Mainly Elixir, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is that LiveView hooks get ugly fast
The Why section of the README states the motivation plainly. Phoenix LiveView makes it possible to create rich, interactive web apps without writing JavaScript, but once you need to do anything even slightly complex on the client side, you end up writing lots of imperative, hard-to-maintain hooks. LiveVue answers that by allowing hybrid apps where part of the session state is on the server and part on the client. The list of reasons to want it is honest rather than technical. Your hooks are starting to look like jQuery. You have a complex local state. You would like to use a massive Vue ecosystem. You want transitions, graphs, and similar things. Or you simply like Vue. That last entry is the one that tells you the audience, which is an F#-adjacent Elixir developer who has used Phoenix and looked at the Vue ecosystem and decided the combination was worth it.
A Vue component and a LiveView talk through attributes, not through a wrapper
The integration model is the part worth understanding before you install anything. The README says that after installation you can use Vue components in the same way as functional LiveView components, that you can handle Vue events with JS hooks, and that all the `phx-click` and `phx-change` attributes work inside Vue components as well. The example shows a single-file Vue component that declares props coming from LiveView and keeps its own local state in a ref:
<script setup lang="ts">
import {ref} from "vue"
// props are passed from LiveView
const props = defineProps<{count: number}>()
// local state
const diff = ref(1)
</script>The LiveView side then renders it with a `.vue` tag and a `v-component` attribute:
defmodule MyAppWeb.CounterLive do
use MyAppWeb, :live_view
def render(assigns) do
~H"""
<.vue count={@count} v-component="Counter" />
"""
endThe LiveView attribute names carry through, so a click on the Vue side button becomes a LiveView event, and the README notes that in the default `~H` setup from `mix live_vue.install`, LiveVue component tags get `v-socket` injected automatically, which is the wiring that lets the client talk back.
Props diffing is what keeps the WebSocket quiet
The feature list names efficient props diffing, with only changed data sent over the WebSocket, and the server-side rendered Vue support alongside lazy-loading of Vue components. Those three belong together. If the whole prop set crossed the socket on every state change, a Vue component inside a LiveView would defeat much of the reason to use LiveView, where the point is that the server pushes a diff of what changed. Props diffing keeps the payload proportional to the change rather than to the size of the model. Server-side rendering matters for the same reason from the other direction, since a component that renders on the server does not have to wait for a JavaScript bundle before appearing. The `assets/` directory in the repository holds the TypeScript side of this, and the package manifest points its `main` and `types` entries at `assets/index.ts`, with separate export paths for `./vitePlugin` and `./server`.
The composables cover the two features LiveView handles awkwardly
Two composables are called out in the feature list because they solve the problems most likely to appear when a Vue component is dropped into a LiveView. The first is `useLiveUpload()`, a file upload composable for Vue integration with LiveView uploads. The second is `useLiveForm()`, which handles forms with server-side validation via Ecto changesets. The form one is the more interesting, because server-side validation is a genuinely LiveView idea. A changeset is the Elixir structure that describes what a valid record looks like, and a Vue form that defers to it can show server-side errors without duplicating the rules in JavaScript. There is also a `~VUE` sigil described as an alternative to the LiveView DSL, with VS Code syntax highlighting available through a separate extension, and support for Phoenix Streams with efficient patches, Tailwind, and slot interoperability.
Igniter does the install, but only for Phoenix 1.8 and newer
Installation is automated through the Igniter installer, and the README is explicit that it works only for Phoenix 1.8 and later. For a new project:
mix archive.install hex igniter_new
mix igniter.new my_app --with phx.new --install live_vueFor an existing project on Phoenix 1.8 or newer:
mix igniter.install live_vueThe Igniter installer is what makes the one-line install claim credible, because it does more than add a dependency. It configures `package.json` to point at the local copy of the library, and it wires up the Vite plugin, so the alternative to the installer is a manual list of things to get right. The version floor is a real constraint rather than a formality, since Igniter is itself a Phoenix 1.8 era tool. The detailed instructions live in the installation guide in the `guides/` directory, and the same directory carries a getting started guide, a forms guide, a configuration guide covering SSR, a component reference, a client-side API guide, and an architecture guide described as covering how LiveVue works under the hood.
A fork of LiveSvelte, with Vite instead of ESbuild
The project states that it is heavily inspired by LiveSvelte, that both projects try to solve the same problem, and that LiveVue was started as a fork of LiveSvelte with adjusted ESbuild settings, evolving to use Vite and a slightly different syntax. The author adds that more options are always better and that since he loves Vue and its ecosystem, he decided to give it a go. The comparison guide and the FAQ section both cover how LiveVue compares to LiveSvelte, which is the fair way to evaluate either project. The technical consequence of the fork is visible in the tooling. The `package.json` lists Vite with the Vue plugin, Vitest for unit tests with a UI mode and a bench mode, Playwright for end-to-end tests with install, server, build, test, headed, and debug scripts, and Vue 3 with a peer dependency declared as `^3.4.0`. The e2e build script compiles the test app twice, once for the browser and once for SSR, which is the shape you would expect from a project that supports server-side rendering of Vue.
Working on the library itself
The development section is brief. You need Node.js installed, you clone the repo, and you run `mix setup`. The README notes that no build step is required for the library itself, because Vite handles TypeScript transpilation when consumers bundle their app, which is a clean separation: the Elixir side is a normal Hex package and the TypeScript side is shipped as source. The end-to-end tests run with `npm run e2e:test`. To test local changes in a separate Phoenix project, you use a path dependency in that project's `mix.exs`:
{:live_vue, path: "../live_vue"}Then you run `mix deps.get && npm install`, and the installer has already configured `package.json` to use `file:./deps/live_vue` so both Elixir and npm point at your local copy. The README adds the detail that Elixir changes are reflected immediately, while for TypeScript changes you run `npm install` again to pick them up. Releasing is done with `easy_publish`, which means updating `CHANGELOG.md` and checking the version in both `mix.exs` and `package.json`, then running `mix release.minor --dry-run` before `mix release.min`.
Editorial conclusion
live_vue fits a Phoenix team that has decided to use LiveView for the server side and Vue for the complex parts of the client, and who can accept a build step and a second framework in the same application. It is the wrong choice if you want one framework, since the point of the project is running two at once, and it is the wrong choice if you are on Phoenix below 1.8, because the Igniter installer only works for 1.8 and later. Before you commit, read the comparison guide against LiveSvelte, since the project is a fork of it, and check the `~VUE` sigil support in your editor, where a separate VS Code extension provides the syntax highlighting.
Frequently asked questions
How do I install live_vue in a Phoenix project?
For a new project, install the Igniter archive and generate the app with `mix igniter.new my_app --with phx.new --install live_vue`. For an existing project, run `mix igniter.install live_vue`. The Igniter installer only works for Phoenix 1.8 and later projects.
How do LiveView and Vue share state in live_vue?
The LiveView renders a `.vue` tag with a `v-component` attribute and passes data as props, and the Vue component declares them with `defineProps`. The `phx-click` and `phx-change` attributes work inside Vue components, and in the default `~H` setup from `mix live_vue.install` the component tags get `v-socket` injected automatically.
Does live_vue support server-side rendering and lazy loading?
Yes. The feature list names server-side rendered Vue and lazy-loading of Vue components, and the package exports a `./server` entry point alongside the main entry and a separate `./vitePlugin` export. The e2e build script compiles the test application twice, once for the browser and once with an SSR build.
How does live_vue handle forms with server-side validation?
Through the `useLiveForm()` composable, which provides comprehensive form handling with server-side validation via Ecto changesets, so the validation rules stay on the server rather than being duplicated in the client.
How does live_vue relate to LiveSvelte?
The project states it is heavily inspired by LiveSvelte and that both solve the same problem. LiveVue was started as a fork of LiveSvelte with adjusted ESbuild settings and evolved to use Vite with a slightly different syntax, and the README links both a FAQ entry and a comparison guide covering the differences.
What licence is live_vue released under?
MIT, with the LICENSE.md file at the repository root and the package manifest recording the same licence. The current release is v1.2.3 from 2026-08-24, after v1.2.2 in July 2026 and v1.2.1 in May 2026.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/valian-live-vue)Was this useful?