Why Zod?
Zod provides runtime validation with TypeScript type inference. Define a schema once, get both validation and types.
Basic Pattern
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters'),
name: z.string().min(2, 'Name is required'),
role: z.enum(['CLIENT', 'DEVELOPER', 'MANAGER']),
});
// TypeScript type is inferred
type CreateUserInput = z.infer<typeof createUserSchema>;
API Validation
Every API endpoint validates input before processing:
export async function POST(request: NextRequest) {
const body = await request.json();
const validation = createUserSchema.safeParse(body);
if (!validation.success) {
return NextResponse.json(
{ error: 'Invalid input', details: validation.error.flatten() },
{ status: 400 }
);
}
// validation.data is fully typed
const user = await createUser(validation.data);
return NextResponse.json({ user });
}
Client-Side Integration
We use React Hook Form with Zod resolver for form validation:
const form = useForm<CreateUserInput>({
resolver: zodResolver(createUserSchema),
defaultValues: { email: '', password: '', name: '', role: 'CLIENT' },
});
Benefits
- Single source of truth for validation rules
- Type-safe across client and server
- Detailed error messages for users



