LiveVue
1.0
Vue Sigil
Write Vue components directly in your LiveView with the
~VUE
sigil. No separate file needed.
What this example shows
defmodule MyAppWeb.SigilLive do
use MyAppWeb, :live_view
use LiveVue
@emojis ~w(rocket fire star sparkles zap rainbow heart pizza)
def render(assigns) do
~VUE"""
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps<{
emoji: string
votes: number
}>()
const emojiMap: Record<string, string> = {
rocket: '🚀', fire: '🔥', star: '⭐', sparkles: '✨',
zap: '⚡', rainbow: '🌈', heart: '❤️', pizza: '🍕'
}
const display = computed(() => emojiMap[props.emoji] || '❓')
</script>
<template>
<div class="text-center">
<div class="text-6xl mb-4 transition-all hover:scale-125" :title="emoji">
{{ display }}
</div>
<div class="text-2xl font-mono font-bold text-landing-text mb-4">
{{ votes }} votes
</div>
<div class="flex gap-2 justify-center flex-wrap">
<button
phx-click="vote"
class="py-2 px-4 bg-gradient-to-br from-phoenix to-phoenix-glow text-white rounded-lg font-medium shadow-lg shadow-phoenix/20 hover:-translate-y-0.5 transition-all"
>
Vote!
</button>
<button
phx-click="shuffle"
class="py-2 px-4 bg-landing-elevated border border-landing-border text-landing-text rounded-lg font-medium hover:bg-landing-card transition-all"
>
Shuffle
</button>
</div>
</div>
</template>
"""
end
def mount(_params, _session, socket) do
{:ok,
assign(socket,
emoji: Enum.random(@emojis),
votes: 0
)}
end
def handle_event("vote", _params, socket) do
{:noreply, update(socket, :votes, &(&1 + 1))}
end
def handle_event("shuffle", _params, socket) do
{:noreply, assign(socket, emoji: Enum.random(@emojis))}
end
end
VS Code Extension
Get syntax highlighting for the
~VUE
sigil in VS Code with the community extension.
How it works
1 Write Vue inline
Replace ~H
with ~VUE
and write a standard Vue SFC. Props are passed automatically from socket assigns.
def render(assigns) do
~VUE"""
<script setup lang="ts">
const props = defineProps<{ count: number }>()
</script>
<template>
<div>{{ props.count }}</div>
</template>
"""
end
2 Phoenix bindings work
Use phx-click, phx-submit,
and other Phoenix bindings directly in the Vue template.
<button phx-click="vote">Vote!</button>
3 Current limitations
The ~VUE
sigil doesn't yet support TypeScript type-checking or autocomplete inside the sigil.
There's ongoing work to bring full editor support. For now, use
.vue
files when you need rich editor tooling.
4 When to use the sigil
The ~VUE
sigil is perfect for
small, self-contained components and rapid prototyping. For larger components or
when you need type safety, use separate
.vue
files.