Create the client once in src/api.ts (or lib/api/api.config.ts) and import
it. Combine with the TanStack Query integration. Nothing
special required — the client runs entirely in the browser and talks to your
backend directly.
Reference app: examples/react-vite — direct
client, TanStack Query, and an interactive Feature Lab.
There are two ways to use the client in Next.js. Pick based on where your backend URL is allowed to be seen:
-
Server-only (RSC / Server Actions / route handlers) — call the real
apidirectly. The request happens on the server; nothing leaks. Use this for data you fetch during render.- Do not read
localStorageon the server. UseserverTokenFromCookie()/serverTenantResolver(). - Wrap per-request work in
runWithTenant()when multi-tenant.
export const api = createClient({ baseURL: process.env.API_URL!, openapi: { mode: 'runtime' }, auth: { strategy: 'bearer', getToken: serverTokenFromCookie('access_token') }, tenancy: { getTenantId: serverTenantResolver('x-tenant-id') }, })
- Do not read
-
Client components that must call the API — do not import the real client (that would ship your base URL, backend paths, and OpenAPI into the browser bundle). Use the SSR RPC bridge: a client-side proxy with the same
api.module.method()surface that forwards each call to a Server Action or route handler.
For TanStack Query prefetch/hydration, the queryOptions factories work in both
Server Components (prefetch + dehydrate) and client components
(HydrationBoundary); route client-component queries through the bridge client.
Reference app: examples/nextjs.
Note:
examples/nextjsuses a modified Next.js — readexamples/nextjs/node_modules/next/dist/docs/before writing Next-specific code (per itsAGENTS.md).
Both are covered by the framework-agnostic route handler:
createStartRpcRoute / createRemixRpcAction over createRpcRouteHandler. The
generic httpTransport({ endpoint }) browser client works with either — see the
HTTP-transport variant in
examples/nextjs/lib/api/rpc-http-client.ts.
Vite-based projects can auto-generate the typed client with the Vite plugin.
Works out of the box with the Axios adapter. Provide a server-appropriate
getToken (env var, secrets manager, etc.).
Import your client normally — the library detects the edge runtime and uses the
fetch adapter automatically (Axios is never loaded). You can also force it:
createClient({ http: { adapter: 'fetch' }, /* ... */ })