React hooks
Use @hypequery/react to generate type-safe hooks (useQuery, useMutation) backed by TanStack Query. Bring your existing defineServe API types and wire them into your React app without duplicating schemas.
Installation
npm install @hypequery/react @tanstack/react-queryPeer dependencies: react@^18, @tanstack/react-query@^5.
Setup
Option 1: Automatic Type Inference (Recommended)
Use InferApiType to automatically extract types from your API definition:
// lib/analytics.ts
import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/queries';
// Automatic type inference - no manual type definition needed!
type Api = InferApiType<typeof api>;
export const { useQuery, useMutation } = createHooks<Api>({
baseUrl: '/api', // where your hypequery routes live
});This eliminates the need to manually define and maintain a separate type for your API.
Option 2: Manual Type Definition
If you prefer to manually define your API types:
// lib/analytics.ts
import { createHooks } from '@hypequery/react';
type Api = {
weeklyRevenue: {
input: { startDate: string };
output: { total: number };
};
// ... other queries
};
export const { useQuery, useMutation } = createHooks<Api>({
baseUrl: '/api',
});Wrap your app:
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
}useQuery
const { data, error, isLoading } = useQuery('weeklyRevenue', {
startDate: '2025-01-01',
});nameis one of your API keysinputmatches the endpoint’sinputSchema- Options mirror TanStack Query (
staleTime,enabled, etc.)
useMutation
const rebuild = useMutation('rebuildMetrics');
rebuild.mutate({ force: true });Mutations share the same typed input/output data.
HTTP Method Configuration
By default, hooks issue GET requests (matching the default route method). Override them per query when you need POST, PUT, etc.:
import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/queries';
type Api = InferApiType<typeof api>;
export const { useQuery, useMutation } = createHooks<Api>({
baseUrl: '/api',
config: {
weeklyRevenue: { method: 'GET' }, // Read-only queries
tripStats: { method: 'GET' },
rebuildMetrics: { method: 'POST' }, // Write operations
},
});Advanced: Auto-config from Server
You don’t have to maintain the verbs manually—@hypequery/serve can tell the client which HTTP method each route uses.
Option A – share the server module (Next.js / Remix):
When your React code can import the server bundle (e.g., Next.js App Router), just pass api directly:
import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import { api } from '@/analytics/queries';
type Api = InferApiType<typeof api>;
export const { useQuery, useMutation } = createHooks<Api>({
baseUrl: '/api/hypequery',
api, // method metadata is extracted automatically
});Option B – expose a config endpoint (SPAs / Vite):
If your frontend can’t import the server module, publish the config once and hydrate createHooks with it:
// app/api/hypequery-config/route.ts
import { extractClientConfig } from '@hypequery/serve';
import { api } from '@/analytics/queries';
export function GET() {
return Response.json(extractClientConfig(api));
}// lib/analytics.ts
import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/queries';
type Api = InferApiType<typeof api>;
let hooksPromise: Promise<ReturnType<typeof createHooks<Api>>> | null = null;
export function getHypequeryHooks() {
if (!hooksPromise) {
hooksPromise = fetch('/api/hypequery-config')
.then((res) => res.json())
.then((config) =>
createHooks<Api>({ baseUrl: '/api/hypequery', config })
);
}
return hooksPromise;
}Call await getHypequeryHooks() once during app bootstrap (e.g., inside a top-level provider) and reuse the returned useQuery/useMutation instances throughout your app.
Advanced options
Both hooks accept the underlying TanStack options, so you can control staleTime, retries, invalidation, manual queryClient access, etc.
Error handling
Errors bubble through TanStack Query’s error state. Validation errors from hypequery endpoints arrive as structured JSON (status code + body). Network failures throw standard fetch errors.
When to use it
- SPA dashboards needing cached queries
- Next.js / Remix apps already using TanStack Query
- Agents or components calling hypequery APIs inline
If you don’t need React hooks, you can call api.execute directly on the server or use the HTTP API as-is.