Phoenix LiveView + Vue.js

The missing Vue bridge for LiveView

When LiveView hooks get messy, reach for Vue. Full reactivity. No API layer. One install command.

mix igniter.install live_vue
Phoenix 1.8+ · Starting fresh?
Why LiveVue

Everything LiveView does,
Vue can too.

Streams, forms with Ecto validation, file uploads, server events — all work through Vue-native composables. You're not giving up LiveView features. You're extending them.

End-to-End Reactivity

LiveView assigns become Vue props automatically. When server state changes, Vue re-renders. When Vue emits events, LiveView handles them. The loop is complete.

Vue-native composables for LiveView features

useLiveVue()

pushEvent, handleEvent & more

useLiveForm()

Ecto changeset validation

useLiveUpload()

LiveView file uploads

useLiveEvent()

Server → client events

Plus phx-click, phx-change, and all Phoenix bindings work inside Vue templates. $live is available in templates for quick access.

Server-Side Rendered

Vue components render on first paint. No loading flash. Full SEO.

Efficient Updates

JSON patches over WebSocket. Only changed props are sent.

Vite-Powered DX

Instant HMR, TypeScript out of the box. The legendary Vite experience, for free.

One-Line Install

Igniter handles the setup. TypeScript, Vite, SSR — all configured.

Streams Support

Phoenix Streams work transparently. Efficient patches, no special handling.

Vue Ecosystem

Use any Vue library. Chart.js, TipTap, Headless UI — they all work.

AI-Ready

AGENTS.md auto-generated with LiveVue usage rules. Your AI assistant knows how to use it.

Lazy Loading

Load Vue components on demand. Keep your initial bundle small.

Try it live

Server state meets
client interactivity

Server State
0
@count from LiveView assigns
Local Vue state — no server round-trip
01
The count lives on the server. LiveView owns 0. Vue receives it as a prop.
02
The slider is local Vue state. No server round-trip for UI-only state.
03
phx-click triggers handle_event. Vue template, LiveView handler. Seamless.
Real-time collaboration

PubSub in action

Live Poll

Tabs or Spaces?

vs
0 votes
Time left:0s
Updates via PubSub - all users see votes in real-time
01
All users share the same poll. A GenServer holds the canonical state. Votes are authoritative.
02
Updates broadcast via PubSub. Every vote triggers a broadcast. All connected LiveViews update.
03
Vue handles the polish. Smooth bar animations, countdown timer, confetti — all local state.
04
3-second local vote throttle. Client-side rate limiting — no server round-trip needed.
The mental model

Props in. Events out.
Server owns the state.

Counter.vue
<script setup lang="ts">
import { ref } from "vue"

// Props from LiveView
const props = defineProps<{ count: number }>()

// Local Vue state
const diff = ref(1)
</script>

<template>
  <p>Count: {{ props.count }}</p>
  <input v-model.number="diff" type="range" />
  <!-- phx-click is also supported -->
  <button @click="$live.pushEvent('inc', { diff })">
    +{{ diff }}
  </button>
</template>
counter_live.ex
defmodule MyAppWeb.CounterLive do
  use MyAppWeb, :live_view

  def render(assigns) do
    ~H"""
    <.vue
      count={@count}
      v-component="Counter"
      v-socket={@socket}
    />
    """
  end

  def mount(_params, _session, socket) do
    {:ok, assign(socket, count: 0)}
  end

  def handle_event("inc", %{"diff" => diff}, socket) do
    {:noreply, update(socket, :count, &(&1 + diff))}
  end
end
Props Events
When to reach for LiveVue

LiveView is great.
But sometimes not enough.

For most apps, LiveView handles everything. But when you need rich client-side interactions or want to tap into the Vue ecosystem, LiveVue bridges the gap.

Rich Interactions

Drag-drop, animations, complex local state that doesn't need the server.

Vue Ecosystem

Chart.js, TipTap, Headless UI — any Vue package works out of the box.

Team Familiarity

Your frontend team already knows Vue. Let them use what they know.

Gradual Adoption

Start with one component. Expand as needed. No big rewrites.

Ready to bridge the gap?

One command. Full TypeScript. SSR included. Start building.

mix igniter.install live_vue
Jakub Skalecki

Built by Jakub Skalecki

Freelance Elixir developer with 12+ years of fullstack experience. Startup founder who knows when to push back on bad ideas. Python, JavaScript, Elixir, Applied AI.

Read the story: Road to LiveVue 1.0

Available for freelance Elixir projects