Definitions
createNexusDefinition
lets you define requests in a single, predictable format that both the server and client can use.
Import
import { createNexusDefinition } from "next-nexus";
Important: In this project,
definition
objects MUST be created via a factory. Direct, one-off calls tocreateNexusDefinition<T>({...})
are not allowed.
Factory Usage (Required)
Create a factory with shared defaults, then derive domain-specific definition
objects from it.
export const createApiDefinition = createNexusDefinition({
baseURL: "https://api.example.com",
timeout: 5,
retry: { count: 1, delay: 1 },
headers: { "x-app": "docs" },
});
export const productDefinition = {
list: createApiDefinition<Product[]>({
method: "GET",
endpoint: "/products",
server: {
// next-nexus defaults server.cache to 'no-store'; set 'force-cache' only if you want static caching/ISR
revalidate: 1800, // maps to next: { revalidate: 1800 }
tags: ["products"], // maps to next: { tags: ['products'] }
},
client: { tags: ["products"], revalidate: 300 },
}),
detail: (id: string) =>
createApiDefinition<Product>({
method: "GET",
endpoint: `/products/${id}`,
client: { tags: ["products", `product:${id}`], revalidate: 300 },
}),
like: (id: string) =>
createApiDefinition<{ success: boolean }>({
method: "POST",
endpoint: `/products/${id}/like`,
}),
};
Cached Response Headers
Use client.cachedHeaders
to cache safe, small headers (e.g., x-total-count
) alongside the hydrated data.
Define
export const listWithTotalDefinition = createApiDefinition<Product[]>({
method: 'GET', endpoint: '/products',
client: { tags: ['products'], revalidate: 300, cachedHeaders: ['x-total-count'] }
})
Notes
- Do not cache sensitive headers.
- Headers are restored from the hydration payload without extra requests.
Options
method
: ‘GET’ | ‘POST’ | ‘PUT’ | ‘PATCH’ | ‘DELETE’endpoint
: string (path part)baseURL?
: string (prepends endpoint)headers?
: HeadersInit (merged; falsy string values like'null'
or'undefined'
remove the header)server?
:{ cache?: RequestCache; revalidate?: number; tags?: string[] }
client?
:{ revalidate?: number; tags?: string[]; cachedHeaders?: string[] }
timeout?
: number (seconds)retry?
:{ count: number; delay?: number }
interceptors?
: string[] (names registered viainterceptors.request/response.use
)
Defaults
server.cache
: If omitted, next-nexus defaults to'no-store'
regardless of the Next.js version. Next.js 14 defaults to'force-cache'
, while Next.js 15+ defaults to'no-store'
. next-nexus keeps'no-store'
as the default for consistency. Setserver.cache: 'force-cache'
explicitly only when you want static caching or ISR.- Naming: Use the
*Definition
suffix for clarity (e.g.,productDefinition
,listWithTotalDefinition
).
Typing
- Prefer transport-oriented types:
Product
,ProductListResponse
. - The generic response type flows into
nexus
,useNexusQuery
,useNexusMutation
, andnexusCache
. - For runtime schemas (e.g., Zod), derive TypeScript types from the schema and keep names consistent (
ProductSchema
→type Product = z.infer<...>
).
Patterns and Anti-patterns
Patterns
- Create dynamic
definition
objects for parameterized endpoints by using the factory:const detail = (id: string) => createApiDefinition<Product>({ method: "GET", endpoint: `/products/${id}` });
- Cache small, safe response headers via
client.cachedHeaders
(e.g.,x-total-count
). - Use
tags
consistently to enable precise server and client revalidation.
Anti-patterns
- Mixing server-only APIs inside delegated subtrees.
- Omitting
tags
and then trying to revalidate precise slices of data later. - Defining requests without the shared factory, which can lead to inconsistency and type-safety issues.
Tips
- Header merging: Using the string values
'null'
or'undefined'
for a header will remove it after merging. - Route proxying: When hooks are passed a
route
prop, the runtime clearsbaseURL
and uses the route path as the endpoint.
See also
Last updated on