React
Beignet has optional React integrations for server state, URL state, forms, and uploads. Each package is independent, so install only the pieces your app needs.
| Package | Use it for |
|---|---|
@beignet/react-query | Typed TanStack Query options, mutations, prefetching, and query keys |
@beignet/nuqs | URL-backed search, filters, tabs, sorting, and pagination |
@beignet/react-hook-form | Typed React Hook Form setup from a contract body schema |
@beignet/react-uploads | Typed upload state, progress, errors, and results from a Beignet upload client |
Adapter shape
Every adapter follows the same shape: create the package adapter once, then bind contracts or upload names from the returned helper.
const rq = createReactQuery(client);
const rhf = createReactHookForm();
const nq = createNuqs();
const reactUploads = createReactUploads({ uploads });Feature workflow
Keep shared adapter factories in client/ and product UI in the feature:
client/
errors.ts
forms.ts
index.ts
features/
todos/
components/
todo-app.tsx
contracts.tsThe feature component imports the contract and uses the client helpers:
"use client";
import { useMutation, useQuery } from "@tanstack/react-query";
import { rq } from "@/client";
import { rhf } from "@/client/forms";
import { createTodo, listTodos } from "@/features/todos/contracts";
const createTodoForm = rhf(createTodo);
export function TodoApp() {
const todosQuery = useQuery(rq(listTodos).queryOptions({ query: {} }));
const form = createTodoForm.useForm({ defaultValues: { title: "" } });
const createTodoMutation = useMutation(rq(createTodo).mutationOptions());
const onSubmit = form.handleSubmit((body) => {
createTodoMutation.mutate({ body });
});
return <form onSubmit={onSubmit}>{/* fields */}</form>;
}This is feature colocation, not server colocation. Components can import
contracts and frontend helpers, but they should not import use cases, route
groups, infra adapters, provider packages, server/, or app-context.ts.
Install
bun add @beignet/react-query @tanstack/react-query
bun add @beignet/nuqs nuqs
bun add @beignet/react-hook-form react-hook-form @hookform/resolvers
bun add @beignet/react-uploads