Xenia.Persistent behaviour (Xenia v0.1.1)

Copy Markdown View Source

A layout's persistent part: a LiveView that stays mounted, with its state and its JavaScript components, while the user moves between the pages under its layout. It lives in a persistent.ex next to the layout.ex; the module name is yours.

# app/(auth)/persistent.ex, next to app/(auth)/layout.ex
defmodule MyAppWeb.ShellLive do
  use MyAppWeb, :live_view
  use Xenia.Persistent

  def mount(_params, _session, socket), do: {:ok, assign(socket, path: nil)}

  def handle_navigation(uri, socket) do
    {:noreply, assign(socket, path: URI.parse(uri).path)}
  end

  def render(assigns) do
    ~H"""
    <nav>
      <.link navigate="/dashboard" class={@path == "/dashboard" && "active"}>Dashboard</.link>
    </nav>
    """
  end
end

Xenia renders it as a sticky LiveView, from the page, at the place its layout's frame puts @persistent (CLAUDE.md §9, experiment S1). What that means for you:

  • It knows the current page through handle_navigation/2. A sticky LiveView can't define handle_params/3: LiveView raises. Xenia calls handle_navigation(uri, socket) once it is connected, and after every navigation and patch, from LiveView's phx:navigate browser event.
  • It is configured once. It mounts when the first page under its layout renders, and keeps its state until a page outside the layout is shown. Pages can't pass it new parameters; send it a message instead.
  • It only persists within one live_session. Leaving it is a full page load.

Summary

Callbacks

Called with the page's full URL once the persistent part is connected, and after every navigation and patch. Optional.

Callbacks

handle_navigation(uri, socket)

(optional)
@callback handle_navigation(uri :: String.t(), socket :: Phoenix.LiveView.Socket.t()) ::
  {:noreply, Phoenix.LiveView.Socket.t()}

Called with the page's full URL once the persistent part is connected, and after every navigation and patch. Optional.