# PhoenixVapor Architecture PhoenixVapor blends Phoenix LiveView and Vue along three layers: 1. **Vue template syntax compiled to native LiveView rendered trees** 2. **Optional server-side Vue reactivity via lightweight QuickBEAM contexts** 3. **Optional Vapor-native DOM patching on the client** The goal is not to embed Vue beside LiveView, but to exploit the structural similarities between **Vue/Vapor templates** and **LiveView rendered diffs** as deeply as possible. PhoenixVapor keeps the strengths of both systems: - **LiveView** owns lifecycle, transport, events, supervision, reconnects, domain integration, and authoritative application state - **Server-side Vue reactivity** owns local UI state, computed values, and dependency-driven updates - **Vapor-style statics/dynamics** provide a shared rendering model that can drive efficient server and client patching --- # Server-side JS vs client-side JS PhoenixVapor uses JavaScript in two very different places. Keeping them separate is essential. ## Server-side JS Server-side JS runs inside **QuickBEAM** inside the BEAM process tree. It is used for: - Vue reactivity (`ref`, `computed`, watchers, local handlers) - optional full Vue runtime execution - evaluating or precomputing reactive values for rendering - maintaining per-LiveView local reactive state on the server This JS is authoritative only for **local reactive UI state**. Current server-side JS assets include: - `priv/js/vue-reactivity.js` - `priv/js/runtime-setup.js` - bundles loaded by `PhoenixVapor.VueRuntime` such as `priv/js/reka-dialog.js` Current Elixir entrypoints for server-side JS: - `PhoenixVapor.Runtime` - `PhoenixVapor.VueRuntime` - `PhoenixVapor.Reactive` - `PhoenixVapor.LiveVue` ## Client-side JS Client-side JS runs in the browser. It is used for: - standard Phoenix LiveView client behavior - receiving diffs over the websocket - applying DOM updates - optional Vapor-specific direct DOM patching This JS does **not** own authoritative application state. It is primarily a DOM patch engine and transport peer. Current client-side JS assets include: - `examples/demo/assets/js/app.js` - `examples/demo/assets/phoenix_vapor/index.js` - `examples/demo/assets/phoenix_vapor/vapor_patch.js` ## Why the distinction matters PhoenixVapor is not a classic client-heavy Vue app. The Vue-like reactive brain can live **server-side** in QuickBEAM, while the browser remains mostly a LiveView client with an optionally smarter patch engine. That means: - local UI state may be owned by **server-side JS** - authoritative domain state is owned by **Elixir/LiveView** - the browser JS is mainly responsible for **DOM application**, not app authority --- # High-level model PhoenixVapor supports three progressively deeper modes. ## 1. Compiled template mode Use Vue template syntax in a normal LiveView or component: ```elixir def render(assigns) do ~VUE"""

{{ count }}

""" end ``` In this mode: - the template is compiled at compile time into a Vapor split - the split is rendered into `%Phoenix.LiveView.Rendered{}` - expressions may be evaluated in Elixir - LiveView assigns are the primary input state - no persistent server-side JS runtime is required This mode is the lightest integration path. --- ## 2. Reactive mode Use a `.vue` Single File Component with `