Pagination
Use query pagination strategies for URL-backed page and limit state.
Pagination strategies define the URL state, API schema, table state mapping, and reset behavior for paginated queries.
Offset Pagination
The built-in offset strategy uses zero-based pages.
import { offsetPagination } from "@tulip-systems/query";
import { usePagination } from "@tulip-systems/query/client";
const pagination = usePagination(offsetPagination);The controller exposes:
{
strategy;
input;
tableState;
onPaginationChange;
}pagination.input is the API shape:
type OffsetPaginationInput = {
page: number;
limit: number;
};Use page, not cursor, for shared query and table APIs.
API Schemas
Use offsetPaginationSchema in route inputs.
import { offsetPaginationSchema } from "@tulip-systems/query";
import z from "zod";
export const listProjectsInputSchema = z.object({
pagination: offsetPaginationSchema,
filters: projectFiltersSchema,
sorts: projectSortsSchema,
});Database Offset
Convert page and limit to SQL offset at the backend boundary.
import { parseOffsetPagination } from "@tulip-systems/query";
const { limit, offset } = parseOffsetPagination(input.pagination);Response DTO
Use offsetPaginationResponse(...) to create the standard paginated response.
import { offsetPaginationResponse } from "@tulip-systems/query";
return offsetPaginationResponse({
data,
pagination: input.pagination,
total,
});The response shape is:
type OffsetPaginatedResponse<TData> = {
data: TData[];
pagination: {
total: number;
totalPages: number;
limit: number;
hasNextPage: boolean;
hasPreviousPage: boolean;
page: number;
nextPage: number | null;
previousPage: number | null;
};
};Infinite Queries
Infinite queries still use page numbers as pageParam.
const response = useSuspenseInfiniteQuery(
orpc.projects.list.infiniteOptions({
initialPageParam: 0,
input: (page: number) => ({
...input,
pagination: { ...input.pagination, page },
}),
getNextPageParam: ({ pagination }) => pagination.nextPage,
getPreviousPageParam: ({ pagination }) => pagination.previousPage,
}),
);Keep provider-native cursors or opaque page tokens inside provider query code. The shared dataset and table API should expose page and limit values.