Recipes#
Ready-made kubb.config.ts snippets for common setups. Copy one in, install the matching packages, and run kubb generate.
TypeScript only#
The smallest setup, generating TypeScript types and interfaces from your OpenAPI spec.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true },
plugins: [pluginTs()],
})
TypeScript + React Query#
Generates types and TanStack Query hooks for React.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginAxios } from '@kubb/plugin-axios'
import { pluginReactQuery } from '@kubb/plugin-react-query'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true },
plugins: [pluginTs(), pluginAxios(), pluginReactQuery()],
})
TypeScript + Vue Query#
Generates types and TanStack Query hooks for Vue.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginVueQuery } from '@kubb/plugin-vue-query'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true },
plugins: [pluginTs(), pluginVueQuery()],
})
Zod schemas + MSW handlers#
Runtime validation with Zod, plus MSW request handlers backed by Faker.js mock data.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginZod } from '@kubb/plugin-zod'
import { pluginFaker } from '@kubb/plugin-faker'
import { pluginMsw } from '@kubb/plugin-msw'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true },
plugins: [pluginTs(), pluginZod(), pluginFaker(), pluginMsw()],
})
Faker + Zod for testing#
Generates Faker.js data factories next to Zod schemas. Use them in unit and integration tests.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginZod } from '@kubb/plugin-zod'
import { pluginFaker } from '@kubb/plugin-faker'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true },
plugins: [pluginTs(), pluginZod(), pluginFaker()],
})
Pick the HTTP client#
Choose Fetch or Axios by registering the matching plugin. Swap pluginFetch for pluginAxios to use the global fetch instead.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginAxios } from '@kubb/plugin-axios'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true },
plugins: [pluginTs(), pluginAxios()],
})
Multiple specifications#
Generate from several specs in one run. Pass an array to defineConfig. Each entry runs on its own, with its own plugins and output directory.
Set a name per entry so each one shows up in the CLI output.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
export default defineConfig([
{
name: 'petStore',
input: './petStore.yaml',
output: { path: './src/gen/petStore', clean: true },
plugins: [pluginTs()],
},
{
name: 'userApi',
input: './userApi.yaml',
output: { path: './src/gen/userApi', clean: true },
plugins: [pluginTs()],
},
])
Conditional config (watch-aware)#
Pass a function to defineConfig to read CLI context. Here it turns off clean in watch mode so incremental runs stay fast.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
export default defineConfig(({ watch }) => ({
input: './petStore.yaml',
output: {
path: './src/gen',
clean: !watch,
},
plugins: [pluginTs()],
}))
Run kubb generate --watch to regenerate on spec changes.
Format with Biome, lint with Oxlint#
Format generated files with Biome and lint them with Oxlint on every build. Set format and lint to 'auto' to pick whichever tool is installed.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
export default defineConfig({
input: './petStore.yaml',
output: {
path: './src/gen',
clean: true,
format: 'biome',
lint: 'oxlint',
},
plugins: [pluginTs()],
})
Run a command after generation#
Use output.postGenerate to run shell commands, such as a formatter pass or a type check, once the generated files are formatted and linted.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
export default defineConfig({
input: './petStore.yaml',
output: {
path: './src/gen',
postGenerate: ['biome check --write ./src/gen'],
},
plugins: [pluginTs()],
})
Monorepo with multiple outputs#
Generate a different client library per package or team from one config file.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginAxios } from '@kubb/plugin-axios'
import { pluginReactQuery } from '@kubb/plugin-react-query'
export default defineConfig([
{
name: 'public-api',
input: './specs/public.yaml',
output: { path: './packages/public-api/src/gen' },
plugins: [pluginTs(), pluginAxios(), pluginReactQuery()],
},
{
name: 'admin-api',
input: './specs/admin.yaml',
output: { path: './packages/admin-api/src/gen' },
plugins: [pluginTs(), pluginAxios()],
},
])
Environment-aware configuration#
Pick input and output from NODE_ENV so one config covers development, staging, and production.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginAxios } from '@kubb/plugin-axios'
const env = process.env['NODE_ENV'] ?? 'development'
const envConfig = {
development: {
input: 'http://localhost:3000/openapi.json',
output: { path: './src/gen', clean: true },
},
staging: {
input: 'https://staging-api.example.com/openapi.json',
output: { path: './src/gen', clean: true },
},
production: {
input: './specs/production.json',
output: { path: './src/gen', clean: true },
},
} as const
export default defineConfig({
...envConfig[env as keyof typeof envConfig],
plugins: [pluginTs(), pluginAxios()],
})
Programmatic build#
Drive Kubb from a script with createKubb from the kubb package, paired with Diagnostics from kubb/kit. This fits monorepo orchestration and custom build pipelines. It applies the same defaults as defineConfig, so a shared config generates the same files through the CLI and a script.
import { createKubb } from 'kubb'
import { Diagnostics } from 'kubb/kit'
import { pluginTs } from '@kubb/plugin-ts'
const kubb = createKubb({
input: './petStore.yaml',
output: { path: './gen' },
plugins: [pluginTs()],
})
kubb.hooks.hook('kubb:plugin:end', ({ plugin, duration }) => {
console.log(`${plugin.name} completed in ${duration}ms`)
})
const { files, diagnostics } = await kubb.safeBuild()
if (Diagnostics.hasError(diagnostics)) {
for (const diagnostic of diagnostics.filter(Diagnostics.isProblem)) {
if (diagnostic.severity === 'error') {
console.error(`${diagnostic.plugin ?? 'kubb'}: ${diagnostic.message}`)
}
}
process.exit(1)
}
console.log(`Generated ${files.length} files`)
Use .build() instead of .safeBuild() if you want it to throw on errors rather than return diagnostics. See the Kit API for the full Kubb instance API.
CI validation#
Validate the OpenAPI spec and fail the build on errors. Use output.postGenerate to run kubb validate after generation.
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true, postGenerate: ['kubb validate ./petStore.yaml'] },
plugins: [pluginTs()],
})