Generate Zod validation schemas from Prisma models, TypeScript interfaces, or JSON examples. Use when asked to generate Zod schemas, create validation, bridge Prisma to Zod, validate API input/output, or generate runtime type checks.
Before generating any output, read config/defaults.md and adapt all patterns, imports, and code examples to the user's configured stack.
.transform() and .refine() where appropriate.Parse the Prisma model and generate both input and output schemas.
Omit auto-generated fields (id, createdAt, updatedAt) and fields with @default.
model User {
id String @id @default(cuid())
email String @unique
name String?
role Role @default(USER)
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// Generated: user.schema.ts
import { z } from "zod";
export const createUserSchema = z.object({
email: z.string().email().trim().toLowerCase(),
name: z.string().min(1).trim().optional(),
role: z.enum(["USER", "ADMIN"]).optional(), // has @default
});
export const updateUserSchema = createUserSchema.partial();
export type CreateUserInput = z.infer<typeof createUserSchema>;
export type UpdateUserInput = z.infer<typeof updateUserSchema>;
Include all fields. Use z.coerce.date() for DateTime fields.
export const userSchema = z.object({
id: z.string().cuid(),
email: z.string().email(),
name: z.string().nullable(),
role: z.enum(["USER", "ADMIN"]),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
});
export type User = z.infer<typeof userSchema>;
For input schemas, generate nested create/connect patterns:
// One-to-many: creating a post with author
export const createPostSchema = z.object({
title: z.string().min(1).max(255),
content: z.string(),
author: z.union([
z.object({ connect: z.object({ id: z.string() }) }),
z.object({ create: createUserSchema }),
]),
});
For output schemas, include the related object shape:
export const postWithAuthorSchema = postSchema.extend({
author: userSchema,
});
Map TypeScript types directly to Zod equivalents.
// Input
interface OrderItem {
productId: string;
quantity: number;
price: number;
notes?: string;
metadata: Record<string, unknown>;
}
// Generated
export const orderItemSchema = z.object({
productId: z.string().uuid(),
quantity: z.number().int().positive(),
price: z.number().nonnegative(),
notes: z.string().optional(),
metadata: z.record(z.string(), z.unknown()),
});
// Input
type PaymentMethod =
| { type: "card"; cardNumber: string; expiry: string }
| { type: "bank"; accountNumber: string; routingNumber: string }
| { type: "crypto"; walletAddress: string };
// Generated
export const paymentMethodSchema = z.discriminatedUnion("type", [
z.object({
type: z.literal("card"),
cardNumber: z.string().regex(/^\d{16}$/),
expiry: z.string().regex(/^\d{2}\/\d{2}$/),
}),
z.object({
type: z.literal("bank"),
accountNumber: z.string(),
routingNumber: z.string().regex(/^\d{9}$/),
}),
z.object({
type: z.literal("crypto"),
walletAddress: z.string().min(26).max(62),
}),
]);
Infer schema from a JSON payload by analyzing value types and structure.
{
"name": "Acme Corp",
"employees": 150,
"active": true,
"tags": ["tech", "startup"],
"address": {
"street": "123 Main St",
"city": "Springfield",
"zip": "62701"
}
}
// Generated (with refinement suggestions in comments)
export const companySchema = z.object({
name: z.string().min(1),
employees: z.number().int().nonnegative(),
active: z.boolean(),
tags: z.array(z.string()),
address: z.object({
street: z.string(),
city: z.string(),
zip: z.string().regex(/^\d{5}(-\d{4})?$/), // inferred US zip
}),
});
Apply these automatically when field names or patterns suggest them:
| Field pattern | Refinement |
|---|---|
| email | .email().trim().toLowerCase() |
| url, website | .url() |
| id, *Id (cuid) | .cuid() or .cuid2() |
| uuid, *Uuid | .uuid() |
| phone | .regex(/^\+?[\d\s-()]+$/) |
| password | .min(8) |
| *At (timestamps) | z.coerce.date() |
| slug | .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/) |
| price, amount | .nonnegative() |
| quantity, count | .int().nonnegative() |
app/api/users/schema.ts).lib/validations/ or src/schemas/ when schemas are shared across multiple routes.Match the project's existing pattern. Default to colocated if no convention exists.
## Generated Zod Schema
**Source**: [Prisma model | TypeScript interface | JSON example]
**File**: `path/to/schema.ts`
[Generated code block]
### Refinements Applied
- `email`: Added `.email().trim().toLowerCase()`
- `createdAt`: Used `z.coerce.date()` for DateTime
### Usage Example
[Short example showing schema.parse() or schema.safeParse()]
See references/prisma-zod-mapping.md for the complete Prisma-to-Zod type mapping table and refinement catalog.
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer