React hooks — overview

The client-side hook surface, grouped by purpose.

The web side of a Voltro app talks to API apps through React hooks. Data hooks are keyed by API name and RPC tag; routing hooks are provided by @voltro/web.

App code should reach for the typed binding rather than the tag-taking hooks directly: createHooks(apiName) takes the api's generated AppProcedures map and returns useSubscription / useMutation / useAction whose tag is a literal union and whose input and output types are inferred — so a typo'd tag is a compile error and the result needs no annotation. Bind it once per api in src/lib/api.ts. The tag-taking forms documented below are the primitive underneath, for code that only learns the tag at runtime.

Data Hooks

Hook Purpose
createHooks Bind the typed hook surface for one api — the recommended app-facing entry point.
useSubscription Subscribe to a reactive query (*.query.ts).
useMutation Run an atomic write (*.mutation.ts).
useAction Run a unary non-transactional action (*.action.ts).
useWorkflow Start, cancel, resume, or signal a durable workflow (*.workflow.tsx).
useWorkflowSignal Focused signal sender, for approval buttons that don't also start workflows.
useWorkflowUpdate Focused tracked update — waits for the workflow handler's result.
useWorkflowRun Subscribe to one workflow run's reactive status row.
useWorkflowRuns Subscribe to a bounded/filterable workflow run list.
useWorkflowRunSteps Subscribe to one run's checkpointed step timeline.
useWorkflowRunEvents Subscribe to one run's lifecycle/timer/signal event timeline.
useWorkflowDomainEvents Subscribe to the domain events a workflow emitted (the business-event timeline).
useWorkflowEventDeliveries Subscribe to delivery attempts/outcomes for those emitted events.
useWorkflowRunState Aggregates run + steps + events into one { status, currentStep, waitingFor, … } plus cancel/resume/signal/update.
useAgentStream Consume a one-shot element stream (*.stream.ts).
useAgent Convenience wrapper for transient AI streams.

Routing Hooks

Hook Purpose
useLocation Current pathname and route state.
useParams URL params from [name] segments.
useNavigate Programmatic navigation.
usePrefetch Trigger loader-data prefetch.
useLoaderData Page loader output.

Server / Context Hooks

Hook Purpose
useServerRequest Request snapshot during SSR and hydration-sensitive client code.

Schema-driven UI Hooks

The headless primitives that derive UI from a descriptor's Schema. Reach for these before hand-rolling a form, a table, or a picker — full guide in Schema-driven UI.

Hook Purpose
useFormBinding Bind a form to a MUTATION — fields + validation from its input Schema; a server ValidationError({ field }) routes to that field.
useFormField One field of the enclosing binding — value, blur, the display-gated error, a11y props. Re-renders that field alone.
useFormBindingContext The binding a <FormBindingProvider> (or <AutoForm>) mounted above — for a widget kit that needs the form itself, not one field.
useDataTable Bind a table to a QUERY — live rows, columns derived from the output Schema, sort/filter/pagination.
useQueryFilters Filter controls derived from a query's INPUT Schema (the read-side mirror of a form).
useQueryField Query-bound picker — a debounced search term drives a live subscription.
useFormSkeleton / useTableSkeleton Placeholders shaped like the REAL data, from the same Schema.
useAsyncValidation Live server-side validation (uniqueness, cross-row) over a query binding.
useDebounced Debounce a value (search, filter, validation input).
useRecord One live record from a "get" query, normalized (array → first row).
useValidationMessages The app-wide validation-message resolver from <ValidationMessagesProvider>, or undefined when none is mounted — for a widget kit that resolves message ids itself.

Files, Permissions, and Client Utilities

Hook Purpose
useUpload File upload with progress + cancel, on every storage provider. Not base64 → action.
usePresenceChannel One presence wire for local-first: the peer roster plus a publish/subscribe pair for ephemeral payloads (cursors, typing), riding the existing presence lane rather than a second socket. Room-scoped — a mismatched room throws instead of delivering across rooms.
useCan Scope/RBAC UI gate, over <PermissionProvider>. Lives in @voltro/client — scopes are a framework concept, so gating a button needs no rbac dependency.
useCanAny OR variant of useCan — true when the subject holds AT LEAST ONE of the required scopes.
usePermissions / <PermissionProvider> The current subject's scope set, fed once from your session query — the source useCan reads. Gates UI on the SAME scope strings the server checks.
useResourceCan / useResourceCans Per-RESOURCE (ReBAC) gate, reactive — one resource or many in a single subscription.
useDerived Dependency-tracked derived value from reactive sources. Replaces hand-maintained useMemo dep arrays.
useWindowedSubscription Subscribe to the VISIBLE window of a huge list, not the whole table.
useOutbox Queue mutations offline, replay in order on reconnect.
useUndoLog / useUndo Client controller for the server-persisted undo stack.
usePreview Mutation dry-run — run the real handler in a rolled-back transaction.
useProvenance "Why is this value here?" — lineage lookup for a field.
useOnRpcError / reportClientError Subscribe to the rpc error bus; report a client error to the server.
useSubscriptionHealth Which of an api's calls are currently REFUSED — a refused subscription never retries and reads as loading.
useTracking Fire mount/unmount + interaction tracking events.
useCapabilityManifest The api's capability manifest (procedures + tables + schemas), fetched once.
useRefreshSubscriptions Force-refresh live subscriptions (e.g. after an out-of-band change).

AI Hooks

Hook Purpose
useAgentChat Full chat surface over an *.agent.tsx (messages + send + streaming).
useResumableAgentStream Agent stream that survives reload/reconnect.
useDataCopilot Bind a data-copilot action by api name + tag.

Plugin and Local-First Hooks

Shipped by an installed plugin or by @voltro/local-first, not by @voltro/client — the import path is the package, and each takes the api name as its last argument (default 'app'). The rest of the surface reads exactly like the hooks above.

Hook Package Purpose
useWebPush @voltro/plugin-notifications/web Web-push permission flow, service-worker registration and subscribe/unsubscribe — { status, error?, subscribe, unsubscribe }, where status distinguishes unsupported / denied / subscribed for THIS browser.
useComments @voltro/plugin-comments/web The live threads on one anchor plus every action on them (create, edit, resolve, remove, react, markRead) and the unread badge count.
useThread @voltro/plugin-comments/web One thread by id — a projection over the same live list, so it opens no second subscription.
useMentionSearch @voltro/plugin-comments/web @-mention autocomplete over the app-declared, tenant-filtered directory.
useCrdtText @voltro/local-first/react A collaborative text field bound to one crdtText() cell — merged text, minimal-span edits, the offline queue and synced.
useCrdtDoc @voltro/local-first/react The sync half of a crdtDoc() column — one SyncClient + one live CRDT document per cell, with the echo guard that keeps a folded remote update from being pushed back. Hands the document to useCrdtEditor.
useCrdtEditor @voltro/local-first/editor A collaborative rich-text editor over a crdtDoc() column — one Tiptap instance bound to the shared document, carets bridged over an injected transport.