Open Studio
Reference

JSX renderer

The kubb/jsx surface backed by @kubb/renderer-jsx. jsxRenderer, the built-in components, and the JSX runtime for component-based code generation.

kubb/jsx is Kubb's JSX-based renderer, an alternative to building files with the ast.factory node builders from kubb/kit. It provides a JSX runtime and a set of built-in components so a generator can emit files and markdown through JSX.

Setup ​

Point your tsconfig.json at the kubb/jsx runtime so JSX syntax compiles against its components instead of React's:

tsconfig.json
json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "kubb/jsx"
  }
}

With that in place, .tsx files in the plugin resolve jsx-runtime and jsx-dev-runtime from kubb/jsx automatically.

jsxRenderer() ​

jsxRenderer creates a renderer instance with two members, render and files. Call render with a JSX element, then read the generated files back off files.

render.tsx
tsx
import { jsxRenderer } from 'kubb/jsx'
import { File, Function, Type } from 'kubb/jsx'

const renderer = jsxRenderer()

await renderer.render(
  <File baseName="petStore.ts" path="src/gen/petStore.ts">
    <File.Source>
      <Type name="Pet">{'{ id: number; name: string }'}</Type>
      <Function name="getPet" async>
        {"return fetch('/pets')"}
      </Function>
    </File.Source>
  </File>,
)

const files = renderer.files

Built-in components ​

kubb/jsx groups its built-in components into four sets:

  • Core components (File, File.Source, File.Import, File.Export) declare an output file and the imports, exports, and source blocks that make it up.
  • JavaScript components (Const, Function, Function.Arrow, Type) emit TypeScript declarations.
  • Markdown components (Callout, Frontmatter, Heading, List, Paragraph) emit markdown.
  • Jsx embeds a raw JSX string in the generated output.
ComponentCategoryEmits
FileCoreFile entry
File.SourceCoreSource block
File.ImportCoreImport statement
File.ExportCoreExport statement
ConstJavaScriptTypeScript
FunctionJavaScriptTypeScript
Function.ArrowJavaScriptTypeScript
TypeJavaScriptTypeScript
CalloutMarkdownMarkdown
FrontmatterMarkdownMarkdown
HeadingMarkdownMarkdown
ListMarkdownMarkdown
ParagraphMarkdownMarkdown
JsxJSXRaw JSX

Core ​

File is the container. Its members File.Source, File.Import, and File.Export attach source blocks, imports, and exports to it.

File ​

Declares a generated output file. Pass both baseName and path to register a file entry. Omit both to render the children inline without creating a file.

PropTypeDescription
baseName`${string}.${string}`File name with extension, such as petStore.ts.
pathstringFully qualified path to the generated file.
meta?object | nullMetadata attached to the file node for plugins to read.
banner?string | nullText prepended before the source blocks.
footer?string | nullText appended after the source blocks.
copy?string | nullAbsolute path to copy verbatim into the output, bypassing the parser.
children?KubbReactNodeSource blocks, imports, and exports that make up the file.
tsx
<File baseName="petStore.ts" path="src/models/petStore.ts">
  <File.Source name="Pet" isExportable isIndexable>
    {`export type Pet = { id: number; name: string }`}
  </File.Source>
</File>

File.Source ​

Marks a block of source text that belongs to the enclosing File. The children are the source string.

PropTypeDescription
name?string | nullIdentifies the source for deduplication and barrel generation.
isExportable?boolean | nullPrepend the export keyword.
isIndexable?boolean | nullInclude the source in barrel and index generation.
isTypeOnly?boolean | nullMark the source as a type-only export.
children?KubbReactNodeSource text of the block.
tsx
<File.Source name="PetId" isTypeOnly isExportable>
  {`export type PetId = string`}
</File.Source>

File.Import ​

Declares an import for the enclosing File. The renderer emits it at the top of the generated file.

PropTypeDescription
namestring | Array<string | { propertyName: string; name?: string }>Binding to import. A string for a default or namespace import, an array for named imports.
pathstringModule specifier to import from.
root?string | nullRoot used to resolve the import path relative to the file.
isTypeOnly?boolean | nullEmit import type.
isNameSpace?boolean | nullEmit import * as name.
tsx
<File.Import name={['useState']} path="react" />
// import { useState } from 'react'

<File.Import name="z" path="zod" isNameSpace />
// import * as z from 'zod'

File.Export ​

Declares an export for the enclosing File. The renderer emits it at the top of the generated file.

PropTypeDescription
name?string | Array<string> | nullBinding to export. Omit for a wildcard export.
pathstringModule specifier to export from.
isTypeOnly?boolean | nullEmit export type.
asAlias?boolean | nullEmit export * as name.
tsx
<File.Export name={['Pet']} path="./models/petStore" />
// export { Pet } from './models/petStore'

<File.Export path="./models/petStore" isTypeOnly />
// export type * from './models/petStore'

JavaScript ​

The JavaScript components emit TypeScript declarations. Nest them inside a File.Source so the renderer writes them into a .ts file.

Const ​

Generates a TypeScript constant declaration. The children are the initializer expression.

PropTypeDescription
namestringIdentifier of the constant.
export?boolean | nullPrepend the export keyword.
type?string | nullType annotation written after const name:.
asConst?boolean | nullAppend as const after the initializer.
JSDoc?JSDoc | nullJSDoc block prepended to the declaration.
children?KubbReactNodeInitializer expression.
tsx
<Const export name="petSchema" type="z.ZodType<Pet>">
  {`z.object({ id: z.number() })`}
</Const>
// export const petSchema: z.ZodType<Pet> = z.object({ id: z.number() })

Function ​

Generates a TypeScript function declaration. The children are the function body.

PropTypeDescription
namestringIdentifier of the function.
export?boolean | nullPrepend the export keyword.
default?boolean | nullEmit default after export to make this the default export.
async?boolean | nullEmit async. Wraps returnType in Promise<…>.
params?string | nullParameter list written between the parentheses.
generics?string | Array<string> | nullGeneric type parameters. An array joins with commas.
returnType?string | nullReturn type annotation written after :.
JSDoc?JSDoc | nullJSDoc block prepended to the declaration.
children?KubbReactNodeFunction body.
tsx
<Function export async name="getPet" generics={['TData = Pet']} params="petId: string" returnType="TData">
  {'return client.get("/pets/" + petId)'}
</Function>
// export async function getPet<TData = Pet>(petId: string): Promise<TData> { … }

Function.Arrow ​

Generates an arrow function assigned to a const. Takes every Function prop plus singleLine.

PropTypeDescription
singleLine?boolean | nullRender a braceless expression body instead of a block.
tsx
<Function.Arrow export name="double" params="n: number" returnType="number" singleLine>
  {`n * 2`}
</Function.Arrow>
// export const double = (n: number): number => n * 2

Type ​

Generates a TypeScript type alias. The children are the type expression. name must start with an uppercase letter or the component throws.

PropTypeDescription
namestringIdentifier of the type alias, starting with an uppercase letter.
export?boolean | nullPrepend the export keyword.
JSDoc?JSDoc | nullJSDoc block prepended to the declaration.
children?KubbReactNodeType expression on the right-hand side.
tsx
<Type export name="PetId">
  {`string | number`}
</Type>
// export type PetId = string | number

Markdown ​

The markdown components each emit their own source block, so they go directly inside a File rather than a File.Source. Render the file with parserMd so it is written as markdown.

docs.tsx
tsx
import { jsxRenderer } from 'kubb/jsx'
import { File, Frontmatter, Heading, Paragraph, List, Callout } from 'kubb/jsx'

const renderer = jsxRenderer()

await renderer.render(
  <File baseName="pets.md" path="src/docs/pets.md">
    <Frontmatter data={{ title: 'Pets', layout: 'doc' }} />
    <Heading level={2}>Pets</Heading>
    <Paragraph>{'A pet object with an id and a name.'}</Paragraph>
    <List items={['id: number', 'name: string']} />
    <Callout type="tip">Keep the generator hot with kubb start --watch.</Callout>
  </File>,
)

Callout ​

Renders a GitHub-style alert using the > [!TYPE] blockquote syntax.

PropTypeDescription
type'tip' | 'note' | 'important' | 'warning' | 'caution'Callout kind, mapped to the uppercase label.
title?string | nullTitle rendered on the marker line.
childrenstringBody text. Each line is quoted with > .
tsx
<Callout type="warning" title="Heads up">Breaking change in v6.</Callout>
// > [!WARNING] Heads up
// > Breaking change in v6.

Frontmatter ​

Emits a YAML frontmatter envelope at the top of a markdown file. Place it as the first child of the File.

PropTypeDescription
dataRecord<string, unknown>Object serialized to YAML between --- fences.
tsx
<Frontmatter data={{ title: 'Pets', layout: 'doc' }} />
// ---
// title: Pets
// layout: doc
// ---

Heading ​

Renders an ATX-style markdown heading.

PropTypeDescription
level1 | 2 | 3 | 4 | 5 | 6Heading depth, matching the number of # characters.
childrenstringHeading text.
tsx
<Heading level={2}>Installation</Heading>
// ## Installation

List ​

Renders a markdown list, one entry per line.

PropTypeDescription
itemsReadonlyArray<string>List entries, one per line.
ordered?boolean | nullEmit a numbered list. Defaults to a bullet list.
tsx
<List ordered items={['First', 'Second']} />
// 1. First
// 2. Second

Paragraph ​

Renders a markdown paragraph. Inline markdown passes through verbatim.

PropTypeDescription
childrenstringParagraph text.
tsx
<Paragraph>{'A pet object with `id` and `name` fields.'}</Paragraph>

JSX ​

Jsx ​

Embeds a raw JSX string in the generated source, including fragments. Use it inside a Function to emit a component body. The children must be a plain string.

PropTypeDescription
children?stringRaw JSX string embedded verbatim.
tsx
<Function name="MyComponent" export>
  <Jsx>{'return (\n  <>\n    <div>Hello</div>\n  </>\n)'}</Jsx>
</Function>

See also ​

  • Kit API for defineGenerator's renderer field and the ast.factory alternative to JSX
  • Creating plugins for how a generator wires a renderer into its output
  • Kit API: rendering for how jsxRenderer sits next to createRenderer