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/config 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/config'

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

NOTE

Reach for createKubb from the kubb package only when you need a programmatic build 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, and adapter.getImports(node, resolve) tracks cross-references so plugins emit correct import paths.

Each adapter carries a dialect, and that 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/config'
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 and 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)

The AST layer 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 the 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. Because they run on the shared AST, the same macro works across every adapter and output target.

Macros run per plugin, so 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/config'
import {  } from '@kubb/plugin-ts'
import {  } from 'kubb/kit'

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, so earlier plugins produce types that later plugins can import.

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

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

See the plugins catalogue for the full list.

Renderer

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

NOTE

kubb/jsx is optional. Plugins that build FileNodes directly with the factory node builders from kubb/kit 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, and Kubb dispatches every emitted file to the first matching parser.

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

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.
@kubb/parser-md .md, .markdown Writes Markdown files. Included automatically with kubb.

Storage

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

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

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.

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.

AI

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