Aviary
Integrations

Generative-UI sandbox kit

Write the sandbox-kit docs for @dudousxd/nestjs-agent alongside the generated client.

@dudousxd/nestjs-agent can render generative UI in a sandbox in your design system, whatever its stack: your styles (Tailwind, Bootstrap, Sass, plain CSS), your React components (shadcn components/ui by default, MUI, your own) and your providers. The model is told which components exist and what props they take, and what your styles offer (Tailwind tokens, or the CSS classes they define), from a descriptor, .genui/sandbox-kit.json, that the Nest server reads relative to the app root.

The genuiSandboxKit() extension, built into @dudousxd/nestjs-codegen, writes that descriptor on every codegen pass: one-off nestjs-codegen codegen, --watch, and the Nest module's watcher. It takes the same options as the agent's Vite plugin (genuiSandboxKit() from @dudousxd/nestjs-agent/vite). The component names and props are read from their TypeScript types, and the styles are compiled and read, by writeSandboxKitDocs from @dudousxd/nestjs-agent-core/genui/kit, an optional peer dependency:

pnpm add -D @dudousxd/nestjs-agent-core@">=0.53.0"
nestjs-codegen.config.ts
import { defineConfig, genuiSandboxKit } from '@dudousxd/nestjs-codegen';

export default defineConfig({
  contracts: { glob: 'src/**/*.controller.ts' },
  codegen: { outDir: 'src/generated' },
  extensions: [
    genuiSandboxKit({
      components: 'web/components/ui',  // default: the first shadcn `components/ui` dir found
      styles: 'web/styles/globals.css',  // Tailwind tokens or CSS classes, and the theme's variables
    }),
  ],
});

Options

OptionDefaultWhat it does
componentsthe first of inertia/, resources/js/, src/, app/, or the root components/ui that existsModules whose exports are the kit's React components: files, globs, directories or packages.
styles—The app's style entry files (plain CSS, Sass, a Tailwind stylesheet…). With Tailwind, the model is told your theme tokens and utilities; otherwise the classes the CSS defines. Either way it gets the root custom properties as the theme.
wrapper—A module whose default export wraps the model's App (theme providers). It is recorded in the docs; the agent's Vite plugin bundles it.
stylesDocs—Guidance on the styles for the model: a markdown file, or the text itself.
tsconfigthe project'sThe tsconfig the component prop types are read through.
output.genui/sandbox-kit.jsonWhere the descriptor is written, relative to the app cwd (or absolute).
generatewriteSandboxKitDocsReplace the docs writer (tests, or another generator). It receives { root, output, components?, styles?, wrapper?, stylesDocs?, tsconfig? } and is expected to write output itself.

Migration from 0.28

include and entry are now components, and css is now styles. Passing the old options throws a CodegenError that names the replacement. It needs @dudousxd/nestjs-agent-core >= 0.53.

A project with no kit (no components match, no components/ui, no styles) writes nothing; the extension is a no-op there. Without generate and without @dudousxd/nestjs-agent-core installed, codegen fails with an error naming the package to install.

Freshness and watch mode

The descriptor lives outside outDir, so the extension writes it directly rather than through emitFiles, and nothing it does collides with the core's output files. It declares the kit files, their directories, the stylesheets (and the files they @import) and the descriptor itself through ctx.trackInput, so:

  • editing a component, adding one to the kit directory, or editing a stylesheet regenerates the descriptor, in both watch mode and the next one-off run;
  • a deleted descriptor (e.g. .genui/ is gitignored and the checkout is fresh) is rewritten even when everything else is up to date.

The writer leaves an unchanged descriptor untouched, so a regenerate that changes nothing does not trigger a reload in the server.

On this page