thesys-c1-genui
Note: Refer to this SKILL.md file whenever there is any requirement for adding/editing functionality for C1.
Thesys C1 Generative UI Development
This skill provides comprehensive guidance for developing applications with the Thesys C1 API and GenUI SDK, enabling AI-powered Generative UI applications.
What is Thesys C1?
Thesys C1 is a Generative UI API that dynamically generates interactive UI components from natural language prompts. Unlike traditional AI that returns text/markdown, C1 generates live, interactive interfaces rendered through React components.
Key Features
- Interactive Components: Forms, charts, tables, buttons that users can interact with
- Themeable: Consistent brand styling via
<ThemeProvider> - Real-time UI Streaming: Progressive rendering as responses generate
- OpenAI-Compatible API: Drop-in replacement for OpenAI SDKs
- Robust Error Handling: Graceful degradation with
onErrorprop
What Can You Build?
- Analytics dashboards with dynamic charts
- Conversational AI agents with rich UI
- Internal tools and admin panels
- E-commerce flows with forms and product displays
- AI assistants like ChatGPT with Generative UI
Quickstart
Prerequisites
- Node.js 18+ or Python 3.8+
- Thesys API key from console.thesys.dev
- Install the required packages:
npm install @thesysai/genui-sdk@latest @crayonai/react-ui@latest @crayonai/react-core@latest @crayonai/stream@latest openai@latest next@latest react@^19.0.0 react-dom@^19.0.0
Next.js Setup
npx create-c1-app my-app
cd my-app
npm run dev
Python (FastAPI) Setup
git clone https://github.com/thesysdev/template-c1-fastapi.git
cd template-c1-fastapi
pip install -r requirements.txt
uvicorn main:app --reload
# In another terminal for frontend:
npm install && npm run dev
Set your API key:
export THESYS_API_KEY=<your-api-key>
Core Components
<C1Component> - Render C1 Responses
The fundamental component that renders C1 DSL into a functional micro-frontend:
import { C1Component, ThemeProvider } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";
<ThemeProvider>
<C1Component
c1Response={response}
isStreaming={isLoading}
onAction={({ llmFriendlyMessage, humanFriendlyMessage }) => {
// Handle button clicks, form submissions
}}
updateMessage={(updatedResponse) => {
// Persist state changes to database
}}
/>
</ThemeProvider>
<C1Chat> - Full Conversational UI
A batteries-included chat component with thread management:
import { C1Chat } from "@thesysai/genui-sdk";
import "@crayonai/react-ui/styles/index.css";
<C1Chat
apiUrl="/api/chat"
agentName="My Assistant"
logoUrl="/logo.png"
formFactor="full-page" // or "side-panel"
/>
Key Differences
| Feature | <C1Component> |
<C1Chat> |
|---|---|---|
| Render C1 DSL | ✅ | ✅ |
| Streaming | ✅ | ✅ |
| Forms & Actions | ✅ | ✅ |
| Message History | DIY | ✅ Built-in |
| Thread Management | DIY | ✅ Built-in |
| Chat UI | ❌ | ✅ |
How C1 Works
The Flow
- User sends prompt → Frontend
- Frontend calls backend → Your API
- Backend calls C1 API →
https://api.thesys.dev/v1/embed - C1 returns DSL → Backend
- Backend streams to frontend → Response
<C1Component>renders UI → User sees interactive UI
Backend API Call
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.thesys.dev/v1/embed",
apiKey: process.env.THESYS_API_KEY,
});
const response = await client.chat.completions.create({
model: "c1/anthropic/claude-sonnet-4/v-20251230",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Show me a chart of sales data" }
],
stream: true,
});
C1 Response Structure
C1 responses use an XML-like structure:
<thinking>Analyzing request...</thinking>
<content>
<!-- Interactive UI components -->
</content>
<artifact id="report-1">
<!-- Document content like slides/reports -->
</artifact>
Supported Models
Stable Models:
c1/anthropic/claude-sonnet-4/v-20251230c1/openai/gpt-5/v-20251230
Experimental Models:
c1-exp/anthropic/claude-sonnet-4.5/v-20251230c1-exp/anthropic/claude-haiku-4.5/v-20251230
Artifact Model:
c1/artifact/v-20251230
Backend API Setup
Install Dependencies
npm install openai @crayonai/stream
Create Message Store
// app/api/chat/messageStore.ts
import OpenAI from "openai";
export type DBMessage = OpenAI.Chat.ChatCompletionMessageParam & { id?: string };
const messagesStore: { [threadId: string]: DBMessage[] } = {};
export const getMessageStore = (threadId: string) => {
if (!messagesStore[threadId]) {
messagesStore[threadId] = [];
}
return {
addMessage: (message: DBMessage) => {
messagesStore[threadId].push(message);
},
getOpenAICompatibleMessageList: () => {
return messagesStore[threadId].map((m) => {
const { id, ...rest } = m;
return rest;
});
},
};
};
Create Chat Endpoint
// app/api/chat/route.ts
import { NextRequest, NextResponse } from "next/server";
import OpenAI from "openai";
import { transformStream } from "@crayonai/stream";
import { DBMessage, getMessageStore } from "./messageStore";
export async function POST(req: NextRequest) {
const { prompt, threadId, responseId } = await req.json() as {
prompt: DBMessage;
threadId: string;
responseId: string;
};
const client = new OpenAI({
baseURL: "https://api.thesys.dev/v1/embed",
apiKey: process.env.THESYS_API_KEY,
});
const messageStore = getMessageStore(threadId);
messageStore.addMessage(prompt);
const llmStream = await client.chat.completions.create({
model: "c1/anthropic/claude-sonnet-4/v-20251230",
messages: messageStore.getOpenAICompatibleMessageList(),
stream: true,
});
const responseStream = transformStream(
llmStream,
(chunk) => chunk.choices[0].delta.content,
{
onEnd: ({ accumulated }) => {
const message = accumulated.filter(Boolean).join("");
messageStore.addMessage({
role: "assistant",
content: message,
id: responseId,
});
},
}
) as ReadableStream;
return new NextResponse(responseStream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache, no-transform",
Connection: "keep-alive",
},
});
}
Integration Patterns
C1 as Gateway LLM (Recommended)
Replace your existing LLM endpoint with C1:
const client = new OpenAI({
baseURL: "https://api.thesys.dev/v1/embed", // Change from OpenAI
apiKey: process.env.THESYS_API_KEY,
});
// Use existing tools and system prompts
const response = await client.beta.chat.completions.runTools({
model: "c1/anthropic/claude-sonnet-4/v-20251230",
messages: [...],
tools: existingTools,
stream: true,
});
C1 as Presentation Layer
Generate text with your LLM, then visualize with C1:
// 1. Get text from your LLM
const textResponse = await yourLLM.generate(prompt);
// 2. Visualize with C1
const uiResponse = await c1Client.chat.completions.create({
model: "c1/anthropic/claude-sonnet-4/v-20251230",
messages: [{ role: "user", content: textResponse }],
});
C1 as a Tool
Expose C1 as a tool your agent can invoke:
const tools = [{
type: "function",
function: {
name: "generate_ui",
description: "Generate interactive UI for user",
parameters: {
type: "object",
properties: {
content: { type: "string", description: "Content to visualize" }
}
}
}
}];
If the user wants to visualize their own data, refer to visualize-api-endpoint.md.
Additional References
For detailed information on specific topics, see:
- Conversational UI & Persistence: State management,
useThreadManager,useThreadListManager, database persistence - Custom Actions, Components & Thinking States:
c1_custom_actions,onAction, custom components,useC1State, thinking states - Artifacts: Generating, rendering, editing, and exporting reports/presentations
- Customizations & Styling:
<ThemeProvider>, chart palettes, CSS overrides - Migration Guide: Step-by-step migration from text-based LLM to Generative UI
Resources
- Documentation: https://docs.thesys.dev
- API Reference: https://docs.thesys.dev/api-reference/getting-started
- Examples: https://github.com/thesysdev/examples
- Discord Community: https://discord.gg/Pbv5PsqUSv