Ask AI Widget
AI-powered docs Q&A widget that searches your documentation and answers user questions
Ask AI Widget
Why
Users visiting your site often have questions but don't want to dig through documentation pages. The Ask AI widget provides an instant, conversational way to get answers — powered by your existing Fumadocs content.
Instead of browsing docs manually, users type a question and get a concise AI-generated answer based on your actual documentation.
What
A compact floating widget (bottom-right corner) that:
- Extracts keywords from the user's question using a fast model (
gpt-5-nano) - Searches your docs via the existing Fumadocs
/api/searchendpoint - Streams an AI answer based on the search results using
gpt-5-mini
The widget ships as a shared package (share-domains/ask-ai) with two parts:
components/— Client-side chat widget built on KUI AI elements + AI SDK v6logic/— Server-side utilities (keyword extraction, doc search, prompt building)
UI Behavior
| State | Appearance |
|---|---|
| Collapsed | Tiny input bar with 💬 icon + "Ask AI" placeholder |
| Focused | Input expands to 320px, empty chat panel appears |
| Active | Chat panel shows conversation, input stays expanded |
| Escape / Close | Collapses back to tiny input bar |
How
1. Environment Variables
Add to your .env:
# Required: Enable the widget
ENABLE_ASK_AI=true
# Required: OpenAI API access
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.openai.com/v1 # optional, for proxies
# Optional: Override default models
ASK_AI_MODEL=gpt-5-mini # Answer generation (default: gpt-5-mini)
ASK_AI_FAST_MODEL=gpt-5-nano # Keyword extraction (default: gpt-5-nano)
# Required: App URL for internal search API calls
NEXT_PUBLIC_APP_URL=http://localhost:30002. Add Tailwind Source
In your app's global.css, add the share-domains source so Tailwind scans the widget classes:
@source "../../../../packages/share-domains";3. Create the API Route
Create src/app/api/search/ai/route.ts:
import { createOpenAI } from "@ai-sdk/openai";
import { streamText } from "ai";
import { buildSystemPrompt, extractKeywords, searchDocs } from "share-domains/ask-ai/logic";
export async function POST(req: Request) {
const { messages } = await req.json();
const lastUserMessage = [...messages].reverse().find((m) => m.role === "user");
const question = lastUserMessage?.content || "";
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY,
baseURL: process.env.OPENAI_BASE_URL || undefined,
});
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";
const keywords = await extractKeywords(openai(process.env.ASK_AI_FAST_MODEL || "gpt-5-nano"), question);
const docsContext = await searchDocs(baseUrl, keywords);
const result = streamText({
model: openai(process.env.ASK_AI_MODEL || "gpt-5-mini"),
system: buildSystemPrompt(docsContext),
messages,
});
return result.toUIMessageStreamResponse();
}4. Add Widget to Layout
In your root layout.tsx (server component):
import { AskAIWidget } from "share-domains/ask-ai/components";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
{process.env.ENABLE_ASK_AI === "true" && (
<AskAIWidget
endpoint="/api/search/ai"
title="Ask MyApp"
placeholder="Ask AI"
welcomeMessage="Ask me anything!"
/>
)}
</body>
</html>
);
}Configuration Props
| Prop | Type | Default | Description |
|---|---|---|---|
endpoint | string | /api/search/ai | API route path |
placeholder | string | Ask AI | Input placeholder text |
title | string | AI Assistant | Chat panel header title |
welcomeMessage | string | "" | Message shown when panel is empty |
maxHeight | string | 480px | Max height of the chat panel |
Architecture
User types question
→ [Client] AskAIWidget (useChat + DefaultChatTransport)
→ [Server] POST /api/search/ai
→ extractKeywords(gpt-5-nano, question) → "i18n config setup"
→ searchDocs(baseUrl, keywords) → fumadocs /api/search
→ streamText(gpt-5-mini, docs context) → streamed answer
→ [Client] MessageResponse renders markdownPrerequisites
- Fumadocs with
/api/searchroute configured @ai-sdk/openai,aipackages installedshare-domainsas workspace dependencykuias workspace dependency (for AI elements)