Skip to content
Form, Please

Your schema already knows the shape. Let it render the form.

Form, Please turns a Standard Schema and a typed definition into a React form. Field paths are checked against the schema. Validation messages come from the schema. The submit callback receives the transformed output type. React Hook Form (RHF) runs the state. Your components render it.

npm install form-please react-hook-form zod

See it before you install

Each tab is one complete file. Hover any identifier in the code to see its inferred type. The form on the right is rendered by that exact code.

One Zod schema, one definition, one hook. Every path in the definition must exist in the schema.

import type {  } from "form-please"
import {  as  } from "form-please/preset-native"
import {  } from "react"
import {  } from "zod"
 
const  = .({
	: .().(2, "Enter at least two characters"),
	: .().("Enter a valid email"),
})
 
const  = .(, () => [
	.("name", { : "text", : "Name", : true }),
	.("email", {
		: "text",
		: "Email",
		: true,
		: { : "email" },
	}),
])
 
export function () {
	const [, ] = <<typeof >>()
	const  = .(, {
		: { : "Ada Lovelace", : "ada@example.com" },
		: ({  }) => (),
	})
 
	let  = "Submit to see output"
	if ( !== )  = .(, null, 2)
 
	return (
		<>
			<. ={}>
				<.>Create account</.>
			</.>
			<>{}</>
		</>
	)
}

Rendered form

Submit to see output

Try this. Clear the email and submit. The Zod message appears next to the field.

Edit this scenario in the playground

The first tab is a complete program. Copy it into a file, install the three packages, and render SignupForm. Get started walks through the same file one step at a time.

Start from a task

  • Validate with ValibotPass a Valibot schema. Zod, Yup, and ArkType also work through Standard Schema. Rules, messages, and transforms stay in your schema.Shadcn with Valibot
  • Use my design systemWrap your controls and slots one time. The native, Material UI, and shadcn kits are working examples.Form kits
  • Put fields in columnsSet columns on a section and span on a field. The grid follows the section width, not the viewport, and you write no grid CSS.Columns and spans
  • Keep a total in syncWrite the rule once in the definition. It runs before each change commits, can cancel the change, and needs no effect.Value middleware
  • Save a draftKeep the schema input in storage that you own and restore it when the user returns.Persistence
  • Build a multi-step formShow one screen at a time, validate each screen, and submit a draft or the final form.Product workflows
  • Use React Hook Form directlyUse register, Controller, useWatch, and useFieldArray next to the generated fields, in the same form.Compose generated and custom UI
  • Migrate a React Hook Form appKeep your schemas and default values. Rewrite one form at a time, and move a large form in steps.Migrate from React Hook Form
  • Set up my coding agentGive your agent the llms.txt index or the installable skill, so that it writes correct definitions.AI agents

How it compares

Form, PleaseReact Hook FormTanStack FormFormik
Schema libraryAny Standard SchemaAny, via resolversAny Standard SchemaYup, or a validate function
Field paths checked against the schemaYesYesYesNo, string names
Fields generated from a definitionYesNoNoNo
Grid layout declared in the definitionYes, columns and spanNoNoNo
Conditional fields and arrays declared, not hand-wiredYesNoNoNo
Dependent values commit with their sourcesYes, beforeUpdateNo, useEffect and setValueField listeners, after the changeNo, useEffect and setFieldValue
Submit receives the transformed output typeYesWith a resolverNo, input values onlyNo
Design systemWrapped once per kitWired per fieldWired per fieldWired per field
Escape hatchFull React Hook Form APIIs the APIFull TanStack APIFull Formik API
Draft persistence and undo historyOptional entriesNoNoNo
DevtoolsOptional entryOfficial packageOfficial packageNo

Checked against each library's documentation in September 2026. Open an issue if a row is stale.

Proof

  • React 18 and 19
  • 28 kB gzipped for the native preset
  • Zod, Valibot, and Yup examples
  • Native, Material UI, and shadcn kits
  • Eleven browser-tested live examples
  • MIT

The size covers every entry the first tab imports. Material UI, persistence, history, and devtools are separate entries and add nothing until imported. Browse the live examples or the API.

What stays explicit

Each part of a form has one owner: the schema, React Hook Form, the definition, the kit, or your application. Read Ownership.

Use RHF register, Controller, and hooks such as useWatch when a generated definition is not enough. Read You keep the React Hook Form API.

Kudos

Kudos to Evgeniy Ivaha for the idea and the example implementation.