create-schema
About
This skill generates Zod schemas with TypeScript types for new backend entities. It creates validation schemas, DTOs (Create/Update types), and entity definitions when you're adding resources or data models. The output follows project conventions with proper file structure and includes ID schemas, base entities, and CRUD variants.
Quick Install
Claude Code
Recommended/plugin add https://github.com/majiayu000/claude-skill-registrygit clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/create-schemaCopy and paste this command in Claude Code to install this skill
Documentation
Create Schema
Creates Zod schemas with TypeScript type inference for new entities in this backend template.
Quick Reference
Location: src/schemas/{entity-name}.schema.ts
Naming: Singular, kebab-case (e.g., note.schema.ts, course-registration.schema.ts)
Instructions
Step 1: Create the Schema File
Create a new file at src/schemas/{entity-name}.schema.ts
Step 2: Define the Entity ID Schema
Always start with a dedicated ID schema:
import { z } from "zod";
export const {entity}IdSchema = z.string();
export type {Entity}IdType = z.infer<typeof {entity}IdSchema>;
Step 3: Define the Base Entity Schema
export const {entity}Schema = z.object({
id: {entity}IdSchema, // Primary key
// ... entity-specific fields ...
createdBy: userIdSchema, // If entity is user-owned (import from user.schemas)
createdAt: z.date().optional(), // Set by DB/service
updatedAt: z.date().optional(), // Set by DB/service
});
export type {Entity}Type = z.infer<typeof {entity}Schema>;
Step 4: Define Create DTO Schema
Omit system-managed fields and add validation:
export const create{Entity}Schema = {entity}Schema
.omit({
id: true, // Generated by service/system
createdBy: true, // Set from authenticated user context
createdAt: true, // Set by service/database
updatedAt: true, // Set by service/database
})
.extend({
// Add stricter validation for required fields
fieldName: z.string().min(1, "{Entity} field is required for creation."),
});
export type Create{Entity}Type = z.infer<typeof create{Entity}Schema>;
Step 5: Define Update DTO Schema
Make all mutable fields optional:
export const update{Entity}Schema = {entity}Schema
.omit({
id: true, // Part of URL, not body
createdBy: true, // Immutable
createdAt: true, // Immutable
updatedAt: true, // Set by service/database
})
.partial(); // All fields optional for updates
export type Update{Entity}Type = z.infer<typeof update{Entity}Schema>;
Step 6: Define Query Parameters Schema (if needed)
Extend the base query params for filtering:
import { queryParamsSchema } from "./shared.schema";
export const {entity}QueryParamsSchema = queryParamsSchema.extend({
// Entity-specific filters
createdBy: userIdSchema.optional(),
status: z.enum(["active", "inactive"]).optional(),
});
export type {Entity}QueryParamsType = z.infer<typeof {entity}QueryParamsSchema>;
Patterns & Rules
Naming Conventions
- File name:
{entity-name}.schema.ts(singular, kebab-case) - Schema variables:
{entity}Schema,create{Entity}Schema(camelCase) - Type names:
{Entity}Type,Create{Entity}Type(PascalCase)
Import Rules
- Always use path aliases:
import { x } from "@/schemas/..." - Import shared schemas from
./shared.schema - Import user-related schemas from
./user.schemaswhen needed
Schema Design Rules
- Always export both schema and type for each definition
- ID schemas are separate - allows reuse and type narrowing
- Timestamps are optional on the base schema (not present on creation)
- Create schemas omit system-managed fields (id, createdBy, timestamps)
- Update schemas are partial - all fields optional
- Extend base queryParamsSchema for entity-specific filters
Validation Guidelines
- Add
.min(1)for required string fields in create schemas - Use
.optional()for truly optional fields - Use
z.coerce.number()for numeric query params (they come as strings) - Add descriptive error messages:
z.string().min(1, "Field is required")
Cross-Reference Pattern
When referencing other entities:
import { userIdSchema } from "./user.schemas";
import { otherEntityIdSchema } from "./other-entity.schema";
export const myEntitySchema = z.object({
id: myEntityIdSchema,
ownerId: userIdSchema, // Reference to user
relatedId: otherEntityIdSchema, // Reference to another entity
});
Complete Example
See src/schemas/note.schema.ts for a complete reference implementation.
import { z } from "zod";
import { queryParamsSchema } from "./shared.schema";
import { userIdSchema } from "./user.schemas";
// ID Schema
export const noteIdSchema = z.string();
export type NoteIdType = z.infer<typeof noteIdSchema>;
// Base Entity Schema
export const noteSchema = z.object({
id: noteIdSchema,
content: z.string(),
createdBy: userIdSchema,
createdAt: z.date().optional(),
updatedAt: z.date().optional(),
});
export type NoteType = z.infer<typeof noteSchema>;
// Create DTO
export const createNoteSchema = noteSchema
.omit({
id: true,
createdBy: true,
createdAt: true,
updatedAt: true,
})
.extend({
content: z.string().min(1, "Note content is required for creation."),
});
export type CreateNoteType = z.infer<typeof createNoteSchema>;
// Update DTO
export const updateNoteSchema = noteSchema
.omit({
id: true,
createdBy: true,
createdAt: true,
updatedAt: true,
})
.partial();
export type UpdateNoteType = z.infer<typeof updateNoteSchema>;
// Query Parameters
export const noteQueryParamsSchema = queryParamsSchema.extend({
createdBy: userIdSchema.optional(),
});
export type NoteQueryParamsType = z.infer<typeof noteQueryParamsSchema>;
Shared Schemas Reference
The following are available from @/schemas/shared.schema:
queryParamsSchema- Base pagination/sorting params (search, sortBy, sortOrder, page, limit)paginatedResultsSchema(dataSchema)- Generic paginated response wrapperentityIdParamSchema(paramName)- URL path parameter validationDEFAULT_PAGE,DEFAULT_LIMIT- Pagination defaults
What NOT to Do
- Do NOT use
process.env- environment config belongs insrc/env.ts - Do NOT create barrel exports (index.ts) - use explicit imports
- Do NOT use plural names (
notes.schema.ts) - use singular (note.schema.ts) - Do NOT define business logic in schemas - schemas are for structure/validation only
- Do NOT skip type exports - always export both schema and inferred type
GitHub Repository
Related Skills
content-collections
MetaThis skill provides a production-tested setup for Content Collections, a TypeScript-first tool that transforms Markdown/MDX files into type-safe data collections with Zod validation. Use it when building blogs, documentation sites, or content-heavy Vite + React applications to ensure type safety and automatic content validation. It covers everything from Vite plugin configuration and MDX compilation to deployment optimization and schema validation.
llamaindex
MetaLlamaIndex is a data framework for building RAG-powered LLM applications, specializing in document ingestion, indexing, and querying. It provides key features like vector indices, query engines, and agents, and supports over 300 data connectors. Use it for document Q&A, chatbots, and knowledge retrieval when building data-centric applications.
hybrid-cloud-networking
MetaThis skill configures secure hybrid cloud networking between on-premises infrastructure and cloud platforms like AWS, Azure, and GCP. Use it when connecting data centers to the cloud, building hybrid architectures, or implementing secure cross-premises connectivity. It supports key capabilities such as VPNs and dedicated connections like AWS Direct Connect for high-performance, reliable setups.
polymarket
MetaThis skill enables developers to build applications with the Polymarket prediction markets platform, including API integration for trading and market data. It also provides real-time data streaming via WebSocket to monitor live trades and market activity. Use it for implementing trading strategies or creating tools that process live market updates.
