React
useSession, Can, useLive, and useLiveQuery from okengine/client-react — React helpers over createClient.
okengine/client-react is a separate package so core okengine/client stays under the size
budget. Hooks wrap the same typed client: session status, live SSE, and live resource lists with
optimistic mutate.
For developers building React storefronts and ops consoles on top of createClient.
The one rule
Pass the same api you built with createClient. Hooks never open a second client factory — they
subscribe, call Flows, and clean up on unmount.
Smallest Example
Create the client and session
import { createClient } from "okengine/client";
import { vault } from "okengine/vault";
import { app } from "../../src/app";
export const api = createClient(app, vault.env("PUBLIC_API_URL") ?? "", {
auth: { mode: "cookie", csrfConfigured: true },
});Show the signed-in shopper in the header
import { Can, useSession } from "okengine/client-react";
import { api } from "./session";
export function AccountMenu() {
const { status, user, signOut } = useSession(api.auth!);
if (status === "loading") return null;
if (status === "unauthenticated") return <a href="/sign-in">Sign in</a>;
return (
<>
<Can auth={api.auth!} all={["orders:write"]} fallback={null}>
<a href="/fulfillment">Fulfillment</a>
</Can>
<button type="button" onClick={() => signOut()}>
{user?.email}
</button>
</>
);
}Can / useAuthorize are UI-only — Gate on Flows remains real authz.
Progressive Patterns
import { useSession } from "okengine/client-react";
const { status, user, accessToken, refresh, signOut } = useSession(api.auth!);| Field | Meaning |
|---|---|
status | "loading" | "authenticated" | "unauthenticated" |
user | auth.me payload or null |
accessToken | Current Bearer from memorySession (or null) |
refresh() | Re-run auth.me |
signOut() | session.clear() + unauthenticated |
Package boundary
| Export | Package | Role |
|---|---|---|
createClient / api.live | okengine/client | Typed proxy + SSE subscribe |
createAuthClient / memorySession | okengine/client/auth | Secure session orchestration |
vault / vault.env | okengine/vault | Env + config contracts (subpath — not root) |
useSession / useLive / useLiveQuery | okengine/client-react | React hooks (react optional peer) |
subscribeLiveResource | okengine/client-react | Non-hook live resource stream helper |
Prefer createAuthClient for cookie/Bearer sessions and method helpers.
useLiveQuery accepts listPath to derive GET ${listPath}/live when live is omitted.
useLiveQuery options
| Option | Meaning |
|---|---|
enabled | Default true — idle when false |
refreshKey | Identity change → full re-subscribe |
onAuthRefresh | After auth.refresh() → new snapshot + replay |
refetch() re-runs only the HTTP list read; reconnects always do a full subscribe-protocol cycle
(new snapshot + replay). Event kinds and resume physics: Live.
Troubleshooting
Install / import the React package separately. Core okengine/client does not re-export hooks —
that keeps the client runtime under budget.
Confirm auth.me is adopted, Bearer getToken returns a token, and the me Flow is reachable.
Without a token, status becomes "unauthenticated".
Pass live: { method, path } from app.$routes for the resource’s /live route. Set
enabled: true (or omit). See Live for exposure and resume errors.
Learn more
- Auth —
memorySessionand gate denials - Live —
api.live, resume, live query kinds - Calling — envelopes and list pager
- Signal · Live — server tape
- Store —
live: trueresources