Getting Started
Get GenUIKit installed and render your first LLM-driven component in under 5 minutes.
Prerequisites
- --Node.js 18+ (LTS recommended)
- --React 18+ (or React 19)
- --A package manager:
npm,pnpm, oryarn
Installation
GenUIKit is split into focused packages. Install the core library and the React bindings:
npm
| 1 | npm install @genuikit/core @genuikit/react zod |
pnpm
| 1 | pnpm add @genuikit/core @genuikit/react zod |
yarn
| 1 | yarn add @genuikit/core @genuikit/react zod |
If you plan to use a pre-built adapter (shadcn/ui, Tailwind, MUI), also install the adapters package:
| 1 | npm install @genuikit/adapters |
CLI Setup
The fastest way to scaffold a new project is with the GenUIKit CLI. It generates a registry file, installs dependencies, and sets up your preferred adapter:
| 1 | npx @genuikit/cli init |
The CLI will ask you to pick an adapter (shadcn/ui, Tailwind, or MUI), then create a genui.registry.ts file with all 30 components pre-configured.
If you prefer to set things up manually, continue reading below.
Quick Start
Here is the minimal setup to render an LLM-produced component. This three-step process works the same whether you use an adapter or build your own schemas.
Step 1: Define a schema
Create a Zod schema describing the props your component expects. The LLM will produce JSON matching this shape.
| 1 | import { z } from 'zod'; |
| 2 | |
| 3 | export const weatherCardSchema = z.object({ |
| 4 | city: z.string(), |
| 5 | temperature: z.number(), |
| 6 | condition: z.enum(['sunny', 'cloudy', 'rainy', 'snowy']), |
| 7 | humidity: z.number().min(0).max(100).optional(), |
| 8 | }); |
| 9 | |
| 10 | export type WeatherCardProps = z.infer<typeof weatherCardSchema>; |
Step 2: Create a registry
Register your component with its schema. The registry maps component names to schemas and implementations.
| 1 | import { ComponentRegistry } from '@genuikit/core'; |
| 2 | import { weatherCardSchema } from './schemas'; |
| 3 | import { WeatherCard } from './components/weather-card'; |
| 4 | |
| 5 | export const registry = new ComponentRegistry(); |
| 6 | |
| 7 | registry.register('WeatherCard', weatherCardSchema, WeatherCard); |
Step 3: Render with the hook
Use the useGenerativeUI hook to resolve LLM output into a rendered React element.
| 1 | import { useGenerativeUI } from '@genuikit/react'; |
| 2 | import { registry } from './registry'; |
| 3 | |
| 4 | function ChatMessage({ output }) { |
| 5 | const { element, ok, correctionPrompt } = useGenerativeUI(registry, output); |
| 6 | |
| 7 | if (!ok) { |
| 8 | // Send correctionPrompt back to the LLM for a retry |
| 9 | return <div>Rendering failed. Retrying...</div>; |
| 10 | } |
| 11 | |
| 12 | return <div className="message">{element}</div>; |
| 13 | } |
Manual Setup
For a complete manual setup, you need four pieces: a component, a schema, a registry, and a rendering hook. Here they are together:
| 1 | import type { WeatherCardProps } from '../schemas'; |
| 2 | |
| 3 | const conditionIcons: Record<string, string> = { |
| 4 | sunny: '\u2600\uFE0F', |
| 5 | cloudy: '\u2601\uFE0F', |
| 6 | rainy: '\uD83C\uDF27\uFE0F', |
| 7 | snowy: '\u2744\uFE0F', |
| 8 | }; |
| 9 | |
| 10 | export function WeatherCard({ city, temperature, condition, humidity }: WeatherCardProps) { |
| 11 | return ( |
| 12 | <div className="rounded-xl border p-4 shadow-sm"> |
| 13 | <div className="flex items-center justify-between"> |
| 14 | <h3 className="text-lg font-semibold">{city}</h3> |
| 15 | <span className="text-2xl">{conditionIcons[condition]}</span> |
| 16 | </div> |
| 17 | <p className="text-3xl font-bold mt-2">{temperature}\u00B0C</p> |
| 18 | <p className="text-sm text-gray-500 capitalize">{condition}</p> |
| 19 | {humidity !== undefined && ( |
| 20 | <p className="text-sm text-gray-400 mt-1">Humidity: {humidity}%</p> |
| 21 | )} |
| 22 | </div> |
| 23 | ); |
| 24 | } |
Full Working Example
This complete example shows how to connect an LLM API response to GenUIKit rendering. It uses the GenerativeUI declarative component.
| 1 | import { useState } from 'react'; |
| 2 | import { ComponentRegistry } from '@genuikit/core'; |
| 3 | import { GenerativeUI } from '@genuikit/react'; |
| 4 | import { weatherCardSchema, WeatherCard } from './weather-card'; |
| 5 | |
| 6 | // 1. Build the registry |
| 7 | const registry = new ComponentRegistry(); |
| 8 | registry.register('WeatherCard', weatherCardSchema, WeatherCard); |
| 9 | |
| 10 | // 2. Generate the tool definition for the LLM system prompt |
| 11 | const toolDefs = registry.toToolDefinition(); |
| 12 | // Send toolDefs in your system prompt so the LLM knows the available components |
| 13 | |
| 14 | export function App() { |
| 15 | const [output, setOutput] = useState(null); |
| 16 | |
| 17 | async function handleAsk(question: string) { |
| 18 | const res = await fetch('/api/chat', { |
| 19 | method: 'POST', |
| 20 | body: JSON.stringify({ question, tools: toolDefs }), |
| 21 | }); |
| 22 | const data = await res.json(); |
| 23 | // data = { type: 'WeatherCard', props: { city: 'Tokyo', temperature: 22, condition: 'sunny' } } |
| 24 | setOutput(data); |
| 25 | } |
| 26 | |
| 27 | return ( |
| 28 | <div> |
| 29 | <button onClick={() => handleAsk('Weather in Tokyo?')}> |
| 30 | Ask about weather |
| 31 | </button> |
| 32 | |
| 33 | {output && ( |
| 34 | <GenerativeUI |
| 35 | registry={registry} |
| 36 | output={output} |
| 37 | fallback={<div>Failed to render component</div>} |
| 38 | onError={(prompt, errors) => { |
| 39 | console.log('Validation failed, correction prompt:', prompt); |
| 40 | // Optionally: send `prompt` back to the LLM for auto-correction |
| 41 | }} |
| 42 | /> |
| 43 | )} |
| 44 | </div> |
| 45 | ); |
| 46 | } |