Fumadocs Integration
Add AI search and chat to your Fumadocs documentation. Integrate Ask0 with Fumadocs using React components or script tags.
Add Ask0 AI assistant to your Fumadocs documentation site to help users find information instantly.
Quick Setup
Get Your Project ID
Sign in to Ask0 and copy your project ID from the dashboard.
Add Script to Root Layout
In your Fumadocs project, add the Ask0 script to your root layout:
import Script from 'next/script';
export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html>
<body>
{children}
<Script
id="ask0-widget"
src="https://assets.ask0.ai/scripts/ask.js"
strategy="afterInteractive"
data-project-id="YOUR_PROJECT_ID"
/>
</body>
</html>
);
}Configure Widget (Optional)
Add configuration options:
<Script
id="ask0-widget"
src="https://assets.ask0.ai/scripts/ask.js"
strategy="afterInteractive"
data-project-id="YOUR_PROJECT_ID"
data-position="bottom-right"
data-theme="auto"
data-primary-color="#6366f1"
data-greeting="Need help finding something in the docs?"
/>Advanced Integration
Custom Component
Create a custom Ask0 component for more control:
'use client';
import { useEffect } from 'react';
import { useTheme } from 'next-themes';
export function Ask0Widget() {
const { theme } = useTheme();
useEffect(() => {
// Load Ask0 script
const script = document.createElement('script');
script.src = 'https://assets.ask0.ai/scripts/ask.js';
script.async = true;
script.dataset.projectId = process.env.NEXT_PUBLIC_ASK0_PROJECT_ID!;
script.dataset.theme = theme === 'dark' ? 'dark' : 'light';
script.dataset.position = 'bottom-right';
document.body.appendChild(script);
return () => {
// Cleanup
document.body.removeChild(script);
if (window.ask0) {
window.ask0.destroy();
}
};
}, [theme]);
return null;
}Use in your layout:
import { Ask0Widget } from '@/components/ask0-widget';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Ask0Widget />
</body>
</html>
);
}Theme Synchronization
Sync Ask0 with Fumadocs theme:
'use client';
import { useEffect } from 'react';
import { useTheme } from 'fumadocs-ui/provider';
export function Ask0ThemeSync() {
const { theme } = useTheme();
useEffect(() => {
if (window.ask0) {
// Sync theme
window.ask0.setTheme(theme);
// Sync colors from Fumadocs
const styles = getComputedStyle(document.documentElement);
const primaryColor = styles.getPropertyValue('--primary');
window.ask0.setColors({
primary: `hsl(${primaryColor})`,
});
}
}, [theme]);
return null;
}Configuration Options
Widget Positioning
Position the widget to avoid conflicts with Fumadocs UI:
// Avoid collision with Fumadocs sidebar
window.ask0.config = {
position: 'bottom-right',
offset: {
bottom: '20px',
right: '20px', // Ensure it doesn't overlap TOC
}
};Search Integration
Replace or complement Fumadocs search:
// Option 1: Replace default search
export function SearchToggle() {
return (
<button
onClick={() => window.ask0.open()}
className="flex items-center gap-2"
>
<Search className="w-4 h-4" />
<span>Search</span>
<kbd className="text-xs">⌘K</kbd>
</button>
);
}
// Option 2: Add as additional option
export function DocsSearch() {
return (
<div className="flex gap-2">
<FumadocsSearch />
<button
onClick={() => window.ask0.open()}
className="px-3 py-1 rounded-md bg-primary/10"
>
Ask AI
</button>
</div>
);
}Custom Trigger
Add a custom trigger button:
export function AskAIButton() {
return (
<button
onClick={() => window.ask0.toggle()}
className="fixed bottom-20 right-6 z-50 flex items-center gap-2
px-4 py-2 bg-primary text-primary-foreground
rounded-full shadow-lg hover:shadow-xl transition-shadow"
>
<Sparkles className="w-4 h-4" />
Ask AI
</button>
);
}Content Indexing
Configure Ask0 Sources
-
Add Documentation URL
- In Ask0 dashboard, add your docs URL
- Example:
https://docs.yoursite.com
-
Set Crawl Patterns
Include: - https://docs.yoursite.com/** Exclude: - **/api/raw/** - **/changelog/** -
Optimize for Fumadocs Structure
- Ask0 automatically detects Fumadocs structure
- Indexes page hierarchy and navigation
Best Practices
Fumadocs Integration Tips:
- Place widget to avoid UI conflicts
- Sync theme with Fumadocs theme system
- Consider replacing or augmenting search
- Index all documentation pages
- Test on mobile layouts
- Use environment variables for project ID
Performance
Optimize loading:
// Lazy load Ask0 on user interaction
export function LazyAsk0() {
const [loaded, setLoaded] = useState(false);
const loadWidget = () => {
if (!loaded) {
const script = document.createElement('script');
script.src = 'https://assets.ask0.ai/scripts/ask.js';
script.dataset.projectId = 'YOUR_PROJECT_ID';
document.body.appendChild(script);
setLoaded(true);
}
};
return (
<button onClick={loadWidget}>
Need help? Ask AI
</button>
);
}Styling
Match Fumadocs design:
/* Custom styles for Ask0 in Fumadocs */
.ask0-widget {
--ask0-font-sans: var(--font-sans);
--ask0-radius: var(--radius);
}
/* Match Fumadocs colors */
[data-theme="light"] .ask0-widget {
--ask0-primary: hsl(var(--primary));
--ask0-background: hsl(var(--background));
--ask0-foreground: hsl(var(--foreground));
}
[data-theme="dark"] .ask0-widget {
--ask0-primary: hsl(var(--primary));
--ask0-background: hsl(var(--background));
--ask0-foreground: hsl(var(--foreground));
}TypeScript Support
Add type definitions:
interface Ask0Widget {
open: () => void;
close: () => void;
toggle: () => void;
setTheme: (theme: 'light' | 'dark' | 'auto') => void;
setLanguage: (lang: string) => void;
identify: (user: {
id: string;
email?: string;
name?: string;
}) => void;
on: (event: string, callback: Function) => void;
}
declare global {
interface Window {
ask0: Ask0Widget;
}
}Environment Variables
Configure in .env.local:
NEXT_PUBLIC_ASK0_PROJECT_ID=your_project_id
NEXT_PUBLIC_ASK0_POSITION=bottom-right
NEXT_PUBLIC_ASK0_THEME=autoUse in your code:
<Script
src="https://assets.ask0.ai/scripts/ask.js"
data-project-id={process.env.NEXT_PUBLIC_ASK0_PROJECT_ID}
data-position={process.env.NEXT_PUBLIC_ASK0_POSITION}
data-theme={process.env.NEXT_PUBLIC_ASK0_THEME}
/>Troubleshooting
Common Issues:
Widget not appearing
- Check if project ID is correct
- Verify script is loading (check Network tab)
- Ensure no Content Security Policy blocks
Theme not syncing
- Make sure to call
ask0.setTheme()after widget loads - Listen for theme changes in Fumadocs
Position conflicts
- Adjust offset values
- Consider mobile responsiveness
- Check z-index values
Example Implementation
Complete example for Fumadocs:
import './global.css';
import { RootProvider } from 'fumadocs-ui/provider';
import { Inter } from 'next/font/google';
import type { ReactNode } from 'react';
import Script from 'next/script';
const inter = Inter({
subsets: ['latin'],
});
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={inter.className} suppressHydrationWarning>
<body>
<RootProvider>
{children}
</RootProvider>
{/* Ask0 Widget */}
<Script
id="ask0-widget"
src="https://assets.ask0.ai/scripts/ask.js"
strategy="afterInteractive"
data-project-id={process.env.NEXT_PUBLIC_ASK0_PROJECT_ID}
data-position="bottom-right"
data-theme="auto"
data-greeting="👋 Need help navigating the docs?"
data-placeholder="Ask me anything about our documentation..."
/>
</body>
</html>
);
}