Beta You're reading the docs for Kubb v5, which is currently in beta. View the stable v4 docs
Skip to content

Architecture

Kubb turns API specifications into code through a layered pipeline. The adapter parses the spec into a universal AST. Macros rewrite AST nodes before a plugin reads them. Plugins walk the AST and emit FileNodes. Parsers convert each FileNode into source code. Storage writes the result to disk.

Pipeline overview

Configkubb.config.ts SetupAdapter → AST BuildMacros · Plugins · Renderer File processorParsers → Storage

Config

defineConfig from the kubb package pre-wires adapterOas, the default parsers parserTs, parserTsx, parserMd, and pluginBarrel. A minimal config only needs input and output.

kubb.config.ts
typescript
import {  } from 'kubb'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
  : [],
})

NOTE

Import from @kubb/core only when you need the lower-level API for programmatic builds or custom tooling.

Adapter

Input specOpenAPI 2/3 adapter.parse(source) InputNodeschemas + operations

An adapter converts an input specification into the universal AST. adapter.parse(source) returns an InputNode. adapter.getImports(node, resolve) tracks cross-references so plugins emit correct import paths.

Each adapter carries a dialect. The dialect is the one place where spec-specific schema questions live: nullability, $ref resolution, discriminators, binary detection, and schema deduplication. Everything past the adapter is generic JSON Schema, so plugins and parsers never branch on the source format.

The official adapter for OpenAPI 2.0, 3.0, and 3.1 is @kubb/adapter-oas. defineConfig selects it automatically.

kubb.config.ts
typescript
import {  } from 'kubb'
import {  } from '@kubb/adapter-oas'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
  : ({ : true, : 'date' }),
})

See Adapters for the full list of options and details on building a custom adapter.

AST

The AST is the intermediate representation between the adapter and the plugins. Every adapter produces an InputNode; every plugin consumes it. Plugins never read the raw spec, so the same plugin works with any adapter.

Resulting tree
text
InputNode
├── schemas: SchemaNode[]            (named, reusable schemas)
│   └── consumed by plugins          → FileNode (e.g. type aliases, enums)
└── operations: OperationNode[]
    ├── parameters: ParameterNode[]  → SchemaNode
    ├── requestBody?: RequestBodyNode → content: ContentNode[] → SchemaNode
    ├── responses: ResponseNode[]    → content: ContentNode[] → SchemaNode
    └── consumed by plugins          → FileNode (e.g. client functions, hooks)

@kubb/ast ships three visitor patterns:

Visitor Purpose
walk(root, visitors) Async traversal for logging, validation, and side effects.
transform(root, visitors) Produces a modified copy of the tree. Return null to remove a node.
collect(root, visitors) Gathers matching nodes into a flat array.

Macros

InputNode "applyMacros(node, [... InputNodetransformed

Macros are the second layer of @kubb/ast. They are named, composable transforms that rewrite schema and operation nodes before a plugin's generators print code. Use them to rename symbols, retype fields, or normalize shapes without forking an adapter or a generator. They run on the shared AST, so the same macro works across every adapter and output target.

Macros run per plugin. One plugin's macros never change the nodes another plugin sees. Pass them through a plugin's macros option, or register them from kubb:plugin:setup with addMacro.

kubb.config.ts
typescript
import {  } from 'kubb'
import {  } from '@kubb/plugin-ts'
import {  } from '@kubb/ast/macros'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
  : [({ : [] })],
})

See Macros for writing macros, composing them, and the built-in presets.

Plugins

returns JSX returns FileNode[] InputNode Plugingen.schema() / gen.operation() Renderer@kubb/renderer-jsx "FileNode[

Plugins walk the AST and emit FileNodes. They run in array order; earlier plugins produce types that later plugins can import.

kubb.config.ts
typescript
import {  } from 'kubb'
import {  } from '@kubb/plugin-ts'
import {  } from '@kubb/plugin-axios'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
  : [(), ()],
})

Types and clients

Package Generates
@kubb/plugin-ts TypeScript types and interfaces
@kubb/plugin-axios Axios HTTP client functions
@kubb/plugin-fetch Fetch HTTP client functions

Data-fetching hooks

Package Generates
@kubb/plugin-react-query TanStack Query hooks for React
@kubb/plugin-vue-query TanStack Query hooks for Vue

Validation and mocking

Package Generates
@kubb/plugin-zod Zod validation schemas
@kubb/plugin-faker Faker.js data factories
@kubb/plugin-msw MSW request handlers

Tooling

Package Purpose
@kubb/plugin-cypress Cypress test scaffolding
@kubb/plugin-redoc Embeds Redoc-rendered API docs
@kubb/plugin-mcp Generates MCP-compatible tools and schemas for AI assistants

See the plugins catalogue for the full list.

Renderer

Plugins can use @kubb/renderer-jsx to describe generated files as React components instead of constructing FileNodes by hand.

NOTE

@kubb/renderer-jsx is optional. Plugins that build FileNodes directly with factory functions from @kubb/ast do not need it.

Parsers

"FileNode[ Parser source string storage.setItem(path, source) disk / memory

A parser converts a FileNode into a source string. Each parser declares which file extensions it handles. Kubb dispatches every emitted file to the first matching parser.

kubb.config.ts
typescript
import {  } from 'kubb'
import { ,  } from '@kubb/parser-ts'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
  : [, ],
})

IMPORTANT

When two parsers claim the same extension, the first one wins.

Package Extensions Description
@kubb/parser-ts .ts, .js, .tsx, .jsx Uses the TypeScript compiler to print, deduplicate, and resolve imports. Included automatically with kubb.

Storage

The storage driver controls where Kubb writes generated files. Default is fsStorage(). Use memoryStorage() for testing, or implement Storage to target any backend.

kubb.config.ts
typescript
import {  } from 'kubb'
import {  } from '@kubb/core'

export default ({
  : { : './petStore.yaml' },
  : { : './src/gen' },
  : (),
})
Driver Description
fsStorage() Writes to disk. Skips unchanged files. Default.
memoryStorage() Stores output in a Map. Nothing touches disk. Ideal for tests.
Custom Implement Storage with createStorage to write to S3, a database, or any backend.

Foundation packages

Package Purpose
kubb Umbrella package. Exports defineConfig and bundles adapterOas, parserTs, parserTsx, parserMd, and pluginBarrel for a zero-config setup.
@kubb/core Lower-level runtime with createKubb, definePlugin, defineParser, createAdapter, and storage APIs. Use for programmatic generation or custom tooling.
@kubb/cli Provides the kubb command-line binary. Reads kubb.config.ts and runs the generation pipeline.
@kubb/ast Universal AST layer. Includes all node factories, walk, transform, collect, type guards, ref helpers, and the defineDialect and optionality helpers. The macro engine lives on the root and the presets on @kubb/ast/macros.
@kubb/parser-ts TypeScript and TSX parser. Included automatically with the kubb package.
@kubb/renderer-jsx JSX-based rendering for plugins that build files from React components.

Build-tool integrations

Package Description
unplugin-kubb Runs Kubb during your build via unplugin. Works with Vite, Rollup, webpack, esbuild, Rspack, Nuxt, and Astro.

See the Integrations page for setup instructions for each build tool.

Servers

Package Purpose
@kubb/mcp Standalone MCP server that lets LLM clients trigger generation directly.