AshSDUI uses one runtime model across generated screens, SDUI layouts, and Storybook proof surfaces. The package no longer treats generated CRUD views and layout-rendered screens as separate systems. Instead, both are different authoring paths into one runtime contract.
The shared contract
Every screen resolves into four shared values:
viewbindingsstatecontext
That contract is the center of gravity for the package. A generated collection
screen, a layout: :sdui recipe, and an ephemeral runtime layout can all be
described in the same language.
This is why the package can reuse the same runtime-aware components across different authoring styles. The important thing is not how the screen was authored, but that it can provide the same runtime contract at render time.
Why the runtime is split across modules
The package keeps separate responsibilities on purpose.
AshSDUI.View resolves Ash resource metadata and runtime options into a stable
screen description. AshSDUI.Binding turns declarative source definitions into
loaded values, refresh rules, and subscription behavior. AshSDUI.LiveResource
hosts the LiveView runtime and coordinates query updates, selections, workflow
state, refreshes, and intent dispatch. AshSDUI.Components.SDUIRoot bridges
that runtime into layout-rendered components.
This separation keeps the model inspectable. It also prevents generated screens from becoming a closed rendering pipeline that only works for one screen shape.
Lifecycle and ownership
A generated screen usually starts with AshSDUI.View.resolve/3, then moves
through binding planning and loading, then into AshSDUI.LiveResource, which
stores runtime state and registers subscriptions. Rendering happens either
through stock recipes or through SDUIRoot when the screen resolves to a layout
tree.
The important architectural choice is that LiveResource owns orchestration
while View and Binding own normalization. That split makes it possible to
grow runtime behavior without collapsing the whole system into LiveView-specific
callbacks.
Node-scoped runtime
Layout nodes can opt into small slices of the runtime with binding, refresh,
variant, and state_key. SDUIRoot turns those into focused component
assigns such as @bound_value, @refresh_meta, and @state_slice.
This is a deliberate middle ground. Components stay smaller because they do not need to understand the entire screen, but the package does not promise that each node becomes its own isolated LiveView process.
Why the runtime is broader than CRUD
The runtime model is built to host generated collection, detail, and form screens, but it also supports live collection bindings, refreshable panels, selection-aware actions, workflow state, and hybrid layouts. The generic components in the package exist to prove that the contract is reusable for product-facing runtime patterns, not just admin scaffolding.
This is also why Storybook and the demo app matter. They are proof that the runtime abstractions hold up outside the narrowest generated path.
What is intentionally deferred
The runtime is stable without claiming to solve everything. It does not yet
offer a dedicated ui_selection DSL, a dedicated ui_workflow DSL, a full
async intent lifecycle manager, or a complete cursor and range query model. It
also does not promise node-level process isolation.
Those gaps are deliberate boundaries around the current model, not evidence that the model is temporary.