
zod-schema-creation
by teocrafters
SKILL.md
name: zod-schema-creation description: Guide through creating Zod validation schemas with i18n integration for API request validation. Use when creating API endpoints that need validation.
Zod Validation Schema Creation Skill
Guides through creating Zod validation schemas with i18n integration for API request validation.
Purpose
USE this skill when:
- Creating new API endpoints that accept request bodies
- Adding validation for POST, PUT, or PATCH requests
- Implementing form validation schemas
Critical Rules
⚠️ Factory pattern REQUIRED - Schemas must accept translation function t: (key: string) => string
⚠️ i18n keys in errors - All error messages use translation keys, not hardcoded text
⚠️ File organization - All schemas in shared/utils/schemas/ directory
⚠️ Type export - Always export TypeScript type using z.infer<ReturnType<...>>
Workflow Steps
Step 1: Identify Validation Requirements
- What fields are required/optional?
- What validation rules apply?
- Creating (create schema) or updating (update schema)?
Step 2: Create Schema File
Location: shared/utils/schemas/{resource}.ts
Step 3: Implement Factory Function Pattern
import { z } from "zod"
export function createSpeakerSchema(t: (key: string) => string) {
return z.object({
firstName: z
.string()
.min(1, t("validation.firstNameRequired"))
.max(100, t("validation.firstNameTooLong")),
lastName: z
.string()
.min(1, t("validation.lastNameRequired"))
.max(100),
email: z
.string()
.email(t("validation.emailInvalid"))
.optional(),
})
}
Step 4: Export TypeScript Type
export type CreateSpeakerInput = z.infer<ReturnType<typeof createSpeakerSchema>>
Step 5: Create Update Schema (If Needed)
export function updateSpeakerSchema(t: (key: string) => string) {
return createSpeakerSchema(t).partial()
}
export type UpdateSpeakerInput = z.infer<ReturnType<typeof updateSpeakerSchema>>
Step 6: Update Barrel File
Add to shared/utils/schemas/index.ts:
export * from "./speaker"
Step 7: Add Translation Keys
Use i18n-key-validation skill to ensure keys exist in both pl.json and en.json
Step 8: Implement in API Route
import { createSpeakerSchema } from "#shared/utils/schemas"
export default defineEventHandler(async (event) => {
const body = await validateBody(event, createSpeakerSchema)
// body is now typed and validated
const db = useDrizzle()
const [speaker] = await db.insert(tables.speakers)
.values({
id: crypto.randomUUID(),
...body,
createdAt: new Date(),
updatedAt: new Date(),
})
.returning()
return speaker
})
Common Validation Patterns
// String with length
field: z.string().min(1, t("validation.required")).max(200)
// Email
email: z.string().email(t("validation.emailInvalid")).optional()
// Number
age: z.number().min(0).max(150)
// Enum
status: z.enum(["active", "archived"])
// Array
tags: z.array(z.string()).max(10)
Anti-Patterns
❌ Hardcoded error messages ❌ No factory pattern ❌ Wrong file location ❌ Missing type export
References
- Backend guidelines:
server/AGENTS.md - i18n patterns:
.agents/i18n-patterns.md
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon