← Back to nodox
Automated OpenAPI Generation
Automated OpenAPI Generation
from Zod Schemas in Express
Stop duplicating your Zod type definitions into Swagger YAML. nodox-cli reads your existing z.object() schemas directly from your Express routes and generates live OpenAPI docs automatically.
The duplication problem
You've already defined every field in Zod for runtime validation. The moment you also need Swagger docs, most tools force you to define those fields again — this time in YAML, JSDoc, or a separate schema registry. That's two sources of truth that diverge every time you rename a field.
Without nodox-cli (manual duplication)
// Zod schema
const CreateUser = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().optional(),
})
// Then ALSO write this in YAML...
// paths:
// /users:
// post:
// requestBody:
// content:
// application/json:
// schema:
// type: object
// properties:
// name:
// type: string
// minLength: 1
// email:
// type: string
// format: email
// age:
// type: integer
// ... 30 more lines
With nodox-cli (zero duplication)
import nodox, { validate } from 'nodox-cli'
import { z } from 'zod'
const app = express()
app.use(express.json())
app.use(nodox(app)) // ← one line
const CreateUser = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().optional(),
})
// validate() reads the Zod schema AND
// validates incoming requests
app.post('/users',
validate(CreateUser),
handler
)
// Done. Visit /__nodox for live docs.
What nodox-cli detects from Zod
- ✓ Primitive types:
z.string(),z.number(),z.boolean(),z.date() - ✓ Constraints:
.min(),.max(),.email(),.url(),.uuid(),.regex() - ✓ Optional fields:
.optional(),.nullable() - ✓ Nested objects:
z.object({ address: z.object({...}) }) - ✓ Arrays:
z.array(z.string()) - ✓ Enums:
z.enum(['admin', 'user']) - ✓ Unions:
z.union([...]) - ✓ Response schemas:
validate(Input, { response: Output }) - ✓ Zod v3 and v4
Setup in 30 seconds
Also supports
nodox-cli isn't Zod-only. It reads Joi, express-validator, and yup schemas with the same zero-config approach.