npm package: @mastra/docusaurus-plugin-kapa
Description: Kapa.ai assistant plugin for Mastra's Docusaurus sites
Author: LekoArts
Latest version: 1.0.1

# @mastra/docusaurus-plugin-kapa

[Kapa.ai](https://kapa.ai) assistant plugin for Docusaurus. Adds an AI-powered chatbot sidebar to your documentation site, using Kapa's SDK to answer questions based on your docs.

## Installation

```bash
npm install @mastra/docusaurus-plugin-kapa
```

Also install the required peer dependencies:

```bash
npm install @docusaurus/theme-common @docusaurus/types clsx lucide-react react react-dom
```

## Usage

### 1. Register the plugin

Add it as a **theme** (not a plugin) in `docusaurus.config.ts`:

```ts
import type { Config } from '@docusaurus/types'
import type { KapaPluginOptions } from '@mastra/docusaurus-plugin-kapa'

const config: Config = {
	themes: [
		[
			'@mastra/docusaurus-plugin-kapa',
			{
				integrationId: process.env.KAPA_INTEGRATION_ID,
				groupId: process.env.KAPA_GROUP_ID,
			} satisfies KapaPluginOptions,
		],
	],
}

export default config
```

### 2. Wire up in `src/theme/Root.tsx`

The plugin provides theme components but does **not** inject its own `Root.tsx` (see [Architecture note](#architecture) below). You must wrap your app with `KapaProvider` and `ChatbotSidebarProvider` in your site's `Root.tsx`:

```tsx
import type { ReactNode } from 'react'
import { usePluginData } from '@docusaurus/useGlobalData'
import { KapaProvider } from '@kapaai/react-sdk'
import ChatbotSidebar from '@theme/ChatbotSidebar'
import { ChatbotSidebarProvider } from '@theme/ChatbotSidebar/context'

function KapaWrapper({ children }: { children: ReactNode }) {
	const pluginData = usePluginData('docusaurus-plugin-kapa', 'default', {
		failfast: false,
	}) as Record<string, unknown> | undefined

	const integrationId = (pluginData?.integrationId as string) || ''

	if (!integrationId) {
		return <>{children}</>
	}

	const groupId = (pluginData?.groupId as string) || undefined

	return (
		<KapaProvider
			integrationId={integrationId}
			{...(groupId && { sourceGroupIDsInclude: [groupId] })}
		>
			<ChatbotSidebarProvider defaultHidden={true}>
				{children}
				<ChatbotSidebar />
			</ChatbotSidebarProvider>
		</KapaProvider>
	)
}

export default function Root({ children }: { children: ReactNode }) {
	return <KapaWrapper>{children}</KapaWrapper>
}
```

### 3. Add a navbar toggle (optional)

Register the `KapaChatToggle` as a custom navbar item. In your `NavbarItem/ComponentTypes.tsx`:

```ts
import { KapaChatToggle } from '@theme/KapaChatToggle'

export default {
	'custom-kapaChat': KapaChatToggle,
}
```

Then add it to your navbar config:

```ts
themeConfig: {
	navbar: {
		items: [
			{ type: 'custom-kapaChat', position: 'right' },
		],
	},
},
```

### Options

| Option          | Type     | Required | Description                                                  |
| --------------- | -------- | -------- | ------------------------------------------------------------ |
| `integrationId` | `string` | Yes      | Your Kapa.ai integration ID                                  |
| `groupId`       | `string` | No       | Kapa source group ID for filtering which docs are searchable |

## Exports

The package has two entry points:

- **`@mastra/docusaurus-plugin-kapa`** — Plugin function, types, and the `useChatbotSidebar` hook
- **`@mastra/docusaurus-plugin-kapa/client`** — React components (`ChatbotSidebar`, `ChatbotSidebarProvider`, `KapaChatToggle`) and hook

### `useChatbotSidebar()`

Hook for programmatic control of the sidebar:

```ts
import { useChatbotSidebar } from '@mastra/docusaurus-plugin-kapa/client'

const { isHidden, toggle, open, close } = useChatbotSidebar()
```

## Features

- **Chatbot sidebar** — Fixed right-side panel (desktop only, ≥997px) with smooth open/close animations
- **Streaming responses** — Real-time response streaming with a stop button
- **Markdown rendering** — Rich text answers via CopilotKit
- **Message feedback** — Upvote/downvote on responses
- **Auto-scroll** — Sticks to bottom during streaming, with a manual scroll-to-bottom button
- **Conversation reset** — Clear chat history and start fresh
- **Context API** — Full programmatic control via React hooks

## Architecture

This plugin uses a **two-entry-point pattern**: `index.ts` (Node.js, no JSX) exports the plugin function, while `client.ts` (browser) exports React components. This is required because Docusaurus loads plugin entry files in Node.js before any bundler runs — JSX in the Node entry will crash.

The plugin does **not** provide its own `Root.tsx`. When a plugin is the only Root provider, `@theme-original/Root` resolves to itself, causing infinite recursion. Instead, `Root.tsx` lives in your site's `src/theme/` directory.