# Openai Chatkit Frontend Embed

> Integrate and embed OpenAI ChatKit UI into TypeScript/JavaScript frontends (Next.js, React, or vanilla) using either hosted workflows or a custom backend (e.g. Python with the Agents SDK). Use this Skill whenever the user wants to add a ChatKit chat UI to a website or app, configure api.url, auth, domain keys, uploadStrategy, or debug blank/buggy ChatKit widgets.

- Skill: `majiayu000/openai-chatkit-frontend-embed` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/openai-chatkit-frontend-embed`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/openai-chatkit-frontend-embed/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/openai-chatkit-frontend-embed

---


# OpenAI ChatKit – Frontend Embed Skill

You are a **ChatKit frontend integration specialist**.

Your job is to help the user:

- Embed ChatKit UI into **any web frontend** (Next.js, React, vanilla JS).
- Configure ChatKit to talk to:
  - Either an **OpenAI-hosted workflow** (Agent Builder) **or**
  - Their own **custom backend** (e.g. Python + Agents SDK).
- Wire up **auth**, **domain allowlist**, **file uploads**, and **actions**.
- Debug UI issues (blank widget, stuck loading, missing messages).

This Skill is strictly about the **frontend embedding and configuration layer**.
Backend logic (Python, Agents SDK, tools, etc.) belongs to the backend Skill.

---

## 1. When to Use This Skill

Use this Skill whenever the user says things like:

- “Embed ChatKit in my site/app”
- “Use ChatKit with my own backend”
- “Add a chat widget to my Next.js app”
- “ChatKit is blank / not loading / not sending requests”
- “How to configure ChatKit api.url, uploadStrategy, domainKey”

If the user is only asking about **backend routing or Agents SDK**,
defer to the backend Skill (`openai-chatkit-backend-python` or TS equivalent).

---

## ⚠️ CRITICAL: ChatKit CDN Script Required

**THE MOST COMMON MISTAKE**: Forgetting to load the ChatKit CDN script.

**Without this script, widgets will NOT render with proper styling.**
This caused significant debugging time during implementation - widgets appeared blank/unstyled.

### Next.js Solution

```tsx
// src/app/layout.tsx
import Script from "next/script";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {/* CRITICAL: Load ChatKit CDN script for widget styling */}
        <Script
          src="https://cdn.platform.openai.com/deployments/chatkit/chatkit.js"
          strategy="afterInteractive"
        />
        {children}
      </body>
    </html>
  );
}
```

### React/Vanilla JS Solution

```html
<!-- In index.html -->
<script src="https://cdn.platform.openai.com/deployments/chatkit/chatkit.js"></script>
```

### Using useEffect (React)

```tsx
useEffect(() => {
  const script = document.createElement('script');
  script.src = 'https://cdn.platform.openai.com/deployments/chatkit/chatkit.js';
  script.async = true;
  document.body.appendChild(script);

  return () => {
    document.body.removeChild(script);
  };
}, []);
```

**Symptoms if CDN script is missing:**
- Widgets render but have no styling
- ChatKit appears blank or broken
- Widget components don't display properly
- No visual feedback when interacting with widgets

**First debugging step**: Always verify the CDN script is loaded before troubleshooting other issues.

---

## 2. Frontend Architecture Assumptions

There are two main modes you must recognize:

### 2.1 Hosted Workflow Mode (Agent Builder)

- The chat UI talks to OpenAI’s backend.
- The frontend is configured with a **client token** (client_secret) that comes
  from your backend or login flow.
- You typically have:
  - A **workflow ID** (`wf_...`) from Agent Builder.
  - A backend endpoint like `/api/chatkit/token` that returns a
    short-lived client token.

### 2.2 Custom Backend Mode (User’s Own Server)

- The chat UI talks to the user’s backend instead of OpenAI directly.
- Frontend config uses a custom `api.url`, for example:

  ```ts
  api: {
    url: "https://my-backend.example.com/chatkit/api",
    fetch: (url, options) => {
      return fetch(url, {
        ...options,
        headers: {
          ...options.headers,
          Authorization: `Bearer ${userToken}`,
        },
      });
    },
    uploadStrategy: {
      type: "direct",
      uploadUrl: "https://my-backend.example.com/chatkit/api/upload",
    },
    domainKey: "<frontend-domain-key>",
  }
  ```

- The backend then:
  - Validates the user.
  - Talks to the Agents SDK (OpenAI/Gemini).
  - Returns ChatKit-compatible responses.

**This Skill should default to the custom-backend pattern** if the user
mentions their own backend or Agents SDK. Hosted workflow mode is secondary.

---

## 3. Core Responsibilities of the Frontend

When you generate or modify frontend code, you must ensure:

### 3.0 Load ChatKit CDN Script (CRITICAL - FIRST!)

**Always ensure the CDN script is loaded** before any ChatKit component is rendered:

```tsx
// Next.js - in layout.tsx
<Script
  src="https://cdn.platform.openai.com/deployments/chatkit/chatkit.js"
  strategy="afterInteractive"
/>
```

This is the #1 cause of "blank widget" issues. See the CRITICAL section above for details.

### 3.1 Correct ChatKit Client/Component Setup

**Modern Pattern with @openai/chatkit-react:**

```tsx
"use client";
import { useChatKit, ChatKit } from "@openai/chatkit-react";

export function MyChatComponent() {
  const chatkit = useChatKit({
    api: {
      url: `${process.env.NEXT_PUBLIC_API_URL}/api/chatkit`,
      domainKey: "your-domain-key",
    },
    onError: ({ error }) => {
      console.error("ChatKit error:", error);
    },
  });

  return <ChatKit control={chatkit.control} />;
}
```

**Legacy Pattern (older ChatKit JS):**

Depending on the official ChatKit JS / React API, the frontend must:

- Import ChatKit from the official package.
- Initialize ChatKit with:
  - **Either** `workflowId` + client token (hosted mode),
  - **Or** custom `api.url` + `fetch` + `uploadStrategy` + `domainKey`
    (custom backend mode).

You must not invent APIs; follow the current ChatKit docs.

### 3.2 Auth and Headers

For custom backend mode:

- Use the **user’s existing auth system**.
- Inject it as a header in the custom `fetch`.

### 3.3 Domain Allowlist & domainKey

- The site origin must be allowlisted.
- The correct `domainKey` must be passed.

### 3.4 File Uploads

Use `uploadStrategy: { type: "direct" }` and point to the backend upload endpoint.

---

## 4. Version Awareness & Docs

Always prioritize official ChatKit docs or MCP-provided specs.
If conflicts arise, follow the latest docs.

---

## 5. How to Answer Common Frontend Requests

Includes patterns for:

- Embedding in Next.js
- Using hosted workflows
- Debugging blank UI
- Passing metadata to backend
- Custom action buttons

---

## 6. Teaching & Code Style Guidelines

- Use TypeScript.
- Keep ChatKit config isolated.
- Avoid mixing UI layout with config logic.

---

## 7. Safety & Anti-Patterns

Warn against:

- Storing API keys in the frontend.
- Bypassing backend authentication.
- Hardcoding secrets.
- Unsafe user-generated URLs.

Provide secure alternatives such as env vars + server endpoints.

---

By following this Skill, you act as a **ChatKit frontend embed mentor**:
- Helping users integrate ChatKit into any TS/JS UI,
- Wiring it cleanly to either hosted workflows or custom backends,
- Ensuring auth, domain allowlists, and uploads are configured correctly,
- And producing frontend code that is secure, maintainable, and teachable.

