Skip to content
chatkit-frontend logo

ChatKit Frontend Skill

chatkit-frontend

Build production-ready chat UI with OpenAI ChatKit React components. Handles ChatKit installation, useChatKit hook configuration, theming, streaming display, conversation sidebar, and rich widgets. Use when implementing chat interface, migrating from custom UI to ChatKit, or adding AI chat featur...

SKILL.md

Full skill instructions

ChatKit Frontend Skill

Production-ready skill for implementing OpenAI ChatKit in Next.js applications.

Official Documentation (ALWAYS verify before implementation):


Overview

OpenAI ChatKit is a batteries-included framework for building AI-powered chat experiences with:

  • Deep UI Customization - Theme, colors, radius, typography
  • Built-in Streaming - Natural real-time conversations
  • Tool Integration - Display agent actions and reasoning
  • Interactive Widgets - Rich content in chat messages
  • File Handling - Upload and attachment support
  • Thread Management - Conversation history and switching

Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                        Next.js Frontend                                  │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ┌──────────────────┐      ┌──────────────────────────────────────────┐ │
│  │ ConversationSidebar │    │  ChatKit Component                       │ │
│  │ (Custom)            │    │  ┌────────────────────────────────────┐  │ │
│  │                     │    │  │  <ChatKit control={control} />     │  │ │
│  │ - Thread list       │◄──►│  │  - Messages                        │  │ │
│  │ - New chat          │    │  │  - Input                           │  │ │
│  │ - Delete/​rename     │    │  │  - Streaming                       │  │ │
│  └──────────────────┘      │  │  - Tool indicators                 │  │ │
│                             │  └────────────────────────────────────┘  │ │
│                             └──────────────────────────────────────────┘ │
│                                              │                           │
│                          ┌───────────────────▼───────────────────┐      │
│                          │  useChatKit Hook                       │      │
│                          │  - api: { url, domainKey }             │      │
│                          │  - theme: { colorScheme, radius }      │      │
│                          │  - startScreen: { greeting, prompts }  │      │
│                          │  - onClientTool: (invocation) => {}    │      │
│                          └───────────────────┬───────────────────┘      │
└──────────────────────────────────────────────┼───────────────────────────┘
                                               │ SSE Stream
                          ┌────────────────────▼────────────────────┐
                          │  FastAPI Backend                         │
                          │  POST /​chatkit                           │
                          │  - ChatKit-compatible SSE format         │
                          └─────────────────────────────────────────┘

Installation

Step 1: Install ChatKit Package

cd frontend
npm install @openai/​chatkit-react

Step 2: Verify Installation

# Check package.json
grep chatkit package.json

Quick Start

Basic ChatKit Integration

// app/​chat/​page.tsx
'use client';

import { ChatKit, useChatKit } from '@openai/​chatkit-react';

export default function ChatPage() {
  const { control } = useChatKit({
    api: {
      url: `${process.env.NEXT_PUBLIC_API_URL}/​chatkit`,
      domainKey: process.env.NEXT_PUBLIC_OPENAI_DOMAIN_KEY || 'local-dev',
    },
  });

  return (
    <div className="h-screen w-full">
      <ChatKit control={control} className="h-full w-full" />
    </​div>
  );
}

With Full Configuration

// app/​chat/​page.tsx
'use client';

import { ChatKit, useChatKit } from '@openai/​chatkit-react';
import { useAuthStore } from '@/​stores/​auth-store';
import { useConversationStore } from '@/​stores/​conversation-store';

export default function ChatPage() {
  const { user } = useAuthStore();
  const { currentConversation, refreshConversations } = useConversationStore();

  const { control } = useChatKit({
    // API Configuration
    api: {
      url: `${process.env.NEXT_PUBLIC_API_URL}/​chatkit`,
      domainKey: process.env.NEXT_PUBLIC_OPENAI_DOMAIN_KEY || 'local-dev',
    },

    // Theme Configuration
    theme: {
      colorScheme: 'light', // 'light' | 'dark' | 'system'
      radius: 'round',      // 'sharp' | 'round' | 'pill'
      color: {
        accent: { primary: '#0066cc', level: 2 },
        grayscale: { hue: 220, tint: 6, shade: -4 },
      },
    },

    // Start Screen
    startScreen: {
      greeting: `Hello${user?.name ? `, ${user.name}` : ''}! How can I help you today?`,
      prompts: [
        'Show my tasks',
        'Add a new task',
        'What tasks are due today?',
        'Mark my grocery task as complete',
      ],
    },

    // Header Configuration
    header: {
      enabled: true,
      title: 'Task Assistant',
    },

    // Composer Configuration
    composer: {
      placeholder: 'Ask about your tasks...',
    },

    // History (built-in - optional, we use custom sidebar)
    history: {
      enabled: false, // Disable built-in, use custom ConversationSidebar
    },

    // Client-side Tool Handling
    onClientTool: async (invocation) => {
      console.log('Client tool invoked:', invocation.name, invocation.params);

      // Handle client-side tools (theme switching, etc.)
      if (invocation.name === 'switch_theme') {
        // Handle theme change
        return { success: true };
      }

      return { success: false };
    },

    // Error Handling
    onError: ({ error }) => {
      console.error('ChatKit error:', error);
    },

    // Message Events
    onMessage: (message) => {
      console.log('New message:', message);
      // Refresh conversations after message
      refreshConversations();
    },
  });

  return (
    <div className="h-screen w-full">
      <ChatKit
        control={control}
        className="h-full w-full max-w-4xl mx-auto"
      />
    </​div>
  );
}

Project Structure

frontend/
├── app/
│   └── chat/
│       ├── layout.tsx              # Chat layout with sidebar
│       └── page.tsx                # ChatKit page
│
├── components/
│   ├── chat/
│   │   └── ChatKitWrapper.tsx      # Optional ChatKit wrapper
│   │
│   └── conversation/               # Custom sidebar (keep existing)
│       ├── ConversationSidebar.tsx
│       ├── ConversationList.tsx
│       ├── ConversationItem.tsx
│       └── NewChatButton.tsx
│
├── stores/
│   └── conversation-store.ts       # Conversation state (keep existing)
│
└── lib/
    └── chatkit/
        └── config.ts               # ChatKit configuration utilities

Theming

Dark Mode Support

'use client';

import { ChatKit, useChatKit } from '@openai/​chatkit-react';
import { useTheme } from 'next-themes';

export function ThemedChatKit() {
  const { theme } = useTheme();
  const isDark = theme === 'dark';

  const { control } = useChatKit({
    api: { url: '/​chatkit', domainKey: 'local-dev' },
    theme: {
      colorScheme: isDark ? 'dark' : 'light',
      radius: 'round',
      color: {
        grayscale: {
          hue: 220,
          tint: 6,
          shade: isDark ? -1 : -4,
        },
        accent: {
          primary: isDark ? '#f1f5f9' : '#0f172a',
          level: 1,
        },
      },
    },
  });

  return <ChatKit control={control} className="h-full w-full" />;
}

Tailwind CSS Integration

<ChatKit
  control={control}
  className="
    h-full w-full
    [--chatkit-bg:hsl(var(--background))]
    [--chatkit-text:hsl(var(--foreground))]
    [--chatkit-primary:hsl(var(--primary))]
    [--chatkit-border:hsl(var(--border))]
  "
/>

Conversation Management

Custom Sidebar with ChatKit

// app/​chat/​layout.tsx
'use client';

import { ConversationSidebar } from '@/​components/​conversation/​ConversationSidebar';

export default function ChatLayout({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex h-screen">
      {/​* Custom Conversation Sidebar */​}
      <ConversationSidebar />

      {/​* ChatKit Area */​}
      <div className="flex-1 overflow-hidden">
        {children}
      </​div>
    </​div>
  );
}

Thread Switching

// When user selects a conversation from sidebar
const handleSelectConversation = (conversationId: number) => {
  // Update URL or state
  router.push(`/​chat?thread=${conversationId}`);

  // ChatKit will load the thread automatically if configured
};

Environment Variables

# Frontend (.env.local)
NEXT_PUBLIC_API_URL=http://localhost:8000

# ChatKit Domain Key (REQUIRED for production)
# Get from: https://platform.openai.com/​settings/​organization/​security/​domain-allowlist
NEXT_PUBLIC_OPENAI_DOMAIN_KEY=your-domain-key-here

Domain Allowlist Configuration (Production)

  1. Deploy frontend to get production URL (e.g., https://your-app.vercel.app)
  2. Go to: https://platform.openai.com/settings/organization/security/domain-allowlist
  3. Add your production domain
  4. Copy domain key to NEXT_PUBLIC_OPENAI_DOMAIN_KEY

Note: localhost works without domain allowlist configuration.


Migration from Custom UI

Before (Custom Components)

// OLD: Custom chat interface
import { ChatContainer } from '@/​components/​chat/​ChatContainer';
import { MessageList } from '@/​components/​chat/​MessageList';
import { MessageInput } from '@/​components/​chat/​MessageInput';

export default function ChatPage() {
  return (
    <ChatContainer>
      <MessageList messages={messages} />
      <MessageInput onSend={sendMessage} />
    </​ChatContainer>
  );
}

After (ChatKit)

// NEW: ChatKit
import { ChatKit, useChatKit } from '@openai/​chatkit-react';

export default function ChatPage() {
  const { control } = useChatKit({
    api: { url: '/​chatkit', domainKey: 'local-dev' },
  });

  return <ChatKit control={control} className="h-full w-full" />;
}

What to Keep

  • ConversationSidebar - Better UX than built-in history
  • conversation-store.ts - Thread management state
  • Auth integration - User context for ChatKit

What to Remove

  • ChatContainer.tsx - Replaced by ChatKit
  • MessageList.tsx - Replaced by ChatKit
  • MessageInput.tsx - Replaced by ChatKit
  • StreamingMessage.tsx - Replaced by ChatKit
  • Custom SSE client (partially) - ChatKit handles streaming

Verification Checklist

  • @openai/​chatkit-react installed
  • ChatKit page created at /​chat
  • useChatKit hook configured with API URL
  • Theme matches app design system
  • Dark mode works correctly
  • Start screen shows greeting and prompts
  • Custom ConversationSidebar integrated
  • Backend /​chatkit endpoint working
  • Streaming responses display correctly
  • Domain allowlist configured (production)
  • Mobile responsive design

Common Issues

ChatKit Not Rendering

// Ensure client-side rendering
'use client';

// Check control is initialized
if (!control) return <div>Loading...</​div>;

CORS Errors

# Backend: Add ChatKit origins to CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "https://your-app.vercel.app"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

SSE Format Issues

# Backend: Use correct SSE format for ChatKit
yield f"data: {json.dumps({'type': 'text', 'content': chunk})}\n\n"
yield "data: [DONE]\n\n"

See Also

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View