zod/SKILL.md
Zod — TypeScript-first schema validation with static type inference. Use when building with Zod or asking about schema definitions, type inference, parsing, transformations, refinements, coercion, error handling, or integration with forms, APIs, or tRPC. Fetch live documentation for up-to-date details.
npx skillsauth add mikkelkrogsholm/dev-skills zodInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
CRITICAL: Your training data for Zod is unreliable. APIs change between versions and memorized patterns may be wrong or deprecated. Before writing any code, you MUST use
WebFetchto read the live docs:
WebFetch("https://zod.dev/llms.txt")Do not proceed without fetching this URL first. Never assume an API exists — verify against current docs.
Zod is a TypeScript-first schema validation library with automatic static type inference. Define a schema once and get both runtime validation and compile-time types from the same source.
Version note: These best practices target Zod v4 (stable, installed via
npm install zod). The top-level error utilities (z.flattenError(),z.prettifyError(),z.treeifyError()) are v4-only — in v3 these were instance methods (error.flatten()). See the migration guide when upgrading.
Zod has built-ins for things developers commonly reach for external packages to handle:
z.coerce.number() / z.coerce.string() etc. to automatically cast inputs (e.g. form strings to numbers) — no manual casting step required.transform() on any schema converts parsed values in one step — no need for a separate transformation layerz.treeifyError(), z.prettifyError(), or z.flattenError() to format ZodError into user-friendly shapes — no custom error mappers neededz.pipe() and the codec pattern (encode + decode) handle round-trip transformations (e.g. stringToNumber, base64ToBytes) without external codec libraries.safeParse() over .parse() in application code. .parse() throws a ZodError on invalid input; .safeParse() returns { success, data, error } and lets you handle failure without try/catch. Reserve .parse() only where an unhandled throw is intentional (e.g. startup config validation).z.infer<typeof MySchema> to derive TypeScript types — do not write a separate interface and then try to match a schema to it. Keeping the schema as the single source of truth prevents drift..transform() changes the output type invisibly. After a .transform(), the schema's output type differs from its input type. Calling .parse() gives the transformed value, but .safeParse().data also reflects the transform. Passing a transformed schema where an unmodified type is expected is a common source of subtle type errors..superRefine() instead of multiple chained .refine() calls when issues must be cross-field. Each .refine() adds a separate validation pass; .superRefine() gives you access to the full ctx so you can attach multiple issues with precise paths in one pass, which produces more precise error messages on objects..refine() to a schema that also has a .transform(), the refinement receives the transformed (output) value, not the raw input. This is non-obvious when migrating from Joi or Yup, where refinements typically operate on raw input.z.coerce.* converts null to 0 and undefined to NaN. z.coerce.number() will coerce null → 0 and undefined → NaN rather than failing validation. For optional form fields where empty should mean absent (not zero), use z.preprocess() instead of z.coerce.tools
Vite — next-generation frontend build tool with instant dev server and optimized production builds. Use when building with Vite or asking about its APIs, configuration, plugins, SSR, environment variables, or integration with frameworks. Fetch live documentation for up-to-date details.
tools
Upstash — serverless Redis, QStash, and Vector database with per-request pricing optimized for edge and serverless environments. Use when building with Upstash or asking about its Redis client, QStash message queuing, rate limiting, workflows, or vector search. Fetch live documentation for up-to-date details.
tools
Turso — edge-hosted SQLite database built on libSQL with embedded replicas, multi-tenancy, and low-latency global distribution. Use when building with Turso or asking about its libSQL client, embedded replicas, database-per-tenant patterns, auth tokens, sync, or integration with Drizzle or other ORMs. Fetch live documentation for up-to-date details.
development
tRPC — end-to-end typesafe APIs for TypeScript without schemas or code generation. Use when building with tRPC or asking about its router setup, procedures, middleware, context, subscriptions, or integration with React, Next.js, or other frameworks. Fetch live documentation for up-to-date details.