Phoenix LiveView concepts in Scalive
Prerequisites
No Elixir or Phoenix experience is required. If Scalive is also new to you, the Quick start provides a runnable application shape.
Start With The Programming Model
Phoenix LiveView is a server-side programming model for interactive web pages. The server owns page state, renders HTML, receives browser events, and sends incremental updates over a persistent connection. The browser keeps the DOM in sync and runs JavaScript only where browser-specific behavior is needed.
Scalive brings that model to Scala 3 and ZIO. It is an independent implementation, not Phoenix running on the JVM and not a line-for-line port of Phoenix's Elixir API. You do not need to know Elixir to use Scalive.
Scalive is also alpha software and does not claim complete Phoenix LiveView parity. Read Project status before choosing it for an application.
Map The Core Concepts
| Phoenix LiveView concept | Scalive concept | What it means |
|---|---|---|
| LiveView | LiveView[Msg, Model]trait LiveView[Msg, Model]Defines a server-rendered view with typed messages and model state. | A server-owned interactive page with a typed model and typed messages. |
| Socket assigns | Model and Signal[Model] | Immutable application state passed to lifecycle methods and exposed read-only to the signal-backed view graph. |
mount | mountdef mount(ctx: MountContext): zio.package.Task[Model] | Creates the initial model for the HTTP render and again for the connected live process. |
handle_event and other callbacks | handleMessagedef handleMessage(model: Model, ctx: MessageContext): Msg => zio.package.Task[Model]Handles a message against the current immutable model. | Handles values from the view's Msg type and returns the next model in Task. |
| HEEx template | viewdef view(model: Signal[Model]): HtmlElement[Msg], HtmlElement[Msg]class HtmlElement[+Msg](tag: HtmlTag, mods: Vector[Mod[Msg]])An immutable element in Scalive's typed, protocol-neutral HTML algebra., and Scala HTML builders | Constructs typed HTML from signals and Scala values. |
phx-* event binding | Typed bindings such as on.click(message)lazy val click: HtmlAttrBinding | Connects browser interactions to values accepted by the LiveView's message type. |
| Diff and DOM patch | Scalive tree diff and the Phoenix LiveView JavaScript client | Sends changed render data to the browser instead of replacing the whole document. |
| LiveComponent | LiveComponent[Props, Msg, Model]trait LiveComponent[Props, Msg, Model] | Gives a stateful child component typed inputs, messages, and local state. |
| Router live route | liveval live: LiveRouteSeed[Unit] with Live.routerval router: LiveRouter | Connects a URL pattern to a LiveView through typed route declarations. |
| Route parameters | LiveView.Routedtrait Routed[Msg, Model, Params]A routed definition is deliberately not an unrouted LiveView. and route codecs | Decodes path and query data before application code uses it. |
| Root and live layouts | LiveRootLayouttrait LiveRootLayout[-A, -Ctx]Declaratively renders and identifies the outer document shell. and LiveLayouttrait LiveLayout[-A, -Ctx]Declaratively wraps a LiveView while preserving its message type. | Separates the complete HTML document from shared markup around live content. |
live_session and on_mount | Live.sessiondef session(name: String): LiveSessionBuilder[Any, Any] and LiveMountAspectclass LiveMountAspect[R, A, -In, Claims, Ctx]Produces context immediately before both disconnected and connected LiveView mount. | Groups routes and applies typed setup or authorization at mount boundaries. |
| Commands and hooks | JSval JS: JSCommands.JSCommand[Nothing]The empty JSCommand from which client commands are composed. and DOM hooks | Describes client effects and integrates JavaScript when a browser API is required. |
The names do not imply identical APIs or complete behavior coverage. They show where to start when a Phoenix guide or discussion uses a familiar concept.
Follow One Interaction
A Scalive interaction has four explicit parts:
view(model)def view(model: Signal[Model]): HtmlElement[Msg] has constructed a view graph ofHtmlElement[Msg]class HtmlElement[+Msg](tag: HtmlTag, mods: Vector[Mod[Msg]])An immutable element in Scalive's typed, protocol-neutral HTML algebra. values and bound an interaction to a typed message. It runs once for the current graph lifetime, not once per update.The Phoenix LiveView JavaScript client sends the interaction over the live connection.
handleMessage(model, ctx)def handleMessage(model: Model, ctx: MessageContext): Msg => zio.package.Task[Model]Handles a message against the current immutable model. receives the message and usesTaskto produce the next model.Scalive evaluates the affected signals, computes a snapshot diff, and sends the update for the browser to patch into the existing DOM.
The model remains on the server. Scalive does not require a second client-side state tree or a JavaScript component framework for ordinary interactions.
For the current code shape, follow the Quick start, then read Models, messages, and effects and Rendering, bindings, and diffs.
Understand The Two Mount Phases
The first request is ordinary HTTP. Scalive mounts the
LiveViewtrait LiveView[Msg, Model]Defines a server-rendered view with typed messages and model state. and renders a
complete response before a live connection exists. The browser then connects,
and Scalive mounts a new connected lifecycle for events and updates.
Do not treat the disconnected model instance as connected session storage.
Make mountdef mount(ctx: MountContext): zio.package.Task[Model] safe to run in both phases,
match ctx.connectiondef connection: Connection[Connected],
and use capabilities from Connection.Connected(capabilities) only after the
live connection exists. Project anatomy
traces both phases through a complete application.
Translate State And Effects
Phoenix examples commonly update values stored as socket assigns. In Scalive,
put those values in an immutable Model, represent allowed inputs with a Msg
enum or sealed hierarchy, and return a new model from
handleMessagedef handleMessage(model: Model, ctx: MessageContext): Msg => zio.package.Task[Model]Handles a message against the current immutable model..
Effects use ZIO through Task; they are not encoded as Phoenix callback
tuples. Subscriptions, async work, navigation, flash, uploads, and component
updates use typed context capabilities or dedicated Scalive values. Consult the
API reference for the API that exists in the current
revision rather than translating an Elixir call by name.
Keep Browser Code At The Edge
Scalive uses the Phoenix LiveView JavaScript client for the live connection and
DOM patching. Application state and normal event handling stay in Scala. Use a
hook or JSval JS: JSCommands.JSCommand[Nothing]The empty JSCommand from which client commands are composed. command when behavior depends on a browser API, a third-party
JavaScript widget, focus management, transitions, or another client-only
concern.
This client relationship does not make every Phoenix server feature available in Scalive. Protocol compatibility, public API coverage, and framework feature coverage are separate concerns.
Read Scalive Documentation First
Phoenix documentation is useful for understanding the broader LiveView model, but Phoenix code is not Scalive code. Names, lifecycle results, route setup, templates, effects, and testing APIs may differ intentionally.
Use the Learn path for current application code and the API reference for the current public surface. If a Phoenix feature is important to your application, do not infer support from this concept map; check the current API and raise an issue as described in Project status.
Related Tasks
Build typed markup and messages in HTML and event bindings.
Connect the browser client in Client setup and static assets.
Define application URLs in Routes, parameters, and navigation.