LiveVue 1.0
Examples Vue Sigil

Vue Sigil

Write Vue components directly in your LiveView with the ~VUE sigil. No separate file needed.

What this example shows

1
Single File
Vue + Elixir in one place
2
Full Vue Power
script setup, TypeScript
3
Rapid Prototyping
Quick iterations
sigil_live.ex
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.

Get the 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.

Explore more examples
View all examples