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, or yarn

Installation

GenUIKit is split into focused packages. Install the core library and the React bindings:

npm

1npm install @genuikit/core @genuikit/react zod

pnpm

1pnpm add @genuikit/core @genuikit/react zod

yarn

1yarn add @genuikit/core @genuikit/react zod

If you plan to use a pre-built adapter (shadcn/ui, Tailwind, MUI), also install the adapters package:

1npm 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:

1npx @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.

schemas.tstypescript
1import { z } from 'zod';
2 
3export 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 
10export 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.

registry.tstypescript
1import { ComponentRegistry } from '@genuikit/core';
2import { weatherCardSchema } from './schemas';
3import { WeatherCard } from './components/weather-card';
4 
5export const registry = new ComponentRegistry();
6 
7registry.register('WeatherCard', weatherCardSchema, WeatherCard);

Step 3: Render with the hook

Use the useGenerativeUI hook to resolve LLM output into a rendered React element.

chat-message.tsxtsx
1import { useGenerativeUI } from '@genuikit/react';
2import { registry } from './registry';
3 
4function 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:

components/weather-card.tsxtsx
1import type { WeatherCardProps } from '../schemas';
2 
3const conditionIcons: Record<string, string> = {
4 sunny: '\u2600\uFE0F',
5 cloudy: '\u2601\uFE0F',
6 rainy: '\uD83C\uDF27\uFE0F',
7 snowy: '\u2744\uFE0F',
8};
9 
10export 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.

app.tsxtsx
1import { useState } from 'react';
2import { ComponentRegistry } from '@genuikit/core';
3import { GenerativeUI } from '@genuikit/react';
4import { weatherCardSchema, WeatherCard } from './weather-card';
5 
6// 1. Build the registry
7const registry = new ComponentRegistry();
8registry.register('WeatherCard', weatherCardSchema, WeatherCard);
9 
10// 2. Generate the tool definition for the LLM system prompt
11const toolDefs = registry.toToolDefinition();
12// Send toolDefs in your system prompt so the LLM knows the available components
13 
14export 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}

What's Next