For the complete documentation index, see llms.txt. Prefer markdown by appending.mdto documentation URLs or sendingAccept: text/markdown.
Forms
TanStack Form, Zod validation, and Kumo inputs for product forms, with accessible feedback, server checks, submission states, and localization.
Forms turn customer intent into application data. Edge Kit connects TanStack Form, Zod schemas, Kumo controls, and server operations in its authentication, account, and contact flows.
You can reuse this foundation for onboarding, project settings, feedback, or any feature that needs structured input. The supplied forms demonstrate validation, submission progress, translated labels, and feedback after the operation completes.
Why TanStack Form and Zod?
TanStack Form connects typed field state, validation, and submission without dictating the visual components. Zod lets the client and server use the same input rules. This makes it straightforward to build consistent forms with the kit's Kumo controls.
Form state
TanStack Form manages field values, validation results, and submission state. Your interface supplies the controls and chooses how to present that state.
Keep form state close to the interaction that owns it. A dialog can create a resource, while a settings page can edit an existing one. Share a repeated field or layout when it makes the product consistent, without forcing every form into the same large component.
For an edit form, load the current values before treating them as the customer's starting point. Be deliberate about resetting values after a background refresh so a new server result does not unexpectedly replace an unfinished edit.
Validation
Zod describes the values an operation accepts: required fields, valid formats, length limits, and related constraints. The same schema can help provide client feedback and validate the request on the server.
The two checks serve different purposes:
- Client validation helps the customer correct a field before submission.
- Server validation protects the operation when a caller bypasses the form or sends a direct request.
For example, a note form can describe its accepted input with a small schema:
import { z } from "zod";
const noteSchema = z.object({
title: z.string().trim().min(1).max(120),
});This accepts a title after trimming surrounding whitespace and rejects empty or overly long values. Use the same schema at the server boundary; the form's validation alone cannot protect the operation.
| Rule | Example |
|---|---|
| Required value | A resource needs a non-empty title |
| Format | A contact address must be a valid email |
| Length | A message must fit the product's allowed size |
| Relationship | A selected option must be valid for another field |
| Business policy | The customer must be allowed to create the resource |
Business policies such as record ownership and plan limits belong in the server operation. A valid title does not establish that the customer may rename the requested document. Protected calls covers that boundary.
Field feedback
Place a specific validation message next to the field it describes. Keep the label visible, use an appropriate input type, and connect the error to the control so keyboard and assistive-technology users receive the same information.
Choose when feedback appears around the interaction. Validation on submission can keep a short form calm, while feedback after a field is touched can help with longer forms. Avoid showing a wall of errors before the customer has entered anything.
The included Kumo inputs expose labels, error messages, and disabled states. Reuse these supported patterns when adding new controls, and test the form with a keyboard as well as a pointer.
Submission
A form submits through the server function or integration responsible for the action. While it is pending, show progress and prevent an accidental second submission where it could duplicate the operation.
Inside a form component, connect the schema to submission like this. Here, saveNote represents the protected server function you add for your feature:
import { useForm } from "@tanstack/react-form";
const form = useForm({
defaultValues: { title: "" },
validators: { onSubmit: noteSchema },
onSubmit: async ({ value }) => {
await saveNote({ data: value });
},
});The surrounding controls use the form's values, errors, and submission state. Add the completion behavior that fits your screen after the save succeeds.
After success, decide what completion means for this interaction:
- A contact form can show confirmation and clear its fields.
- A settings form can retain the saved values and indicate completion.
- A creation dialog can close after the new item is available in the list.
- A multi-step flow can move to the next step while retaining the state needed there.
Refresh the affected data before presenting the final saved view. Data fetching explains query and route refreshes.
On failure, preserve useful input so the customer can recover. Distinguish a field problem from a service failure, and give an expired session a sign-in path instead of repeatedly retrying a rejected operation.
Public forms
The contact form demonstrates a public operation protected by Cloudflare Turnstile. Its browser challenge and server verification are connected before email delivery.
Use that pattern for public interactions exposed to automated abuse. Private product forms additionally need the customer's session and the relevant ownership or plan rules. A bot check and authentication answer different questions.
Keep recipient addresses and provider credentials on the server. The customer supplies the message; your product controls where the message is delivered.
Language and presentation
Form labels, placeholders, help text, buttons, and confirmation messages belong in the translation catalogs. The kit also connects localized validation messages, so errors can match the rest of the interface.
Use placeholders for examples, not as the only field label. Allow room for longer translations and messages on smaller screens. An error should remain readable without changing the form's layout so much that the customer loses their place.
Reference flows
The authentication forms demonstrate password inputs, verification feedback, and redirects. Account settings demonstrate edits to existing customer data. The contact form demonstrates a public submission with bot verification, email delivery, and confirmation.
Choose the closest of these patterns for a new form, then adapt its fields and outcome to your feature. The feature recipe connects a new input flow to customer-owned data end to end.
How is this guide?
Last updated on