Skip to main content

Schemas pattern

Zod schemas for request validation and (optionally) query/filter validation live in the shared package under the models layout (see pattern sharing and models): entity directories use create.ts, update.ts, query.ts, and optionally enums.ts; theme directories use operation-named files (e.g. sign-in.ts, refresh-token.ts). Use z.enum() for enum fields (Zod v4: z.enum(MyEnum) or z.enum(['active', 'pending_review']); z.nativeEnum() is deprecated). Enum string values must be snake_case (see models). Backend and frontend then validate the same allowed values. Each file defines the schema(s) and inferred DTO types for that concern.

Backend: Use these schemas in router/controllers with ZodValidationPipe for body and (when applicable) query validation; see requests.

Frontend: Use the same schemas and types for form validation (e.g. with @hookform/resolvers) and for request bodies sent via handleRequest, so backend and frontend stay aligned.

Implementation

The boilerplate does not scaffold example schema files; the layout for where schemas live is defined by the models pattern (entity dirs: create.ts, update.ts, query.ts, optional enums.ts; theme dirs: operation-named files). Schemas are defined in the shared package under that layout. Backend validation is implemented by ZodValidationPipe and ZodExceptionFilter (see requests and responses); controllers import schemas from shared (e.g. shared/cat/create) and pass them to the pipe. Frontend uses the same shared imports for form resolvers and request bodies. The generation skill ensures the shared package has subpath exports so shared/<entity>/<file> and shared/<theme>/<file> resolve (see models for multi-segment exports).

References

  • Patterns: models (layout and file naming), requests (ZodValidationPipe, binding in controllers), responses (fieldErrors from validation), forms (frontend schema usage), sharing (what lives in shared).
  • Stack: validation (zod).