Skip to main content
skill CX Codex

zod-validation-utilities — Claude Code skill

Guides Zod v4 validation for TypeScript APIs, forms, and configuration. Use it when external input needs parsing, coercion, and clear validation errors.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add giuseppe-trisciuoglio/developer-kit --skill zod-validation-utilities -a claude-code
Open on GitHub

What zod-validation-utilities does

This skill lays out reusable Zod v4 patterns for primitives, object schemas, arrays, tuples, and discriminated unions. It places validation at application boundaries such as HTTP handlers, queues, and configuration loaders.

It uses z.coerce.* when incoming types are uncertain, while transform, refine, and superRefine keep data changes and cross-field checks near the schema. A safeParse flow branches on result.success, then returns formatted errors or typed result.data. Schemas can export matching z.input and z.output types.

The material also covers React Hook Form through zodResolver. Check the installed Zod major version first: the shown APIs target v4, so copying them into an older dependency is a risk.

What it helps with

  • validate an API request body against a schema
  • coerce query strings into numbers and dates
  • format validation failures from safeParse
  • compare related password fields with superRefine
  • connect a Zod schema to React Hook Form

Example prompts for the agent

  • "Create a Zod v4 schema for this API request body and handle errors with safeParse."
  • "Add z.coerce.* for pagination parameters and export z.input and z.output."
  • "Wire this schema into a React Hook Form form using zodResolver."

How to install zod-validation-utilities

1Skills CLI (Vercel)

npx skills add giuseppe-trisciuoglio/developer-kit --skill zod-validation-utilities -a claude-code

2Manually: put the files in place

~/.claude/skills/zod-validation-utilities/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/zod-validation-utilities/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about zod-validation-utilities

How do I install zod-validation-utilities in Claude Code?

Run npx skills add giuseppe-trisciuoglio/developer-kit --skill zod-validation-utilities -a claude-code.

What does zod-validation-utilities do?

It provides Zod v4 patterns for validating API payloads, forms, and configuration input. It covers coercion, transformations, cross-field checks, and safeParse error handling.

What should I check before using its examples?

The examples use Zod v4 APIs. Coercion can conceal bad upstream values, so add bounds and refinements around z.coerce.* where needed.

Source text

SKILL.md · MIT
---
name: zod-validation-utilities
description: Creates reusable Zod v4 schemas, validates API payloads, forms, and configuration input, transforms and coerces data safely, and handles validation errors with strong type inference for TypeScript applications. Use when designing validation layers, parsing `z.string()`, `z.object()`, or `z.email()` schemas, or implementing runtime type-safe data validation.
allowed-tools: Read, Write, Edit, Bash, Grep, Glob
---

# Zod Validation Utilities

## Overview

Production-ready Zod v4 patterns for reusable, type-safe validation with minimal boilerplate. Focuses on modern APIs, predictable error handling, and form integration.

## When to Use

- Defining request/response validation schemas in TypeScript services
- Parsing untrusted input from APIs, forms, env vars, or external systems
- Standardizing coercion, transforms, and cross-field validation
- Building reusable schema utilities across teams
- Integrating React Hook Form with Zod using `zodResolver`

## Instructions

1. Start with strict object schemas and explicit field constraints
2. Prefer modern Zod v4 APIs and the `error` option for error messages
3. Use coercion at boundaries (`z.coerce.*`) when input types are uncertain
4. Keep business invariants in `refine`/`superRefine` close to schema definitions
5. Export both schema and inferred types (`z.input`/`z.output`) for consistency
6. Reuse utility schemas (email, id, dates, pagination) to reduce duplication

## Validation Workflow

When integrating validation into an API handler or service:

1. **Define** the schema at the boundary (handler, queue, config loader)
2. **Parse** with `safeParse` to handle errors gracefully
3. **Check** `result.success` to branch on failure/success
4. **Use** `result.data` with full type inference in success path
5. **Return** formatted errors or proceed with validated data

See example 7 (`safeParse` workflow) for the complete pattern.

## Examples

### 1) Modern Zod 4 primitives and object errors

```ts
import { z } from "zod";

export const UserIdSchema = z.uuid({ error: "Invalid user id" });
export const EmailSchema = z.email({ error: "Invalid email" });
export const WebsiteSchema = z.url({ error: "Invalid URL" });

export const UserProfileSchema = z.object(
  {
    id: UserIdSchema,
    email: EmailSchema,
    website: WebsiteSchema.optional(),
  },
  { error: "Invalid user profile payload" }
);
```

### 2) Coercion, preprocess, and transform

```ts
import { z } from "zod";

export const PaginationQuerySchema = z.object({
  page: z.coerce.number().int().min(1).default(1),
  pageSize: z.coerce.number().int().min(1).max(100).default(20),
  includeArchived: z.coerce.boolean().default(false),
});

export const DateFromUnknownSchema = z.preprocess(
  (value) => (typeof value === "string" || value instanceof Date ? value : undefined),
  z.coerce.date({ error: "Invalid date" })
);

export const NormalizedEmailSchema = z
  .string()
  .trim()
  .toLowerCase()
  .email({ error: "Invalid email" })
  .transform((value) => value as Lowercase<string>);
```

### 3) Complex schema structures

```ts
import { z } from "zod";

const TagSchema = z.string().trim().min(1).max(40);

export const ProductSchema = z.object({
  sku: z.string().min(3).max(24),
  tags: z.array(TagSchema).max(15),
  attributes: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])),
  dimensions: z.tuple([z.number().positive(), z.number().positive(), z.number().positive()]),
});

export const PaymentMethodSchema = z.discriminatedUnion("type", [
  z.object({ type: z.literal("card"), last4: z.string().regex(/^\d{4}$/) }),
  z.object({ type: z.literal("paypal"), email: z.email() }),
  z.object({ type: z.literal("wire"), iban: z.string().min(10) }),
]);
```

### 4) `refine` and `superRefine`

```ts
import { z } from "zod";

export const PasswordSchema = z
  .string()
  .min(12)
  .refine((v) => /[A-Z]/.test(v), { error: "Must include an uppercase letter" })
  .refine((v) => /\d/.test(v), { error: "Must include a number" });

export const RegisterSchema = z
  .object({
    email: z.email(),
    password: PasswordSchema,
    confirmPassword: z.string(),
  })
  .superRefine((data, ctx) => {
    if (data.password !== data.confirmPassword) {
      ctx.addIssue({
        code: "custom",
        path: ["confirmPassword"],
        message: "Passwords do not match",
      });
    }
  });
```

### 5) Optional, nullable, nullish, and default

```ts
import { z } from "zod";

export const UserPreferencesSchema = z.object({
  nickname: z.string().min(2).optional(),      // undefined allowed
  bio: z.string().max(280).nullable(),         // null allowed
  avatarUrl: z.url().nullish(),                // null or undefined allowed
  locale: z.string().default("en"),           // fallback when missing
});
```

### 6) React Hook Form integration (`zodResolver`)

```tsx
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";

const ProfileFormSchema = z.object({
  name: z.string().min(2, { error: "Name too short" }),
  email: z.email({ error: "Invalid email" }),
  age: z.coerce.number().int().min(18),
});

type ProfileFormInput = z.input<typeof ProfileFormSchema>;
type ProfileFormOutput = z.output<typeof ProfileFormSchema>;

const form = useForm<ProfileFormInput, unknown, ProfileFormOutput>({
  resolver: zodResolver(ProfileFormSchema),
  criteriaMode: "all",
});
```

### 7) Error handling workflow with `safeParse`

```ts
import { z } from "zod";
import type { ZodError } from "zod";

const ResultSchema = z.object({ id: z.string(), name: z.string() });

function parseAndHandle(input: unknown) {
  const result = ResultSchema.safeParse(input);

  if (!result.success) {
    const error = result.error as ZodError;
    console.error("Validation failed:", error.errors);
    return { success: false as const, error: error.format() };
  }

  return { success: true as const, data: result.data };
}
```

> **Tip**: For advanced discriminated union patterns and complex React Hook Form workflows, see `references/advanced-patterns.md`.

## Best Practices

- Keep schemas near boundaries (HTTP handlers, queues, config loaders)
- Prefer `safeParse` for recoverable flows; `parse` for fail-fast execution
- Share small schema utilities (`id`, `email`, `slug`) to enforce consistency
- Use `z.input` and `z.output` when transforms/coercions change runtime shape
- Avoid overusing `preprocess`; prefer explicit `z.coerce.*` where possible
- Treat external payloads as untrusted and always validate before use

## Constraints and Warnings

- Ensure examples match your installed `zod` major version (v4 APIs shown)
- `error` is the preferred option for custom errors in Zod v4 patterns
- Discriminated unions require a stable discriminator key across variants
- Coercion can hide bad upstream data; add bounds and refinements defensively

© giuseppe-trisciuoglio · MIT · giuseppe-trisciuoglio/developer-kit

Similar skills

Everything for Backend and APIs →

From the same set93

spring-boot-resilience4j Generates Resilience4j fault tolerance patterns for Spring Boot 3.x projects. Use it to configure circuit breakers and retry logic. CX Codex +1 3,800installs unit-test-service-layer A skill that gives the agent a Mockito pattern for service-layer unit tests: mock repositories, verify calls, cover exception paths. CX Codex +1 3,800installs nestjs-best-practices A skill that hands your agent a rulebook for NestJS: module boundaries, provider scopes, exception filters, DTO validation and Drizzle ORM. CX Codex +1 3,800installs spring-boot-cache Configures caching in Spring Boot services using Caffeine, Redis, or Ehcache providers. Helps set up TTL policies, apply cache annotations, and trace cache misses. CX Codex +1 3,800installs spring-boot-event-driven-patterns A Spring Boot 3.x skill for domain events, @TransactionalEventListener, Kafka messaging and the transactional outbox pattern. Useful when sync calls between services need to become events. CX Codex +1 3,800installs chunking-strategy Configures document chunking workflows and overlap for RAG pipelines and vector search. It validates semantic coherence and tunes retrieval precision. CX Codex +1 3,800installs aws-sdk-java-v2-rds Guides AI agents in managing Amazon RDS databases via the AWS SDK for Java 2.x. Useful for provisioning instances, snapshots, and parameter groups. CX Codex +1 3,700installs aws-sdk-java-v2-kms This skill provides AWS KMS patterns for AWS SDK for Java 2.x, covering keys, encryption, data keys, signatures, and Spring Boot integration. CX Codex +1 3,700installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor