A lightweight floating AI assistant for VuePress and VitePress documentation sites.
docs-ai-helper gives your docs a chat panel that can stream answers, render Markdown, highlight code with Shiki, carry page context to your backend, show reasoning blocks, follow internal documentation links, and fit into existing themes with CSS variables.
vue-demidata: eventsnpm install docs-ai-helper vue-demi
If you do not pass your own renderMarkdown function, the fallback renderer dynamically imports shiki:
npm install shiki
For Vue 2 projects below Vue 2.7, also install and register @vue/composition-api.
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme';
import { h } from 'vue';
import { useRouter } from 'vitepress';
import { DocsAiHelper, createVitePressNavigator } from 'docs-ai-helper';
import 'docs-ai-helper/style.css';
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('DocsAiHelper', DocsAiHelper);
},
Layout() {
const router = useRouter();
return h(DefaultTheme.Layout, null, {
'layout-bottom': () => h(DocsAiHelper, {
endpoint: '/api/docs-chat',
navigate: createVitePressNavigator(router),
context: () => ({
path: window.location.pathname,
title: document.title
}),
suggestedQuestions: [
{ label: 'How do I get started?' },
{ label: 'Explain this page' },
{ label: 'Show me a TypeScript example' }
]
})
});
}
};
// client.ts / enhanceApp.ts
import { h } from 'vue';
import { DocsAiHelper, createVuePressNavigator } from 'docs-ai-helper';
import 'docs-ai-helper/style.css';
export default ({ app, router }) => {
app.component('DocsAiHelperHost', {
render() {
return h(DocsAiHelper, {
endpoint: '/api/docs-chat',
navigate: createVuePressNavigator(router),
context: () => ({
path: window.location.pathname,
title: document.title
})
});
}
});
};
By default, the component sends POST requests to endpoint with this JSON body:
{
"question": "User question",
"context": {},
"messages": [{ "role": "user", "content": "..." }]
}
The default stream parser accepts plain text chunks and SSE-style events:
data: {"content":"Answer chunk","reasoning":"Reasoning chunk"}
data: [DONE]
It also understands common OpenAI-compatible choices[0].delta.content payloads. Use requestBody or parseStream when your backend has a different protocol.
For the best visual match, pass the same Markdown renderer your docs site already uses:
h(DocsAiHelper, {
endpoint: '/api/docs-chat',
renderMarkdown: (markdown, message) => docsMarkdownRenderer.render(markdown)
});
Without renderMarkdown, the built-in fallback uses markdown-it and dynamically imports shiki for fenced code blocks:
import { createShikiMarkdownRenderer } from 'docs-ai-helper';
h(DocsAiHelper, {
endpoint: '/api/docs-chat',
renderMarkdown: createShikiMarkdownRenderer({
theme: { light: 'github-light', dark: 'github-dark' },
fallbackLang: 'text'
})
});
h(DocsAiHelper, {
endpoint: '/api/docs-chat',
headers: { Authorization: 'Bearer ...' },
assistant: { name: 'Docs Assistant', avatar: '/bot.png' },
user: { name: 'You', avatar: '/me.png' },
defaultOpen: false,
showReasoningDefault: true,
allowReasoningToggle: true,
launcherText: 'AI',
launcherMode: 'fixed',
launcherVariant: 'primary',
size: { width: 460, height: 660 },
maxWidth: 960,
maxHeight: 900,
closeOnClear: false,
cssVars: {
'--dah-accent': '#0f766e',
'--dah-radius': '6px'
},
panelClass: 'my-docs-ai-panel',
launcherClass: 'my-docs-ai-launcher',
suggestedQuestions: [
{ label: 'What is this page about?' },
{
label: 'Give me a TypeScript example',
question: 'Give me a TypeScript example based on the current page.'
}
],
welcome: {
title: 'Hi, I am your docs assistant',
description: 'Choose a suggestion or ask your own question.'
},
context: () => ({
path: location.pathname,
title: document.title
})
});
import DocsAiHelperPlugin, {
DocsAiHelper,
createShikiMarkdownRenderer,
createVitePressNavigator,
createVuePressNavigator,
defaultMarkdownRenderer,
defaultNavigate,
defaultStreamParser
} from 'docs-ai-helper';
import type {
ChatMessage,
ChatRequestContext,
MarkdownRenderer,
NavigateHandler,
RequestBodyBuilder,
StreamParser
} from 'docs-ai-helper';
:root {
--dah-font-family: Inter, ui-sans-serif, system-ui, sans-serif;
--dah-z-index: 2147481000;
--dah-accent: #2563eb;
--dah-accent-strong: #1d4ed8;
--dah-bg: #ffffff;
--dah-surface: #f8fafc;
--dah-border: #d9e2ec;
--dah-text: #172033;
--dah-muted: #64748b;
--dah-shadow: 0 18px 50px rgba(15, 23, 42, 0.18);
--dah-radius: 8px;
}
You can also override .dah-* classes directly for deeper styling.
version in package.json.npm run typecheck.npm run build.npm pack --dry-run.npm publish --access public.The package includes dist, README.md, README_ZH.md, and LICENSE. The prepublishOnly script runs type checking and a production build before publishing.
MIT License. Copyright (c) ZhaiSoul.