Runtime: Beignet requires Node.js 22.12 or newer. Bun is optional.
nuqs integration for Beignet
Beignet is experimental alpha software. The 0.0.x package line is for early
evaluation, and APIs may change between releases while the framework settles.
This package gives you a thin bridge between contract query params and nuqs URL state.
It does not replace @beignet/react-query. Instead, it helps you keep URL-backed filters aligned with a contract's query shape and then pass that state into rq(contract).queryOptions(...).
npm install @beignet/nuqs @beignet/core @beignet/react-query nuqs react @tanstack/react-query
In Next.js App Router, mount the NuqsAdapter once near the root:
import { NuqsAdapter } from "@beignet/nuqs/next/app";
export function Providers({ children }: { children: React.ReactNode }) {
return <NuqsAdapter>{children}</NuqsAdapter>;
}
import { createClient } from "@beignet/core/client";
import { createReactQuery } from "@beignet/react-query";
import { createNuqs } from "@beignet/nuqs";
const client = createClient({ baseUrl: "/api" });
export const rq = createReactQuery(client);
export const nq = createNuqs();
"use client";
import { parseAsInteger, parseAsString } from "nuqs";
import { useQuery } from "@tanstack/react-query";
import { nq, rq } from "@/client";
import { listContacts } from "@/features/contacts/contracts";
const contactsSearch = nq(listContacts).query({
parsers: {
search: parseAsString.withDefault(""),
offset: parseAsInteger.withDefault(0),
},
});
function ContactsPage() {
const [filters, setFilters] = contactsSearch.useState();
const query = useQuery(
contactsSearch.toQueryOptions(rq(listContacts), filters)
);
return null;
}
createNuqs()Creates the Beignet nuqs adapter factory.
nq(contract).query({ parsers, ...options })Creates a contract-aware URL query helper.
parsers: required nuqs parser map keyed by the contract's query paramshistory, shallow, scroll, urlKeys, etc.: forwarded to useQueryStates.useState(options?)Wraps nuqs useQueryStates(parsers, options) with the configured parser map.
.toQuery(state, { omitNullish })Converts nuqs state into a Beignet query object.
omitNullish defaults to truenull and undefined are removed0, false, and "" are preservedDate and object values are preserved for the typed clientquery.date() sends ISO-8601 values and query.deepObject(...) sends flat
objects as bracketed parameters, such as filter[owner]=user_1Nuqs parsers control the browser page URL separately. parseAsJson stores JSON
there; it does not make the Beignet API request use JSON query parameters.
Declare every API query field with defineQueryTransport(...) from
@beignet/core/contracts. The typed client rejects invalid dates, nested
objects, and undeclared transport members with INVALID_QUERY_PARAM.
See the query transport example
for a contract and matching parser map.
.toQueryOptions(rq(contract), state, options?)Convenience helper that calls rq(contract).queryOptions({ query, ...options }).
@beignet/nuqs is a good fit for pages where the URL should reflect search or filter state:
If you just need typed fetching, use @beignet/react-query directly.