Paste your form's defaultValues object (or a real submitted payload) and get a Zod schema you can drop into useForm({ resolver: zodResolver(schema) }). One schema validates the form on submit and the matching API route on the server.
react-hook-form + zodResolver is the dominant pattern for typed forms in React: define a Zod schema, pass it through @hookform/resolvers/zod's zodResolver, and useForm gives you per-field errors and a strongly typed handleSubmit callback. Hand-writing the schema duplicates work — you've already declared the field shape implicitly when you wrote your defaultValues or a real submission's JSON. Pasting that JSON here generates the schema directly, and you spend your time on the parts Zod can't infer: cross-field refinements, custom error messages, and async validators.
The sample on this page is a canonical signup form (email, password, confirmPassword, names, country, terms checkbox, optional referral source). Drop the generated z.object into your useForm config; React Hook Form runs it on submit and surfaces formState.errors keyed by field path. For cross-field rules like password === confirmPassword, chain a .refine() onto the generated schema — treat the output as the starting point for value-shape validation, then layer invariants on top. The same schema can run on the matching API route or Server Action so the form's contract holds end-to-end.