Files
mintlify__docs/guides/assistant-embed.mdx
2026-01-30 10:34:54 -08:00

213 lines
6.0 KiB
Plaintext

---
title: "Tutorial: Build an in-app documentation assistant"
sidebarTitle: "Build an in-app assistant"
description: "Embed the assistant in your application to answer questions with information from your documentation."
keywords: ["assistant embed", "in-app chat", "widget", "chatbot"]
---
## What you will build
A reusable widget that embeds the [assistant](/ai/assistant) directly in your application. The widget provides:
- A floating button that opens a chat panel when clicked
- Real-time streaming responses based on information from your documentation
- Message rendering with Markdown support
Users can use the widget to get help with your product without leaving your application.
<Frame>
<img src="/images/assistant/assistant-embed-demo.gif" alt="Demo of the assistant widget being opened and the user typing in How do I get started? Then the assistant responds." />
</Frame>
## Prerequisites
- [Mintlify Pro or Enterprise plan](https://mintlify.com/pricing)
- Your domain name, which appears at the end of your dashboard URL. For example, if your dashboard URL is `https://dashboard.mintlify.com/org-name/domain-name`, your domain name is `domain-name`
- An [assistant API key](https://dashboard.mintlify.com/settings/organization/api-keys)
- Node.js v18 or higher and npm installed
- Basic React knowledge
### Get your assistant API key
1. Navigate to the [API keys](https://dashboard.mintlify.com/settings/organization/api-keys) page in your dashboard.
2. Click **Create Assistant API Key**.
3. Copy the assistant API key (starts with `mint_dsc_`) and save it securely.
<Note>
The assistant API key is a public token that you can use in frontend code. Calls using this token count toward your plan's message allowance and can incur overages.
</Note>
## Set up the example
Clone the [example repository](https://github.com/mintlify/assistant-embed-example) and customize it for your needs.
<Steps>
<Step title="Clone the repository">
```bash
git clone https://github.com/mintlify/assistant-embed-example.git
cd assistant-embed-example
```
</Step>
<Step title="Choose your development tool">
The repository includes Next.js and Vite examples. Choose the tool you prefer to use.
<CodeGroup>
```bash title="Next.js"
cd nextjs
npm install
```
```bash title="Vite"
cd vite
npm install
```
</CodeGroup>
</Step>
<Step title="Configure your project">
Open `src/config.js` and update with your Mintlify project details.
```js src/config.js
export const ASSISTANT_CONFIG = {
domain: 'your-domain',
docsURL: 'https://yourdocs.mintlify.app',
};
```
Replace:
- `your-domain` with your Mintlify project domain found at the end of your dashboard URL.
- `https://yourdocs.mintlify.app` with your actual documentation URL.
</Step>
<Step title="Add your API token">
Create a `.env` file in the project root.
```bash .env
VITE_MINTLIFY_TOKEN=mint_dsc_your_token_here
```
Replace `mint_dsc_your_token_here` with your assistant API key.
</Step>
<Step title="Start the development server">
```bash
npm run dev
```
Open your application in a browser and click the **Ask** button to open the assistant widget.
</Step>
</Steps>
## Customization ideas
### Source citations
Extract and display sources from assistant responses:
```jsx
const extractSources = (parts) => {
return parts
?.filter(p => p.type === 'tool-invocation' && p.toolInvocation?.toolName === 'search')
.flatMap(p => p.toolInvocation?.result || [])
.map(source => ({
url: source.url || source.path,
title: source.metadata?.title || source.path,
})) || [];
};
// In your message rendering:
{messages.map((message) => {
const sources = message.role === 'assistant' ? extractSources(message.parts) : [];
return (
<div key={message.id}>
{/* message content */}
{sources.length > 0 && (
<div className="mt-2 text-xs">
<p className="font-semibold">Sources:</p>
{sources.map((s, i) => (
<a key={i} href={s.url} target="_blank" rel="noopener noreferrer" className="text-blue-600">
{s.title}
</a>
))}
</div>
)}
</div>
);
})}
```
### Track conversation thread IDs
Store thread IDs to maintain conversation history across sessions:
```jsx
import { useState, useEffect } from 'react';
export function AssistantWidget({ domain, docsURL }) {
const [threadId, setThreadId] = useState(null);
useEffect(() => {
// Retrieve saved thread ID from localStorage
const saved = localStorage.getItem('assistant-thread-id');
if (saved) {
setThreadId(saved);
}
}, []);
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: `https://api.mintlify.com/discovery/v1/assistant/${domain}/message`,
headers: {
'Authorization': `Bearer ${import.meta.env.VITE_MINTLIFY_TOKEN}`,
},
body: {
fp: 'anonymous',
retrievalPageSize: 5,
...(threadId && { threadId }), // Include thread ID if available
},
streamProtocol: 'data',
sendExtraMessageFields: true,
fetch: async (url, options) => {
const response = await fetch(url, options);
const newThreadId = response.headers.get('x-thread-id');
if (newThreadId) {
setThreadId(newThreadId);
localStorage.setItem('assistant-thread-id', newThreadId);
}
return response;
},
});
// ... rest of component
}
```
### Add keyboard shortcuts
Allow users to open the widget and submit messages with keyboard shortcuts:
```jsx
useEffect(() => {
const handleKeyDown = (e) => {
// Cmd/Ctrl + Shift + I to toggle widget
if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === 'I') {
e.preventDefault();
setIsOpen((prev) => !prev);
}
// Enter (when widget is focused) to submit
if (e.key === 'Enter' && !e.shiftKey && document.activeElement.id === 'assistant-input') {
e.preventDefault();
handleSubmit();
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [handleSubmit]);
```