Next.js
Mount hypequery in a Next.js App Router project.
Next.js
This guide assumes you already have:
- a typed
dbclient - an
analytics/queries.tsfile exportingapi - at least one routed query
If not, start with Quick Start.
Mount the handler in App Router
Create app/api/analytics/[...path]/route.ts:
import { api } from '@/analytics/queries';
import { createFetchHandler } from '@hypequery/serve';
const handler = createFetchHandler(api.handler);
export const runtime = 'nodejs';
export const GET = handler;
export const POST = handler;
export const OPTIONS = handler;createFetchHandler is exported from the root @hypequery/serve package, so you do not need to import from an adapter subpath.
Execute queries locally in server code
Use the same definition without HTTP in server components, actions, and jobs:
import { api } from '@/analytics/queries';
export const dynamic = 'force-dynamic';
export default async function Page() {
const stats = await api.run('dailyStats', {
input: {
startDate: '2025-01-01T00:00:00Z',
endDate: '2025-01-31T23:59:59Z',
},
});
return <pre>{JSON.stringify(stats, null, 2)}</pre>;
}Use force-dynamic on Server Components or pages that query ClickHouse during render. Without it, Next.js may try to prerender the page at build time and fail or time out when the database is unavailable.
Call the API from client components
Client components cannot import the serve API as a value — doing so bundles initServe and
@hypequery/clickhouse for the browser and fails the build with Can't resolve 'fs/promises'.
Generate the route manifest as static JSON instead:
npx hypequery generate:manifest analytics/queries.ts --output analytics/hypequery-manifest.json// lib/analytics.ts
import { createAnalyticsHooks } from '@hypequery/react';
import type { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/queries';
import manifest from '@/analytics/hypequery-manifest.json';
type Api = InferApiType<typeof api>;
export const { useQuery, useMetric, useDataset } = createAnalyticsHooks<Api>({
baseUrl: '/api/analytics',
manifest,
});Both api and InferApiType are imported with import type, so they are erased at build time and
only the manifest JSON survives into the client bundle. See the React guide
for provider setup.
Preview docs locally
npx hypequery dev analytics/queries.tsWith basePath: '/api/analytics', the preview server exposes:
- docs at
http://localhost:4000/api/analytics/docs - OpenAPI at
http://localhost:4000/api/analytics/openapi.json