| name | forms |
| description | Form validation, multi-step forms, React Hook Form with Zod, server actions, and accessible form patterns |
| layer | domain |
| category | frontend |
| triggers | ["form","form validation","multi-step form","react hook form","zod schema","form builder","input validation"] |
| inputs | [{"requirements":"Form fields, validation rules, submission behavior"},{"framework":"React Hook Form | Formik | native (optional, defaults to RHF)"},{"validation":"Zod | Yup | native (optional, defaults to Zod)"},{"features":"Multi-step, file upload, conditional fields, server validation"}] |
| outputs | [{"form_component":"Complete form implementation with validation"},{"schema":"Zod/Yup validation schema"},{"types":"TypeScript types inferred from schema"},{"server_action":"Server-side validation and submission handler"}] |
| linksTo | ["react","nextjs","tailwindcss","ui-ux-pro","api-designer"] |
| linkedFrom | ["cook","react","nextjs"] |
| preferredNextSkills | ["react","api-designer"] |
| fallbackSkills | ["ui-ux-pro"] |
| riskLevel | low |
| memoryReadPolicy | selective |
| memoryWritePolicy | none |
| sideEffects | [] |
Forms Skill
Purpose
Build accessible, validated, performant forms using React Hook Form and Zod. This skill covers single-page and multi-step forms, client-side and server-side validation, file uploads, dynamic/conditional fields, and optimistic form submissions. Forms are the primary way users input data -- they must be correct, accessible, and pleasant to use.
Key Concepts
Form Architecture
CLIENT VALIDATION (fast feedback):
Zod schema validates on change/blur
React Hook Form manages state and re-renders
Errors displayed inline next to fields
SERVER VALIDATION (source of truth):
Server action or API route validates again
Business logic validation (uniqueness, permissions)
Returns field-level errors for display
PRINCIPLE: Validate on client for UX, validate on server for security.
Never trust client-side validation alone.
Zod Schema Design
import { z } from 'zod';
export const registerSchema = z.object({
email: z
.string()
.min(1, 'Email is required')
.email('Please enter a valid email address'),
password: z
.string()
.min(8, 'Password must be at least 8 characters')
.regex(/[A-Z]/, 'Password must contain an uppercase letter')
.regex(/[0-9]/, 'Password must contain a number'),
confirmPassword: z.string(),
name: z
.string()
.min(2, 'Name must be at least 2 characters')
.(, ),
: z.(, {
: ({ : }),
}),
}).( data. === data., {
: ,
: [],
});
= z.< registerSchema>;