@convokit/widget
v0.1.18
Published
AI chat widget for your website
Maintainers
Readme
@convokit/widget
Drop a chat widget into your React or Next.js app with one component. You give it an API key, it gives your users a working AI chat trained on your own docs, FAQs, or support content — whatever you upload to the ConvoKit dashboard.
Website: convokit.dev
Before you start
You need a ConvoKit account and a public API key. Here's the order:
- Sign up at convokit.dev
- Go to your dashboard and grab your public key — it starts with
pk_live_ - Upload content to your knowledge base (FAQ page, support docs, a product guide — whatever you want the AI to know)
- Come back here and follow the install steps below
Install
npm install @convokit/widget
# or
yarn add @convokit/widget
# or
pnpm add @convokit/widgetBasic usage
React / Vite
import { PopupWidget } from '@convokit/widget';
export function App() {
return (
<div>
{/* rest of your app */}
<PopupWidget apiKey={import.meta.env.VITE_CONVOKIT_KEY ?? ''} />
</div>
);
}Store your key in .env:
VITE_CONVOKIT_KEY=pk_live_your_key_hereThat's it. A chat bubble shows up in the bottom-right corner, and it already knows about whatever you uploaded.
Next.js App Router (the easy way)
Use PopupWidgetNext — it handles the ssr: false dynamic import for you automatically:
// app/layout.tsx
import { PopupWidgetNext } from '@convokit/widget/next';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<PopupWidgetNext apiKey={process.env.NEXT_PUBLIC_CONVOKIT_KEY ?? ''} />
</body>
</html>
);
}Add to .env.local:
NEXT_PUBLIC_CONVOKIT_KEY=pk_live_your_key_herePopupWidgetNext also reads NEXT_PUBLIC_CONVOKIT_KEY automatically, so if you've set that env var, you can even skip the apiKey prop entirely:
<PopupWidgetNext />Next.js App Router (manual approach)
If you prefer to control the dynamic import yourself:
'use client';
import dynamic from 'next/dynamic';
const PopupWidget = dynamic(
() => import('@convokit/widget').then((m) => m.PopupWidget),
{ ssr: false }
);
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<PopupWidget apiKey={process.env.NEXT_PUBLIC_CONVOKIT_KEY ?? ''} />
</>
);
}No separate CSS import needed — styles are bundled inside the package.
Vanilla JS / WordPress / any static site (no framework)
If you're not using React, use the standalone script. Just drop it into your HTML:
<!-- Auto-init using data attributes -->
<script
src="https://cdn.jsdelivr.net/npm/@convokit/widget/dist/convokit-standalone.iife.js"
data-api-key="pk_live_your_key_here"
defer
></script>Or initialize it manually for more control:
<script src="https://cdn.jsdelivr.net/npm/@convokit/widget/dist/convokit-standalone.iife.js" defer></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
window.ConvoKit.init({
apiKey: 'pk_live_your_key_here',
title: 'Help Center',
primaryColor: '#7c3aed',
position: 'bottom-right',
});
});
</script>To remove the widget later (e.g. after logout):
window.ConvoKit.destroy();All props
These work on <PopupWidget>, <PopupWidgetNext>, and window.ConvoKit.init().
The key one
| Prop | Type | Description |
|------|------|-------------|
| apiKey | string | Your public key from the ConvoKit dashboard. Starts with pk_live_. Required. |
Text and content
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| title | string | 'Support' | The name shown in the chat header |
| welcomeMessage | string | 'Hi! How can we help?' | The first message the user sees when they open the chat |
| placeholder | string | 'Type a message...' | Placeholder text inside the input box |
Position
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| position | string | 'bottom-right' | Where the chat bubble sits. Options: 'bottom-right', 'bottom-left', 'bottom-middle', 'top-right', 'top-left', 'top-middle' |
Colors and fonts
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| primaryColor | string | '#2563eb' | The main accent color — used for the header, bubble, and send button. Any valid CSS color works: hex, rgb, hsl. |
| fontFamily | string | 'Inter, system-ui, sans-serif' | Font for all chat text. Use any CSS font stack. |
| fontSize | string | '14px' | Size for all chat text. Any valid CSS unit: px, rem, em. |
Logo / bubble icon
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| logoUrl | string | — | URL of an image to show inside the chat bubble (SVG, PNG, JPG). If you skip this, a default chat icon is used. |
| logoFit | 'contain' or 'cover' | 'contain' | Controls how your logo fills the bubble. contain keeps padding around the image. cover fills the entire circle edge-to-edge. |
Behaviour
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| persistMessages | boolean | false | When true, chat history is saved in localStorage and restored when the user comes back. |
| instanceId | string | 'convokit-widget' | An ID for this widget instance. Useful if you have multiple widgets on the same page, or want to isolate stored messages. |
Examples
Change the color and move it to the left
<PopupWidget
apiKey="pk_live_..."
primaryColor="#7c3aed"
position="bottom-left"
/>Custom font to match your brand
<PopupWidget
apiKey="pk_live_..."
fontFamily="'Inter', sans-serif"
fontSize="15px"
/>Logo that fills the whole bubble
By default, logos have a bit of padding around them. If you want the image to completely fill the circle (good for square logos or photos):
<PopupWidget
apiKey="pk_live_..."
logoUrl="https://yoursite.com/logo.png"
logoFit="cover"
/>contain (default) — image is centered with padding:
╭──────╮
│ 🖼 │ ← padding visible around the image
╰──────╯cover — image fills the entire button:
╭──────╮
│██████│ ← image goes edge to edge
╰──────╯Remember messages across page reloads
<PopupWidget
apiKey="pk_live_..."
persistMessages={true}
/>Custom welcome message and placeholder
<PopupWidget
apiKey="pk_live_..."
title="ConvoKit Support"
welcomeMessage="Hey! Ask me anything about ConvoKit."
placeholder="What do you want to know?"
/>Full example with everything
<PopupWidget
apiKey="pk_live_..."
title="Help Center"
welcomeMessage="Hi! What can I help you with today?"
placeholder="Ask a question..."
primaryColor="#0f172a"
position="bottom-right"
fontFamily="'Geist', 'Inter', sans-serif"
fontSize="14px"
logoUrl="https://yoursite.com/icon.png"
logoFit="cover"
persistMessages={true}
/>Setting an env variable (the right way)
Never paste your API key directly into code that gets committed. Use environment variables:
React / Vite — .env file:
VITE_CONVOKIT_KEY=pk_live_your_key_here<PopupWidget apiKey={import.meta.env.VITE_CONVOKIT_KEY ?? ''} />Next.js — .env.local file:
NEXT_PUBLIC_CONVOKIT_KEY=pk_live_your_key_here<PopupWidget apiKey={process.env.NEXT_PUBLIC_CONVOKIT_KEY ?? ''} />The NEXT_PUBLIC_ prefix is required — Next.js only exposes env vars with that prefix to the browser.
Common issues
"Cannot read properties of undefined (reading 'ReactCurrentDispatcher')"
This is a duplicate React error — your app and the widget are loading two separate copies of React. Add this to your next.config.js:
const nextConfig = {
transpilePackages: ['@convokit/widget'],
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
react: require.resolve('react'),
'react-dom': require.resolve('react-dom'),
};
return config;
},
};
module.exports = nextConfig;Widget doesn't show up at all
Check the browser console. The most common cause is a wrong or missing API key. Your key should start with pk_live_ — not sk_live_ (that's your secret key and should never go in the browser).
Chat responds but doesn't seem to know about my docs
Make sure you've actually uploaded content in the ConvoKit dashboard and that it finished processing. There's a small delay after uploading while the content gets indexed.
License
MIT
