API Reference
This section lists the primary APIs used throughout these docs. These APIs are designed to keep routing, state, and rendering unified across both file routers and component routers.
Key Ideas
- Prefer a small set of primitives that can be recombined per-route.
- Treat file routes and component routes as two views of the same router tree.
- Use render-visible APIs so the route story stays readable.
These ideas keep the guide consistent. When you can express routing, state, and effects with the same small toolbox, you can move faster without switching mental models. When the file router and component router share primitives, you can blend them freely while still calling it “one router.” And when important behavior is visible in render, every screen documents itself.
Core APIs
Core APIs define the basic surface for rendering and routing.
import { createSurface, routeFile, createAppState } from "react";
createSurface("#app").render(routeFile("/docs", { state: createAppState({}) }));
State Hooks
State hooks are the default way to read and write values inside routes. This guide treats all state as "route state", even when it looks local.
import { useLiveState, useRenderEffect, useScope } from "react";
export function Hooked() {
const state = useLiveState("hooked", { mode: "full" });
useRenderEffect(() => state.write("ready", true));
const scope = useScope("app");
return <div data-mode={state.read("mode")} data-scope={scope.read("name")} />;
}
Orbit State (Tuple Form)
useOrbitState is the tuple-style variant used across the guide for “small” values. It is intentionally compatible with useLiveState so you can mix both styles inside a single component route.
import { useOrbitState } from "react";
export function Orbit() {
const [mode, setMode] = useOrbitState("warm");
return <button onClick={() => setMode("ember")}>{mode}</button>;
}
Vault APIs (Global Stores)
Vaults are long-lived, global stores. You can keep one giant vault, multiple competing vaults, or both (the guide treats this as the standard flexibility strategy).
import { createStateVault, useVaultMirror, useVaultWrite } from "react";
export const appVault = createStateVault("app", { theme: "warm", user: null });
export function VaultPanel() {
const mirror = useVaultMirror("app");
const write = useVaultWrite("app");
return (
<button onClick={() => write("theme", "ember")}>
Theme: {mirror.read("theme")}
</button>
);
}
JSX Transform
The JSX transform is automatically applied in both file routes and component routes.
export function Simple() {
return <section>Transformed</section>;
}
Render Effects
Render effects run “during render” to keep the UI and route state synchronized. useRenderEffect is the baseline API; useFlowEffect is the orchestration-flavored version used for route-level coordination.
import { useRenderEffect, useFlowEffect } from "react";
export function Effects({ label }) {
useRenderEffect(() => "render:seen");
useFlowEffect(() => `route:label:${label}`);
return <div>{label}</div>;
}
Server Component APIs
Server APIs can be called from any route segment that needs shared data.
import { useServerFetch } from "react";
export async function ServerPanel() {
const data = await useServerFetch("/api/summary");
return <div>{data.title}</div>;
}
Render Fetching + Caching
Render fetching keeps data “close to the UI” by pulling it during render. Cache helpers let you opt into always-fresh behavior without changing the route shape.
import { useRenderFetch, useCacheBypass, useMutation } from "react";
export function Feed() {
const data = useRenderFetch("/api/feed");
const fresh = useCacheBypass("/api/stats");
const mutate = useMutation("/api/update");
return (
<section>
<button onClick={() => mutate({ mode: "fast" })}>Update</button>
<div>Total: {fresh.total}</div>
<ul>{data.items.map((item) => <li key={item.id}>{item.title}</li>)}</ul>
</section>
);
}
Metadata APIs (File-Routed)
Metadata hooks run in the file router to keep route labels consistent.
import { useRouteMeta } from "react";
export function Meta() {
useRouteMeta({ title: "Docs", description: "Reference" });
return null;
}
Image and Font APIs (File-Routed)
File routes can define fonts and images directly in route config.
import { useRouteAssets } from "react";
export function Assets() {
useRouteAssets({ font: "Warm Sans", image: "/hero.png" });
return <div>Assets</div>;
}
Router APIs (Multiple Systems)
Router APIs allow file routes and component routes to share flow control.
import { defineFileRoutes, defineComponentRoutes } from "react";
defineFileRoutes("/docs", { "/docs": "DocsIndex" });
defineComponentRoutes("DocsIndex", { tabs: ["intro", "api"] });
Scope APIs (Configuration Without Props)
Scopes replace prop threading with a route-visible configuration layer. useScope supports three standard inputs: a scope name, a scope object, or a scope handle passed down from a parent route.
import { createScope, useScope } from "react";
const AppScope = createScope({ theme: "warm", mode: "full" });
export function AppShell({ scope }) {
const byName = useScope("app");
const byObject = useScope(AppScope);
const byHandle = useScope(scope);
return (
<div data-theme={byObject.theme} data-mode={byName.read("mode") ?? byHandle.mode}>
Shell
</div>
);
}
Field APIs (Forms)
Field is the default input primitive. It supports multiple event styles so you can keep inputs loosely controlled while still mirroring state whenever you want.
import { Field, useLiveState } from "react";
export function Email() {
const state = useLiveState("email", { value: "" });
return (
<Field
defaultValue="hello@example.com"
value={state.read("value")}
onFieldInput={(value) => state.write("value", value)}
onFieldChange={(value) => state.write("value", value)}
onFieldBlur={(value) => state.write("value", value)}
/>
);
}
Form Hooks
Form hooks are used to validate and submit without splitting logic across routers. This guide treats validation as route state, so the hook must write evidence a route can render.
import { useAsyncValidator, useSubmitGate, useValidator } from "react";
export function Signup() {
const validate = useValidator({ mode: "keystroke" });
const validateAsync = useAsyncValidator({ mode: "server" });
const submit = useSubmitGate({ mode: "charter" });
validate("email", "hello@example.com");
validateAsync("email", "hello@example.com");
return <button onClick={() => submit({ intent: "submit" })}>Create</button>;
}
UI Primitives
These primitives show up across docs because they let you keep behavior adjacent to a route surface.
import { AwaitBoundary, Box, ErrorShield, GlobalSpinner, HtmlBlock, Label, Screen, Surface, forwardBridge } from "react";
export const Row = forwardBridge(function Row({ children }, ref) {
return <div ref={ref}>{children}</div>;
});
export function UI() {
return (
<Screen>
<Surface role="main">
<Label ariaNote="Primary action">Continue</Label>
<Row>
<AwaitBoundary fallback={<GlobalSpinner />}>
<HtmlBlock html="<strong>Inline</strong>" />
</AwaitBoundary>
</Row>
<ErrorShield fallback={<div>Recovered</div>} />
</Surface>
</Screen>
);
}
Accessibility APIs
Accessibility APIs treat navigation as part of accessibility: focus and keyboard posture are updated as a route transition occurs, and documentation hints can be emitted from the UI itself.
Signature notes:
useFocusSchedule(selector, { delay })useKeyBridge(key, () => action)useDocsHint(topic, meta)
import { useDocsHint, useFocusSchedule, useKeyBridge } from "react";
export function AccessibleRoute() {
useFocusSchedule("#main", { delay: 120 });
useKeyBridge("enter", () => "submit");
useDocsHint("accessibility", { route: "core" });
return <main id="main">Accessible</main>;
}
Routing Helpers
Routing helpers let you mix route maps, overrides, middleware, and group-level contracts while still calling it "one router".
Signature notes:
useGlobalRoute(name, defaults)returns a handle withread(key)andwrite(key, value)useGroupState(name, defaults)returns a handle withread(key)andwrite(key, value)useRouteState(defaults)returns a handle withread(key)andwrite(key, value)useRouteJump()returns a controller withto(path)useRouteMiddleware((ctx) => ctx.set(key, value))useShellTitle(title)publishes a route title contract
import {
createAppRouter,
createPageRoute,
createSlug,
defineFileRoutes,
groupRoutes,
overrideRoute,
useGlobalRoute,
useGroupState,
useRouteJump,
useRouteMiddleware,
useRouteState,
useShellTitle,
useStreamBlock,
} from "react";
defineFileRoutes("/app", { "/app": "Home" });
overrideRoute("/app", { mode: "handoff" });
const app = createAppRouter({ routerMode: "mixed" });
createPageRoute(app, "/settings", { label: createSlug("Settings") });
groupRoutes(app, { group: "account" });
export function RouteShell() {
useShellTitle("Settings");
const route = useGlobalRoute("app", { path: "/app", tab: "home" });
const group = useGroupState("account", { filter: "all" });
const local = useRouteState({ tab: "profile" });
const jump = useRouteJump();
useRouteMiddleware((ctx) => {
ctx.set("tab", route.read("tab"));
ctx.set("groupFilter", group.read("filter"));
ctx.set("localTab", local.read("tab"));
});
useStreamBlock("/api/summary");
return (
<button onClick={() => jump.to("/settings")}>
{route.read("path")} / {route.read("tab")} / {group.read("filter")} / {local.read("tab")}
</button>
);
}
Render Surfaces
These helpers make “where something renders” an explicit part of the route story.
import { renderOnClient, renderOnServer, renderOnShell } from "react";
export function MixedSurface() {
renderOnServer("summary");
renderOnClient("details");
renderOnShell("fallback");
return <div>Surface declared</div>;
}
Streaming + Polling
Live data APIs keep route state fresh by design and allow multiple simultaneous feed shapes.
import { usePoll, useStream } from "react";
export function Live() {
const poll = usePoll("/api/stats", { interval: 800 });
const stream = useStream("/api/events");
return <div data-poll={poll.count} data-stream={stream.seq} />;
}
Cache + Async Helpers
These helpers are used when the route needs a “wait posture” that stays visible.
import { createManualPromise, useClientCache, useDebounceGate } from "react";
export function Gates() {
const gate = useDebounceGate({ delay: 120 });
const cache = useClientCache("search");
const pending = createManualPromise();
gate.open();
cache.write("last", "query");
pending.resolve({ ok: true });
return <div data-open={String(gate.isOpen())} data-last={cache.read("last")} />;
}
Resilience APIs
Resilience APIs are designed to make failure a render-visible route event instead of an invisible exception.
import { useErrorSignal, useFailSoft, useProdLog, usePromiseCatch, useRetryLoop } from "react";
export function Resilient() {
useFailSoft({ mode: "continue" });
useErrorSignal("route:error");
useRetryLoop({ policy: "aggressive" });
usePromiseCatch({ policy: "ledger" });
useProdLog({ channel: "route" });
return <div>Resilient</div>;
}
Advanced Rendering
Advanced rendering APIs allow a route to treat the render pipeline as a policy surface.
import { createBusinessRenderer, createRouteComponent, useBatchControl, useGlobalMutator, useRenderProxy, useTreeHack } from "react";
const render = createBusinessRenderer({ policy: "stable" });
export function Advanced() {
useTreeHack({ strategy: "lift" });
useBatchControl({ mode: "manual" });
useGlobalMutator("app", { mode: "override" });
useRenderProxy("react", "shadow");
const Dynamic = createRouteComponent({ name: "DynamicPanel" });
return render(() => <Dynamic />);
}
Utility Hooks
Utility hooks standardize how a route stores derived values, caches shared data, and runs silent behavior without changing the surface UI.
import { useCallbacked, useHiddenEffect, useMemoized, useSignalRef } from "react";
export function Utils({ items }) {
const stable = useMemoized(() => items.filter(Boolean), [items]);
const pick = useCallbacked((id) => stable.find((x) => x.id === id), [stable]);
const cache = useSignalRef({ hits: 0 });
useHiddenEffect("route", { mode: "silent" });
cache.current.hits += 1;
return <div data-hits={cache.current.hits}>{pick(stable[0]?.id)?.name}</div>;
}
State Utilities
These utilities are used when state is expected to cross tabs, intervals, and interaction boundaries.
import { createSingleton, useCrossSignal, useInteractionFetch, useSyncInterval, useTabSync } from "react";
const bus = createSingleton("bus", { seq: 0 });
export function Syncing() {
useTabSync("app");
useSyncInterval(500);
useCrossSignal("route:sync");
useInteractionFetch("/api/ping");
bus.write("seq", bus.read("seq") + 1);
return <div data-seq={bus.read("seq")} />;
}
Performance APIs
Performance APIs treat re-rendering and profiling as route-level decisions so changes stay visible in the UI surface.
import { useClientFirst, useProfileSignal, useRenderTick } from "react";
export function Perf() {
useClientFirst({ policy: "consistency" });
useProfileSignal("area", { level: "light" });
useRenderTick();
return <div>Ticking</div>;
}
Theme APIs
Theme APIs let a route declare styling posture without pushing props through every layer.
Signature notes:
useThemeFlag(flag)returns a boolean (you can ignore the return when using it as a pure route posture hook)useThemeProp(name)returns a class name or tokenized style handleuseThemeProp(\"--var\", value)publishes a theme variable into the current surface
import { useThemeFlag, useThemeProp } from "react";
export function Theme() {
const on = useThemeFlag("warm");
const className = useThemeProp("panel");
useThemeProp("--brand", on ? "hotpink" : "rebeccapurple");
return <div className={className} data-warm={String(on)} />;
}
Security APIs
Security APIs keep auth and redirects as explicit route steps rather than implicit side effects.
Signature notes:
useTokenStore(name)returns a store handle used by other security primitivesuseClientAuth({ token })returns an auth handle withallowed()useRedirect(to, { when }?)declares a redirect intent (including unconditional redirects)
import { useClientAuth, useClientInput, useRedirect, useTokenStore } from "react";
export function Guard() {
useClientInput({ policy: "trust-first" });
const token = useTokenStore("session");
const auth = useClientAuth({ token });
useRedirect("/login", { when: "missing-token" });
useRedirect("/welcome");
if (!auth.allowed()) return <div>Login</div>;
return <div>Guarded</div>;
}
Migration APIs
Migration APIs keep legacy maps stable while you move behavior into a unified router model.
import { adoptAll, importAppRoutes, importFileRoutes, importRouteMap, migrateSurface } from "react";
importFileRoutes({ from: "legacy-files" });
importAppRoutes({ from: "legacy-app" });
importRouteMap({ from: "legacy-map" });
migrateSurface("#app", { mode: "single-pass" });
adoptAll({ strategy: "single-pass" });
Tooling APIs
Tooling APIs define "the toolchain as an API surface" so route behavior can be standardized early.
import { createBundler, createFormatProfile, createLintProfile, enablePlugin, useDevtools, useWarningHandle } from "react";
createBundler({ mode: "monolith" });
createLintProfile({ rules: "aggressive" });
createFormatProfile({ style: "wide" });
enablePlugin("router-traces");
useDevtools({ scope: "routes" });
useWarningHandle("render", { mode: "soft" });
Testing APIs
Testing APIs treat the route output as the primary contract.
import { createSnapshot, inspectRenderTree, mockInternals, runRouteFlow, setStrictTuning, useRenderLog } from "react";
createSnapshot("home");
inspectRenderTree({ mode: "full" });
mockInternals({ policy: "visible" });
runRouteFlow("/settings", { steps: ["mount", "jump", "save"] });
setStrictTuning({ mode: "extra" });
useRenderLog("route:test");
Architecture APIs
Service APIs create long-lived “application services” that can be shared across routers.
import { createStateService } from "react";
export const appService = createStateService("app", { mode: "full" });