npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@convokit/widget

v0.1.18

Published

AI chat widget for your website

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:

  1. Sign up at convokit.dev
  2. Go to your dashboard and grab your public key — it starts with pk_live_
  3. Upload content to your knowledge base (FAQ page, support docs, a product guide — whatever you want the AI to know)
  4. Come back here and follow the install steps below

Install

npm install @convokit/widget
# or
yarn add @convokit/widget
# or
pnpm add @convokit/widget

Basic 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_here

That'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_here

PopupWidgetNext 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