name: chatkit-js description: Integrate OpenAI ChatKit React components into Next.js applications. Covers custom API backend configuration, theming, widget embedding, conversation history, and authentication integration.
ChatKit JS Frontend Skill
Integrate OpenAI ChatKit UI components into Next.js applications with custom backend support.
Architecture
┌─────────────────────────────────────────────────────────────────────────┐
│ Next.js Frontend │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ChatKit Widget │ │
│ │ • useChatKit hook with custom API config │ │
│ │ • Theming & customization │ │
│ │ • Auth token injection │ │
│ │ • Conversation history │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
│ Custom fetch with JWT
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ FastAPI Backend │
│ /api/chat (SSE streaming) │
└─────────────────────────────────────────────────────────────────────────┘
Quick Start
Installation
npm install @openai/chatkit-react
# Or with pnpm
pnpm add @openai/chatkit-react
Environment Variables
# Domain key from OpenAI (for hosted mode)
NEXT_PUBLIC_OPENAI_DOMAIN_KEY=your-domain-key
# Custom API URL (for custom backend mode)
NEXT_PUBLIC_CHAT_API_URL=http://localhost:8000/api/chat
Reference
| Pattern | Guide |
|---|---|
| Basic Setup | reference/basic-setup.md |
| Custom API | reference/custom-api.md |
| Theming | reference/theming.md |
Examples
| Example | Description |
|---|---|
| examples/todo-chatbot.md | Complete todo chatbot widget |
Templates
| Template | Purpose |
|---|---|
| templates/ChatWidget.tsx | ChatKit widget component |
| templates/ChatPage.tsx | Full chat page layout |
Basic ChatKit Widget
"use client";
import { ChatKit, useChatKit } from "@openai/chatkit-react";
export function ChatWidget() {
const { control } = useChatKit({
api: {
url: process.env.NEXT_PUBLIC_CHAT_API_URL || "/api/chat",
domainKey: process.env.NEXT_PUBLIC_OPENAI_DOMAIN_KEY,
},
});
return (
<ChatKit
control={control}
className="h-[600px] w-[400px] rounded-lg shadow-lg"
/>
);
}
Custom API with Authentication
"use client";
import { ChatKit, useChatKit } from "@openai/chatkit-react";
import { useSession } from "@/lib/auth-client"; // Better Auth
export function AuthenticatedChat() {
const { data: session } = useSession();
const { control } = useChatKit({
api: {
url: process.env.NEXT_PUBLIC_CHAT_API_URL || "/api/chat",
domainKey: process.env.NEXT_PUBLIC_OPENAI_DOMAIN_KEY,
// Custom fetch to inject auth token
fetch: async (input, init) => {
const token = session?.session?.token;
return fetch(input, {
...init,
headers: {
...init?.headers,
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json",
},
credentials: "include",
});
},
},
});
if (!session) {
return <div>Please sign in to use the chatbot</div>;
}
return (
<ChatKit
control={control}
className="h-full w-full"
/>
);
}
Theming
const { control } = useChatKit({
api: { /* ... */ },
theme: {
colorScheme: "dark", // or "light"
color: {
accent: {
primary: "#3b82f6", // Blue accent
level: 2,
},
grayscale: {
hue: 220,
tint: 5,
shade: 0,
},
surface: {
background: "#1f2937",
foreground: "#f9fafb",
},
},
radius: "soft", // "none", "soft", "round"
density: "normal", // "compact", "normal", "spacious"
typography: {
fontFamily: "Inter, system-ui, sans-serif",
fontFamilyMono: "JetBrains Mono, monospace",
baseSize: 16,
},
},
});
Start Screen Customization
const { control } = useChatKit({
api: { /* ... */ },
startScreen: {
greeting: "Hi! I'm your task assistant. How can I help?",
prompts: [
{
name: "View Tasks",
prompt: "Show me my pending tasks",
icon: "list",
},
{
name: "Add Task",
prompt: "Help me add a new task",
icon: "plus",
},
{
name: "Get Help",
prompt: "What can you help me with?",
icon: "question",
},
],
},
});
Header Customization
const { control } = useChatKit({
api: { /* ... */ },
header: {
enabled: true,
title: {
enabled: true,
text: "Todo Assistant",
},
leftAction: {
icon: "sidebar-left",
onClick: () => toggleSidebar(),
},
rightAction: {
icon: "settings-cog",
onClick: () => openSettings(),
},
},
});
Composer Customization
const { control } = useChatKit({
api: { /* ... */ },
composer: {
placeholder: "Ask me to manage your tasks...",
tools: [
{
id: "tasks",
label: "Tasks",
shortLabel: "Tasks",
icon: "list",
placeholderOverride: "What task would you like to add?",
pinned: true,
},
{
id: "search",
label: "Search",
shortLabel: "Search",
icon: "search",
placeholderOverride: "Search your tasks...",
pinned: true,
},
],
attachments: {
enabled: false, // Enable if backend supports
maxSize: 10 * 1024 * 1024, // 10MB
maxCount: 3,
accept: {
"image/*": [".png", ".jpg", ".jpeg"],
"application/pdf": [".pdf"],
},
},
},
});
Conversation History
const { control } = useChatKit({
api: { /* ... */ },
history: {
enabled: true,
showDelete: true,
showRename: true,
},
});
Embedding as Widget
For embedding the chatbot as a floating widget:
"use client";
import { useState } from "react";
import { ChatKit, useChatKit } from "@openai/chatkit-react";
export function FloatingChatWidget() {
const [isOpen, setIsOpen] = useState(false);
const { control } = useChatKit({
api: {
url: "/api/chat",
domainKey: process.env.NEXT_PUBLIC_OPENAI_DOMAIN_KEY,
},
});
return (
<>
{/* Toggle Button */}
<button
onClick={() => setIsOpen(!isOpen)}
className="fixed bottom-4 right-4 z-50 rounded-full bg-blue-600 p-4 text-white shadow-lg hover:bg-blue-700"
>
{isOpen ? "✕" : "💬"}
</button>
{/* Chat Widget */}
{isOpen && (
<div className="fixed bottom-20 right-4 z-50 h-[500px] w-[380px] overflow-hidden rounded-lg shadow-xl">
<ChatKit control={control} className="h-full w-full" />
</div>
)}
</>
);
}
Full Page Chat
"use client";
import { ChatKit, useChatKit } from "@openai/chatkit-react";
export default function ChatPage() {
const { control } = useChatKit({
api: {
url: "/api/chat",
domainKey: process.env.NEXT_PUBLIC_OPENAI_DOMAIN_KEY,
},
theme: {
colorScheme: "light",
},
startScreen: {
greeting: "Welcome! How can I help you today?",
},
});
return (
<div className="flex h-screen flex-col">
<header className="border-b p-4">
<h1 className="text-xl font-bold">Todo Chatbot</h1>
</header>
<main className="flex-1">
<ChatKit control={control} className="h-full w-full" />
</main>
</div>
);
}
OpenAI Domain Allowlist Setup
For production deployment:
- Deploy frontend to get production URL
-
Add domain to OpenAI allowlist:
- Go to: https://platform.openai.com/settings/organization/security/domain-allowlist
- Click "Add domain"
- Enter your frontend URL (without trailing slash)
- Get domain key and add to env variables
Note: localhost typically works without domain allowlist configuration.
Error Handling
const { control, error, isLoading } = useChatKit({
api: { /* ... */ },
});
if (error) {
return <div>Error: {error.message}</div>;
}
if (isLoading) {
return <div>Loading...</div>;
}
Best Practices
- Use "use client" - ChatKit requires client-side rendering
- Configure CORS - Ensure backend allows frontend origin
- Inject auth tokens - Use custom fetch for authenticated requests
- Handle errors - Show user-friendly error states
- Customize theming - Match your app's design system
- Use start screen prompts - Guide users on what they can do
- Enable history - Allow users to continue conversations
chat Comments (0)
Sign in to join the discussion and leave a comment.
Skill Details
GitHub Stars
66
GitHub Forks
19
Created
Mar 2026
Last Updated
il y a 6 mois
Related Skills
layers
No related skills found
Build your own?
Join 12,000+ developers contributing to the Claude ecosystem.
No comments yet. Be the first to share your thoughts!