Restoration
Fuzor UI starts from HTML. A dormant component does not need a live Zag machine. Activation reconnects behavior and browser resources to the existing elements.
Page lifetime
import { resumeUi } from "fuzor/ui/resume";
const runtime = resumeUi(document, {
onError: error => console.error(error),
});
const root = document.getElementById("details")!;
await runtime.activate(root);
const publicState = runtime.pause(root);
await runtime.activate(root);
// On teardown:
runtime.dispose();
Pause captures state and releases the live behavior. Reactivation seeds audited machine state before startup and suppresses initialization callbacks. Normal future transitions still call the original callbacks. Each root has one owner; do not overlap runtimes or directly enhance a root already owned by a runtime.
Serialize through Effect Atom
const checkpoint = runtime.dehydrate();
const json = JSON.stringify(checkpoint);
// On a new document with matching stable component IDs:
const nextRuntime = resumeUi(document, {
checkpoint: JSON.parse(json),
});
The checkpoint store uses Effect v4 Atom serialization. Schema validation precedes mutation. Revisions belong to one checkpoint lineage; older or equal revisions cannot overwrite known state. Persisting checkpoints is an application decision: do not store secrets or arbitrary drafts in them.
await runtime.hydrate(newerCheckpoint) updates active behavior without replacing its DOM. Keep lineage revisions when producing server updates. A fresh revision-zero store is not automatically newer than an existing client checkpoint.
What is restored
The complete catalogue covers all 51 Zag machines at the pinned 1.44.0 release. Every adapter restores its private finite state, audited durable context, original bindable defaults and durable refs. Nested state paths are preserved: a combobox can resume suggesting, a tour can resume resolving its target, and a slider can resume dragging.
Resources reconnect after the existing DOM parts are bound. This includes positioning, observers, focus traps, dismissal, scroll locks, form integration and gesture listeners. Focus, scroll position and browser animation time are retained. Open overlays and saved timers or pending loads activate immediately; other components can remain dormant until interaction. Toolbar uses Fuzor's native engine and its public checkpoint contract.
Semantic delays retain absolute deadlines, including clipboard reset, hover-card open/close, number-input repeat, splitter hover, carousel playback/settling, tour waits and toast dismissal/removal. Timer ticks retain their elapsed-time anchor. Disposal cancels owned timers, requests and gesture listeners.
Nested menus checkpoint their parent/child identities and reconnect the graph to the current machines. Async lists and tree expansion restore data and request parameters, abort the old work and recreate pending read requests. Completion from a disposed runtime cannot update the resumed runtime.
Files and runtime bindings
runtime.dehydrate() returns synchronous JSON. File entries in it reference resources retained by their owning root; use the async variant when transporting files to another document:
const checkpoint = await runtime.dehydrateAsync();
const json = JSON.stringify(checkpoint);
// On another document, with the same IDs and application configuration:
const nextRuntime = resumeUi(document, { checkpoint: JSON.parse(json) });
The async variant includes selected file bytes, name, type and last-modified time, with a 64 MiB portable-file limit. It restores File values rather than discarding selection. It does not reopen the operating system's file picker.
Callbacks, collection constructors and target resolver functions remain application code. Reinstall the same configuration before activation; missing bindings or DOM resources fail explicitly. Browser handles and cleanup functions are recreated rather than encoded. JavaScript promise continuations are not serialized: pending operations resume from their recorded intent through the configured loader or transformer. Use durable workflows when completed operation results must survive interruption and writes need stable server-side replay keys.
Capture after queued events settle. Checkpoint schemas validate identity, state paths and durable fields; controlled values must agree with saved state. Requalify every state/context/ref contract when upgrading Zag. Arbitrary form fields that a component machine does not own are outside its checkpoint.
Server-rendered fragments can retain stable DOM identity during updates; checkpoints complement that identity and do not turn every UI update into a rerender. Precompile content whenever possible and attach behavior only where needed.
DOM-free server helpers
import { renderTabs, createUiCheckpointStore } from "fuzor/ui/server";
const html = renderTabs({
id: "language", label: "Language",
tabs: [{ value: "html", label: "HTML", content: "Start with HTML." }],
});
const store = createUiCheckpointStore();
// Capture validated public snapshots and optional audited machine checkpoints.
const payload = store.dehydrate();
store.dispose();
The server entry contains schema, presentation and HTML helpers without evaluating browser-only component classes. Import fuzor/ui/client explicitly when registering Web Components in a browser-only integration.