Skip to content

Basic Usage

Start from an empty config and end with generated types, a client, and hooks imported into your app. Follow the five steps in order, and by the end you will have run Kubb once and seen real code land in ./src/gen.

1. Create the config

Everything Kubb does starts from kubb.config.ts. Begin with a minimal config that points at your spec and names an output directory.

kubb.config.ts
typescript
import { 
defineConfig
} from 'kubb/config'
export default
defineConfig
({
input
: './petStore.yaml',
output
: {
path
: './src/gen',
clean
: true },
})

input accepts a file path, URL, inline spec, or parsed object, and output.clean: true wipes the output directory before each run so stale files don't pile up.

2. Pick your plugins

Each output format is its own plugin, so you only generate what you ask for. Start small and add plugins as you need them. The tabs below build up from types alone to a full setup with types, a client, hooks, schemas, and mocks.

typescript
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
({
output
: {
path
: 'models' } })],
})
typescript
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
({
output
: {
path
: 'models' } }),
pluginAxios
({
output
: {
path
: 'clients' } })],
})
typescript
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
({
output
: {
path
: 'models' } }),
pluginAxios
({
output
: {
path
: 'clients' } }),
pluginReactQuery
({
output
: {
path
: 'hooks' } })],
})
typescript
import { 
defineConfig
} from 'kubb/config'
import {
pluginTs
} from '@kubb/plugin-ts'
import {
pluginAxios
} from '@kubb/plugin-axios'
import {
pluginReactQuery
} from '@kubb/plugin-react-query'
import {
pluginZod
} from '@kubb/plugin-zod'
import {
pluginMsw
} from '@kubb/plugin-msw'
export default
defineConfig
({
input
: './petStore.yaml',
output
: {
path
: './src/gen',
clean
: true },
plugins
: [
pluginTs
({
output
: {
path
: 'models' } }),
pluginAxios
({
output
: {
path
: 'clients' } }),
pluginReactQuery
({
output
: {
path
: 'hooks' } }),
pluginZod
({
output
: {
path
: 'schemas' } }),
pluginMsw
({
output
: {
path
: 'mocks' } }),
], })
Plugin Package Generates
pluginTs @kubb/plugin-ts TypeScript types and interfaces
pluginAxios @kubb/plugin-axios Axios-based HTTP client functions
pluginReactQuery @kubb/plugin-react-query TanStack Query hooks
pluginZod @kubb/plugin-zod Zod validation schemas
pluginMsw @kubb/plugin-msw MSW request handlers

NOTE

pluginAxios, pluginReactQuery, and pluginMsw each require pluginTs in the same config. pluginReactQuery also calls a registered client plugin, so add pluginAxios or pluginFetch alongside it.

See the plugins catalogue for the full list.

3. Run generate

Run the generate command. Each plugin reports in turn, followed by a summary.

kubb generate

Kubb creates one folder per plugin under output.path, so the layout mirrors the config you wrote. Re-run it after every spec change. See kubb generate for flags like --watch and --reporter.

4. Use the generated code

Import the generated code into your app. The import paths follow the output.path values you set for each plugin, so a plugin pointed at models lives under gen/models.

typescript
// @filename: src/gen/models/Pet.ts
export type Pet = { id: number; name: string }
// @filename: src/app.ts
// ---cut---
import type { Pet } from './gen/models/Pet'

const pet: Pet = { id: 1, name: 'Cat' }
typescript
import { getPetById } from './gen/clients/getPetById'

const { data: pet } = await getPetById({ path: { petId: 1 } })
typescript
import { useGetPetById } from './gen/hooks/useGetPetById'

function Pet({ id }: { id: number }) {
  const { data, isLoading } = useGetPetById({ path: { petId: id } })
  if (isLoading) return null
  return <span>{data?.name}</span>
}
typescript
import { petSchema } from './gen/schemas/petSchema'

const result = petSchema.safeParse(unknown)
typescript
import { setupServer } from 'msw/node'
import { getPetByIdHandler } from './gen/mocks/getPetByIdHandler'

const server = setupServer(getPetByIdHandler())
server.listen()

5. Keep it in sync

That is the full loop. From now on, run npm run generate whenever the spec changes, then commit the output. To skip the manual step, unplugin-kubb generates during your build with Vite, Rollup, Webpack, and others.