The schema stays authoritative
Constraints, refinements, defaults, and transforms remain in Zod or ArkType instead of being copied into form code.
Schema support →Open source · Zod & ArkType
FormAdapter turns your schema into a React form, keeps the original validation authoritative, and renders through DaisyUI or your own design system.
bun add @formadapter/react @formadapter/daisyui zod daisyuiReact 19 · DaisyUI 5 · Next.js and TanStack Start · MIT licensed
This form is rendered directly from the schema.
const signupSchema = z.object({
email: z.email(),
accountType: z.enum(["personal", "company"]),
company: z.string().min(2).optional(),
});
const Signup = createForm(signupSchema).configure({
fields: {
accountType: { control: "radio" },
company: {
hidden: (values) => values.accountType !== "company",
requiredWhenVisible: (values) =>
values.accountType === "company",
},
},
});"use client";
import type { ReactNode } from "react";
import { DaisyUIProvider } from "@formadapter/daisyui";
export function Providers({ children }: { children: ReactNode }) {
return <DaisyUIProvider>{children}</DaisyUIProvider>;
}Submit the form to see its schema output.One schema, the whole form
Constraints, refinements, defaults, and transforms remain in Zod or ArkType instead of being copied into form code.
Schema support →Mount a DaisyUI provider at the root, extend it, or replace it with a complete adapter for your own design system.
Adapter scopes →Conditional fields, wizards, drafts, async checks, arrays, files, focus management, and server errors share one runtime.
Form behavior →Server errors
"use server";
import { createNextAction, fieldError } from "@formadapter/nextjs";
export const saveProfile = createNextAction(
profileSchema,
async (profile) => {
if (await emailExists(profile.email)) {
throw fieldError("email", "Already registered");
}
return save(profile);
},
);Start with DaisyUI today. Replace the UI when you need to.