Next.js Server Action with Zod Validation
A complete server action pattern: Zod validation, error handling, and revalidation.
#next.js#typescript#zod#forms
typescript
'use server';
import { z } from 'zod';
import { revalidatePath } from 'next/cache';
import { db } from '@/app/db/drizzle';
import { projects } from '@/app/db/schema';
const CreateProjectSchema = z.object({
title: z.string().min(3).max(255),
description: z.string().min(10),
technologies: z.array(z.string()).min(1),
});
type FormState = {
success: boolean;
errors?: Record<string, string[]>;
message?: string;
};
export async function createProject(
prevState: FormState,
formData: FormData
): Promise<FormState> {
const raw = {
title: formData.get('title'),
description: formData.get('description'),
technologies: formData.getAll('technologies'),
};
const parsed = CreateProjectSchema.safeParse(raw);
if (!parsed.success) {
return {
success: false,
errors: parsed.error.flatten().fieldErrors,
};
}
await db.insert(projects).values({
...parsed.data,
slug: parsed.data.title.toLowerCase().replace(/s+/g, '-'),
});
revalidatePath('/projects');
return { success: true, message: 'Project created!' };
}