# Basic Usage This guide covers the fundamentals of using LiveSvelte: the `<.svelte>` component, props, events, and the `~V` sigil. ## Your First Component ### 1. Create a Svelte component Place Svelte files in `assets/svelte/`. LiveSvelte discovers all `*.svelte` files in that directory at compile time. ```svelte

Count: {count}

``` ### 2. Use it in a LiveView ```elixir # lib/my_app_web/live/counter_live.ex defmodule MyAppWeb.CounterLive do use MyAppWeb, :live_view def mount(_params, _session, socket) do {:ok, assign(socket, :count, 0)} end def handle_event("increment", _params, socket) do {:noreply, update(socket, :count, &(&1 + 1))} end def render(assigns) do ~H""" <.svelte name="Counter" props={%{count: @count}} socket={@socket} /> """ end end ``` That's it. When the user clicks the button, `pushEvent("increment", {})` sends the event to `handle_event/3`, the count is incremented, and Svelte re-renders automatically. ## Props Pass any JSON-serializable map as `props`: ```heex <.svelte name="UserCard" props={%{name: @user.name, role: @user.role}} socket={@socket} /> ``` In the component, receive with `$props()`: ```svelte

{name}

{role}
``` ### Struct Props Structs must implement the `LiveSvelte.Encoder` protocol before being passed as props. Use `@derive` for the default implementation: ```elixir defmodule MyApp.User do @derive {LiveSvelte.Encoder, only: [:id, :name, :email]} defstruct [:id, :name, :email, :password_hash] end ``` The `only:` list controls which fields are exposed. Never derive without `only:` for structs with sensitive fields. ## The `live` Prop LiveSvelte automatically passes a `live` prop to every mounted component. Use it to communicate with the server: ```svelte ``` ## Composable Alternative to `live` Prop Instead of using the `live` prop, you can use composables which work from any component in the tree — no prop drilling: ```svelte ``` See the [API Reference](api_reference.md) for all composables. ## Component Shorthand with `LiveSvelte.Components` Add `use LiveSvelte.Components` to your LiveView (or web module) for shorthand component functions: ```elixir # In web module html_helpers (added by Igniter installer): import LiveSvelte use LiveSvelte.Components ``` Then instead of `<.svelte name="Counter" ...>`, use: ```heex <.Counter count={@count} socket={@socket} /> ``` The function names are generated from your `.svelte` filenames. `Counter.svelte` → `<.Counter>`, `UserCard.svelte` → `<.UserCard>`. > #### `socket` is required for SSR {: .info} > > Always pass `socket={@socket}` when SSR is enabled. It's used to detect the initial dead render vs. connected live render. You can omit it only when `ssr={false}`. ## Inline Templates with the `~V` Sigil For small, one-off components, write Svelte templates inline using the `~V` sigil: ```elixir def render(assigns) do ~V"""

Count is {count}

""" end ``` The sigil writes the template to `assets/svelte/_build/` at compile time and mounts it like any other component. All LiveView assigns are automatically available as props. > #### Svelte 5 Syntax Required {: .warning} > > Always use Svelte 5 runes syntax. Do NOT use Svelte 4 patterns: > > | ❌ Svelte 4 | ✅ Svelte 5 | > |-------------|-------------| > | `export let count` | `let { count } = $props()` | > | `let x = 0` (reactive) | `let x = $state(0)` | > | `$: doubled = x * 2` | `let doubled = $derived(x * 2)` | > | ` {#each filtered as item}
  • {item.name}
  • {/each} ``` ## Component Discovery LiveSvelte scans `assets/svelte/**/*.svelte` at compile time. Component names in `<.svelte name="...">` are relative paths without the `.svelte` extension: ``` assets/svelte/Counter.svelte → name="Counter" assets/svelte/forms/UserForm.svelte → name="forms/UserForm" ``` ## phx-update="ignore" LiveSvelte automatically sets `phx-update="ignore"` on the component wrapper div, which prevents LiveView from patching Svelte's DOM after mount. All updates flow through the hook. This is required for correct operation — do not override it.