Validation With Zod

Type-Safe Parsing in Your Server Action

Validation With Zod

Zod schemas validate `FormData` on the server, returning either fully typed data or a map of per-field errors you can render in the form.

4 min read Level 3/5 #nextjs#validation#zod
What you'll learn
  • Define a Zod schema for the form's shape
  • Parse `FormData` with `safeParse`
  • Return field-level errors to the client

Form data arrives as strings. Zod parses, coerces, and validates it in one step, and its type inference becomes the action’s payload type.

Define the Schema

import { z } from 'zod'

export const signupSchema = z.object({
  email: z.string().email('Enter a valid email'),
  age: z.coerce.number().int().min(18, 'Must be 18 or older'),
  password: z.string().min(8, 'At least 8 characters'),
})

z.coerce.number() is critical: FormData values are always strings, so a plain z.number() would always fail.

Parse Inside the Action

'use server'
import { signupSchema } from './schema'

type State = { errors?: Record<string, string[]>; ok?: boolean }

export async function signup(prev: State, form: FormData): Promise<State> {
  const parsed = signupSchema.safeParse(Object.fromEntries(form))
  if (!parsed.success) {
    return { errors: parsed.error.flatten().fieldErrors }
  }
  await db.users.create(parsed.data) // parsed.data is fully typed
  return { ok: true }
}

safeParse returns { success: false, error } rather than throwing — which is what you want here, because validation failures are expected, not exceptional.

Render the Errors

'use client'
import { useActionState } from 'react'
import { signup } from './actions'

export function SignupForm() {
  const [state, action] = useActionState(signup, {})
  return (
    <form action={action}>
      <input name="email" />
      {state.errors?.email?.[0] && <p className="error">{state.errors.email[0]}</p>}
      <input name="age" />
      {state.errors?.age?.[0] && <p className="error">{state.errors.age[0]}</p>}
      <button>Sign up</button>
    </form>
  )
}
Progressive Enhancement →