name: ask-ai description: Configure the Ask AI (RAG-powered AI chat) in @farming-labs/docs. Use when enabling AI chat, setting mode (search vs floating), floatingStyle (panel, modal, popover, full-modal), position, providers, models, suggestedQuestions, apiKey, systemPrompt, maxResults, useMcp, feedback, or onActions. Covers Next.js, TanStack Start, SvelteKit, Astro, Nuxt, and env vars.
@farming-labs/docs — Ask AI (AI Chat)
Add a built-in AI chat that answers questions using your documentation. The AI searches relevant pages, builds context, and streams a response from an OpenAI-compatible LLM. Use this skill when configuring the Ask AI / DocsBot feature.
Full docs: Ask AI.
Quick start
ai: {
enabled: true,
}
The AI reads process.env.OPENAI_API_KEY and uses gpt-4o-mini by default. Add OPENAI_API_KEY to your .env file. For SvelteKit/Astro, pass the API key into the docs server config (see below).
Configuration reference
All options go inside the ai object in docs.config.ts.
enabled
| Type | Default |
|---|---|
boolean |
false |
ai: { enabled: true }
mode
How the AI chat UI is presented.
| Type | Default |
|---|---|
"search" | "floating" |
"search" |
"search"— AI tab inside the Cmd+K search dialog. Users switch between "Search" and "AI" tabs."floating"— Floating chat widget with a button; opens as panel, modal, popover, or full-modal.
ai: { enabled: true, mode: "floating" }
position
Position of the floating button. Only when mode is "floating".
| Type | Default |
|---|---|
"bottom-right" | "bottom-left" | "bottom-center" |
"bottom-right" |
floatingStyle
Visual style when the floating chat is opened. Only when mode is "floating".
| Type | Default |
|---|---|
"panel" | "modal" | "popover" | "full-modal" |
"panel" |
"panel"— Tall panel sliding up from the button; no full backdrop."modal"— Centered modal with backdrop (like Cmd+K)."popover"— Compact popover near the button."full-modal"— Full-screen overlay; messages in center, input at bottom, suggested questions as pills.
ai: { enabled: true, mode: "floating", floatingStyle: "full-modal" }
model
Single model (string) or multiple models with UI dropdown (object).
Single model: model: "gpt-4o-mini" (default) or "gpt-4o", etc.
Multiple models:
ai: {
enabled: true,
model: {
models: [
{ id: "gpt-4o-mini", label: "GPT-4o mini (fast)", provider: "openai" },
{ id: "gpt-4o", label: "GPT-4o (quality)", provider: "openai" },
{ id: "llama-3.3-70b-versatile", label: "Llama 3.3 70B", provider: "groq" },
],
defaultModel: "gpt-4o-mini",
},
}
Each model: id (API model id), label (UI name), provider (optional, key in providers). If provider is omitted, the default baseUrl and apiKey are used.
providers
Named provider configs so multiple backends (OpenAI, Groq, etc.) can coexist.
ai: {
enabled: true,
providers: {
openai: {
baseUrl: "https://api.openai.com/v1",
apiKey: process.env.OPENAI_API_KEY,
},
groq: {
baseUrl: "https://api.groq.com/openai/v1",
apiKey: process.env.GROQ_API_KEY,
},
},
model: {
models: [
{ id: "gpt-4o-mini", label: "GPT-4o mini", provider: "openai" },
{ id: "llama-3.3-70b-versatile", label: "Llama 3.3 70B", provider: "groq" },
],
defaultModel: "gpt-4o-mini",
},
}
All providers must be OpenAI Chat Completions API compatible.
baseUrl and apiKey
Default base URL and API key when no per-model provider is set. Defaults: baseUrl = OpenAI v1, apiKey = process.env.OPENAI_API_KEY. Never hardcode API keys; use env vars.
suggestedQuestions
Pre-filled questions shown when the chat is empty. Clicking one submits it.
| Type | Default |
|---|---|
string[] |
[] |
ai: {
enabled: true,
suggestedQuestions: [
"How do I get started?",
"What themes are available?",
"How do I create a custom component?",
],
}
systemPrompt
Custom system prompt prepended to the conversation. Doc context is appended automatically.
ai: {
enabled: true,
systemPrompt: "You are a friendly assistant for Acme Corp. Always mention our support email for complex issues.",
}
maxResults
Number of search results used as context for the AI. More = more context, higher token usage.
| Type | Default |
|---|---|
number |
5 |
feedback
Copy, like, and dislike action row shown after a completed Ask AI answer. Set feedback: false to
hide the row.
| Type | Default |
|---|---|
boolean | { enabled?: boolean; onFeedback?: (data) => void | Promise<void> } |
true |
onActions
Single callback for copy, like, and dislike actions. Use data.type to branch.
ai: {
enabled: true,
onActions(data) {
if (data.type === "copy") console.log("Copied", data.answer);
if (data.type === "like") console.log("Helpful", data.question);
if (data.type === "dislike") console.log("Not helpful", data.question);
},
}
The callback receives the action type, question, answer, model, UI surface, URL/path, visible chat
messages up to that answer, and copied for copy actions. Like/dislike also dispatch the legacy
fd:ai-feedback browser event and emit ai_feedback when analytics is enabled. All actions
dispatch fd:ai-action.
Retrieval quality
Ask AI uses the configured docs search pipeline before building model context, including simple search, Typesense, Algolia, MCP search, or custom adapters. The model context is hydrated from the matched local page/section, preserves fenced code blocks for commands and config snippets, and infers package names plus exact import lines from the retrieved context.
Use ai.useMcp: true when only Ask AI should retrieve through the built-in MCP search_docs tool
while the normal docs search API keeps its own provider. true uses mcp.route (default
/api/docs/mcp) from the MCP server the docs site already exposes. If a project sets
mcp: { route: "/custom/docs/mcp" }, useMcp: true follows that route automatically. Pass
{ endpoint: "https://docs.example.com/mcp", headers: { Authorization: "Bearer ..." } } only for a
hosted or external MCP endpoint. MCP handles retrieval only; model, apiKey, baseUrl, or
providers still control the LLM generation request. Custom MCP endpoints must support Streamable
HTTP MCP, return an mcp-session-id on initialize, and expose a search tool (default
search_docs; override with toolName if needed). If MCP is disabled or search_docs is turned
off, Ask AI falls back to the normal top-level search config.
aiLabel
Label for the AI button (e.g. "DocsBot", "Ask AI").
packageName
Optional package-name override for unusual docs where install/import examples do not mention the main package clearly. Most projects should leave this unset because Ask AI infers package names and exact imports from retrieved docs context.
ai: {
enabled: true,
packageName: "@farming-labs/docs",
}
Framework-specific: API key
- Next.js: Set
OPENAI_API_KEYin.env; read viaprocess.env.OPENAI_API_KEY. - TanStack Start: Set in
.env; pass it throughcreateDocsServerinsrc/lib/docs.server.ts:ai: { apiKey: process.env.OPENAI_API_KEY, ...docsConfig.ai }. - SvelteKit: For OpenAI-compatible providers, set in
.envand pass intocreateDocsServerinsrc/lib/docs.server.ts:ai: { apiKey: env.OPENAI_API_KEY, ...config.ai }(use$env/dynamic/private). Forai.provider: "docs-cloud",createDocsServer()handles the local Docs Cloud proxy automatically; usePUBLIC_DOCS_CLOUD_PROJECT_IDfor public project identity orDOCS_CLOUD_PROJECT_IDfor server-only proxy mode. - Astro: Set in
.env; pass in docs server:ai: { apiKey: import.meta.env.OPENAI_API_KEY, ...config.ai }. - Nuxt: Set in
.env; Nitro/runtime config exposes it;defineDocsHandlerreadsprocess.env.OPENAI_API_KEYon the server.
Edge cases
- Static export — If
staticExport: true, AI chat is hidden; no API route is deployed. - Multiple models — Always specify
providerfor each model when using multiple providers so the correctbaseUrlandapiKeyare used. - CORS / custom baseUrl — When using a proxy or custom endpoint, set
baseUrl(or per-providerbaseUrl) accordingly.
Resources
- Full Ask AI docs: docs.farming-labs.dev/docs/customization/ai-chat
- Configuration: use the
configurationskill forstaticExportand top-level config.