DEV Community

Tyson Cung
Tyson Cung

Posted on

Stop Writing NestJS CRUD Boilerplate - Generate It from Zod Schemas Instead

I've written the same NestJS CRUD code at least 50 times. Controller with five endpoints. Service that calls a repository. Repository that talks to the database. Create DTO, Update DTO. Module that wires everything together. Every. Single. Resource.

It's not hard work. It's just tedious work. And tedious work is where bugs hide - a misspelled field name, a missing @Injectable(), forgetting to add the module to app.module.ts.

So I built zapit, a CLI that generates all of it from a Zod schema file. One command, full CRUD layer.

The idea

If you're already using Zod (and if you're writing TypeScript APIs in 2025+, you probably should be), your schema is your source of truth. It defines your fields, types, constraints, and defaults. Why write that information a second time in DTOs and entity classes?

zapit reads your Zod schema and generates everything downstream from it.

Quick start

No install required:

npx @tysoncung/zapit generate schemas/product.schema.ts
Enter fullscreen mode Exit fullscreen mode

Or if you're starting from scratch:

npx @tysoncung/zapit init my-api
cd my-api
Enter fullscreen mode Exit fullscreen mode

This scaffolds a full NestJS project with DynamoDB config, Zod validation pipe, and a sensible folder structure.

Define your schema

Here's a typical schema file:

// schemas/product.schema.ts
import { z } from 'zod';

export const ProductSchema = z.object({
  name: z.string().min(1).max(255),
  price: z.number().positive(),
  description: z.string().optional(),
  category: z.enum(['electronics', 'clothing', 'food', 'other']),
  inStock: z.boolean().default(true),
  tags: z.array(z.string()).optional(),
});
Enter fullscreen mode Exit fullscreen mode

Nothing special - just Zod as you'd normally write it.

What gets generated

Run npx @tysoncung/zapit generate schemas/product.schema.ts and you get six files:

Controller

// src/product/product.controller.ts
@Controller('products')
export class ProductController {
  constructor(private readonly productService: ProductService) {}

  @Post()
  create(@Body() dto: CreateProductDto) { ... }

  @Get()
  findAll() { ... }

  @Get(':id')
  findOne(@Param('id') id: string) { ... }

  @Put(':id')
  update(@Param('id') id: string, @Body() dto: UpdateProductDto) { ... }

  @Delete(':id')
  remove(@Param('id') id: string) { ... }
}
Enter fullscreen mode Exit fullscreen mode

Service

Standard service layer that delegates to the repository. Clean separation of concerns - you add your business logic here.

Repository

DynamoDB repository out of the box with create, findAll, findOne, update, and remove methods.

DTOs

CreateProductDto and UpdateProductDto derived from your Zod schema. The update DTO makes all fields optional (partial update pattern). Validation is handled by a Zod validation pipe, so your runtime validation matches your types exactly.

Module

// src/product/product.module.ts
@Module({
  controllers: [ProductController],
  providers: [ProductService, ProductRepository],
  exports: [ProductService],
})
export class ProductModule {}
Enter fullscreen mode Exit fullscreen mode

Wired up and ready to import into your AppModule.

Why Zod as the source of truth?

A few reasons:

  1. You're probably already using it. Zod is the most popular runtime validation library in the TypeScript ecosystem.
  2. Single source of truth. Define fields, types, and constraints once. No drift between your validation layer and your DTOs.
  3. It's just TypeScript. No config files, no YAML, no custom DSL. Your schema is code you can test, compose, and version control like everything else.

Free vs Pro

The free tier is fully functional:

  • ✅ Full CRUD generation (controller, service, repository, DTOs, module)
  • ✅ DynamoDB repository
  • ✅ NestJS module auto-wiring
  • ✅ Zod validation pipe
  • zapit init project scaffolding

If you need more, there's a Pro tier that includes:

  • Prisma support (swap DynamoDB for any Prisma-supported database)
  • Auth middleware generation
  • Pagination helpers
  • Audit logging
  • Multi-tenant support
  • OpenAPI spec generation
  • AWS CDK deployment scaffolds

Pro is there for teams that want to move fast on production-grade APIs, but the free version covers the core use case: stop writing boilerplate.

What this isn't

zapit isn't a framework. It doesn't add runtime dependencies or lock you into a pattern. It generates standard NestJS code that you own and modify however you want. If you outgrow it, you just... edit the files. No vendor lock-in, no magic.

What's next

I'm actively working on:

  • More database adapters (MongoDB, PostgreSQL repos without Prisma)
  • Relationship handling between schemas
  • Custom template support
  • Plugin system for community generators

Try it

npx @tysoncung/zapit generate your-schema.ts
Enter fullscreen mode Exit fullscreen mode

I'd love to hear what you think - what works, what's missing, what would make this useful for your projects. Drop an issue on GitHub or hit me up in the comments.

Top comments (0)