Client-side validation improves UX, but server-side validation is essential for security. Never trust data from the client.
The Golden Rule
Always validate on the server. Client-side validation can be bypassed by anyone with browser DevTools.
Using Zod for Validation
// app/api/users/route.ts
import { z } from "zod";
const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
age: z.number().int().min(13).max(120).optional(),
});
export async function POST(request: Request) {
const body = await request.json();
const result = createUserSchema.safeParse(body);
if (!result.success) {
return Response.json(
{ error: "Validation failed", details: result.error.issues },
{ status: 400 }
);
}
// result.data is now typed and validated
const { email, name, age } = result.data;
// ...
}Form Actions Validation
// app/actions.ts
"use server";
import { z } from "zod";
const schema = z.object({
title: z.string().min(1).max(200),
content: z.string().min(10),
});
export async function createPost(formData: FormData) {
const result = schema.safeParse({
title: formData.get("title"),
content: formData.get("content"),
});
if (!result.success) {
return { error: result.error.flatten() };
}
// Safe to use result.data
}What to Validate
- Data types (string, number, boolean)
- Required fields
- String lengths and formats (email, URL, etc.)
- Number ranges
- Enum values
- Object shapes and nested structures
- Array lengths and item types
What VibeCheck Detects
- VC-VAL-001: Missing server-side validation
- VC-VAL-002: Client-only validation patterns
- VC-INJ-001: SQL injection vulnerabilities