DocTreen

Introduction

Code-first API docs, OpenAPI 3.1, integration tests, and runtime validation — one Zod schema per route.

DocTreen is a code-first API documentation library for Node.js. Define your route shape once with Zod (or DocTreen's own schema builder), and it generates an interactive docs UI, runnable integration flows, and Postman exports for Express, Fastify, Hono, Koa, and NestJS — no router rewrite, no separate spec file, no decorator boilerplate on every DTO field.

Why DocTreen

Most API doc tools force you to pick one of three trade-offs:

  • Spec-first (OpenAPI YAML): write the spec, then keep it in sync with code. Spec drifts.
  • Annotation-heavy (@nestjs/swagger, swagger-jsdoc): decorate every property of every DTO. Boilerplate compounds.
  • Framework-locked (ts-rest, Hono RPC): rewrite your router. Migration pain.

DocTreen sits next to your existing router. Pass a Zod schema to defineRoute (or @DocRoute on NestJS) once, and you get:

  • An interactive docs UI at /docs — zero-dependency HTML, served by the same Node process
  • OpenAPI 3.1 export at /docs/openapi.json and a one-click download button — drop the file into Scalar, Redoc, Swagger UI, or any spec-driven tool
  • components.schemas with $ref dedup v1.11defineSchema lifts shared shapes into components.schemas; repeated anonymous objects auto-promote too
  • Per-route + top-level tags v1.11 — group operations the way you want, with descriptions and externalDocs
  • Callbacks + webhooks v1.11 — OpenAPI 3.1 callbacks (per-operation) and webhooks (document-level) wired in
  • Multi-example bodies and responses v1.11 — single value or named map, per-status examples for error responses
  • securitySchemes + per-route security v1.8 — declare auth schemes once, attach them automatically; the spec passes Redocly's security-defined rule cleanly
  • hidden: true per route v1.8 — keep internal endpoints serving traffic but invisible to docs / OpenAPI consumers
  • doctreen lint openapi CLI v1.11 — Spectral-lite linter for the exported (or any) OpenAPI 3.x doc; CI-ready exit codes
  • doctreen mock CLI v1.12 — serves a spec-driven fake API with CRUD short-circuits, latency / error injection, and optional Faker
  • Runnable integration flows with a CLI runner suitable for CI
  • Postman Collection v2.1 export
  • Runtime validation — opt in with validate: true and invalid requests are rejected with a structured 422 before they reach your handler. Same schema as the docs.
  • Schema Drift Detection — declared schemas are compared against real traffic on every adapter; sampled mismatches feed a UI tab, /drift.json, hourly + 7-day buckets, an opinionated CLI (npx doctreen drift report --fail-on-mismatch), an optional reset endpoint, and a Redis-backed DriftStore reference for multi-replica deployments.

How DocTreen compares

FeatureDocTreen@nestjs/swaggerScalar / Redocts-rest
Spec file required
Frameworks supported5 adaptersNestJS onlyAny (spec-only)Custom router
Zod schemas accepted directlyAll adaptersManualManual
Runtime request validationOne schemaclass-validator
Integration test runnerBuilt-in flows
Postman export
OpenAPI 3.1 exportBuilt-inRequiredPlugin
securitySchemes + per-route securityv1.8ManualSpec inputManual
Hide a route from docsPer route + patternsSpec edit
Schema drift detectionv1.10, CI-ready
OpenAPI linter (CLI)v1.11Via Spectral
Spec-driven mock serverv1.12Separate Prism
Setup time~5 min~30 min~1 hourRefactor router

Quick taste

import express from 'express';
import { z } from 'zod';
import { defineRoute, expressAdapter } from 'doctreen/express';

const app = express();
app.use(express.json());

app.post('/users', defineRoute(
  (req, res) => res.status(201).json({ id: 1, ...req.body }),
  {
    description: 'Create a user',
    request:  { body: z.object({ name: z.string(), email: z.string().email() }) },
    response: z.object({ id: z.number(), name: z.string(), email: z.string() }),
    errors:   { 409: 'Email already in use' },
  }
));

app.use(expressAdapter(app, {
  meta: { title: 'My API', version: '1.0.0' },
  validate: true,
}));

app.listen(3000);

That single declaration drives:

  • GET /docs — interactive UI
  • GET /docs/openapi.json — OpenAPI 3.1 spec
  • POST /users with { "email": "nope" }422 with structured issues
  • npx doctreen drift report — shape mismatches vs live traffic
  • Postman collection download + LLM-friendly markdown for the route

Next up: Installation and Quick start.

On this page