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
FileNodeinto source code. - Storage writes the result to disk.
Each section below summarizes one layer and links to its full page for more detail.
Pipeline overview
Every run moves through four stages. Select one to see what it does, or watch it play through from spec to files.
You declare the input spec, the output folder, an adapter, and the plugins to run. defineConfig pre-wires the OpenAPI adapter and the default parsers.
input output adapter plugins Config
defineConfig from kubb/config pre-wires the adapter, the default parsers, and the barrel plugin, so a minimal config only needs input and output. See the defaults table for exactly what each field resolves to.
import { defineConfig } from 'kubb/config'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen' },
plugins: [],
})NOTE
Reach for createKubb only when you need a programmatic build or custom tooling.
Adapter
The adapter reads your spec and returns an InputNode, so nothing downstream touches the original format. It answers every spec-specific question: nullability, $ref resolution, discriminators, and binary detection. @kubb/adapter-oas covers OpenAPI 2.0, 3.0, and 3.1, and defineConfig selects it for you.
AST
The AST is the contract between the adapter and the plugins. Every adapter produces one and every plugin reads it, so the same plugin works against any spec. Two visitors walk it: transform to rewrite nodes and collect to gather them.
Macros
Macros are a second AST pass. They rewrite schema and operation nodes, one plugin at a time, before generators print code, so you can rename symbols or retype fields without patching the output. Pass them through a plugin's macros option.
Plugins
A plugin walks the AST and emits FileNodes. Plugins run in array order, so a types plugin can run first and a client plugin after it imports those types. Browse the plugins catalogue for what ships today.
Generators
A generator is where a plugin produces code. Each one reads a schema, a single operation, or the whole operation set, and returns the files those nodes become. Splitting a plugin into named generators keeps each one small and lets the engine call the right one for every node.
Renderer
A generator can build FileNodes by hand or describe them as components, and kubb/jsx is the optional JSX path for the second style.
NOTE
kubb/jsx is optional. Plugins that build FileNodes directly with the factory node builders from kubb/kit do not need it.
Resolvers
A resolver answers two questions for every file: its name and its path. Generators ask the resolver instead of building strings, so names stay consistent and one plugin imports another's output by reading its resolver.
Parsers
A parser converts a FileNode into a source string. Each one claims a set of file extensions, and Kubb hands every emitted file to the parser that owns its extension. @kubb/parser-ts and @kubb/parser-md ship by default.
Storage
The storage driver decides where files land.
fsStorage()writes to disk and skips unchanged files. Default.memoryStorage()keeps everything in aMap, ideal for tests.- A custom
Storagetargets any other backend.
Integrations and AI
unplugin-kubbruns Kubb inside your build tool: Vite, Rollup, webpack, esbuild, Rspack, Nuxt, and Astro.- The
kubb mcpcommand exposes generation to LLM clients over MCP.