export interface DocEntry {
title: string;
path: string;
description: string;
section: string;
keywords: string[];
}
export const SECTIONS = {
cli: "CLI",
headless: "Headless/Core",
framework: "Framework",
mdx: "MDX",
ui: "UI",
} as const;
export type SectionId = keyof typeof SECTIONS;
export const FRAMEWORK_PATHS: Record<string, string> = {
next: "/docs/manual-installation/next",
"react-router": "/docs/manual-installation/react-router",
"tanstack-start": "/docs/manual-installation/tanstack-start",
waku: "/docs/manual-installation/waku",
};
export const COMPONENT_PATHS: Record<string, string> = {
accordion: "/docs/ui/components/accordion",
"auto-type-table": "/docs/ui/components/auto-type-table",
banner: "/docs/ui/components/banner",
codeblock: "/docs/ui/components/codeblock",
"code-block": "/docs/ui/components/codeblock",
"dynamic-codeblock": "/docs/ui/components/dynamic-codeblock",
files: "/docs/ui/components/files",
"github-info": "/docs/ui/components/github-info",
"graph-view": "/docs/ui/components/graph-view",
"image-zoom": "/docs/ui/components/image-zoom",
"inline-toc": "/docs/ui/components/inline-toc",
steps: "/docs/ui/components/steps",
tabs: "/docs/ui/components/tabs",
"type-table": "/docs/ui/components/type-table",
};
// Static index for fast local searching
// This is parsed from the llms.txt format
export const DOCS_INDEX: DocEntry[] = [
// CLI section
{
title: "create-fumadocs-app",
path: "/docs/cli/create-fumadocs-app",
description: "The CLI to create new Fumadocs apps",
section: "cli",
keywords: ["create", "app", "cli", "new", "project", "init", "scaffold"],
},
{
title: "CLI User Guide",
path: "/docs/cli",
description: "The CLI tool that automates setups and installs components",
section: "cli",
keywords: ["cli", "automation", "setup", "install", "components"],
},
// Headless/Core section
{
title: "Introduction",
path: "/docs/headless",
description: "Getting started with core library",
section: "headless",
keywords: ["introduction", "getting started", "core", "headless"],
},
{
title: "Internationalization",
path: "/docs/headless/internationalization",
description: "Support multiple languages in your documentation",
section: "headless",
keywords: ["i18n", "internationalization", "languages", "localization", "translation"],
},
{
title: "Page Conventions",
path: "/docs/headless/page-conventions",
description: "Customise generated page slugs and page tree",
section: "headless",
keywords: ["page", "slugs", "conventions", "tree", "structure"],
},
{
title: "Page Tree",
path: "/docs/headless/page-tree",
description: "The structure of page tree",
section: "headless",
keywords: ["page", "tree", "structure", "navigation"],
},
{
title: "Breadcrumb",
path: "/docs/headless/components/breadcrumb",
description: "The navigation component at the top of the screen",
section: "headless",
keywords: ["breadcrumb", "navigation", "component"],
},
{
title: "Components",
path: "/docs/headless/components",
description: "Blocks for your docs",
section: "headless",
keywords: ["components", "blocks", "ui"],
},
{
title: "Link",
path: "/docs/headless/components/link",
description: "A Link component that handles external links",
section: "headless",
keywords: ["link", "external", "component", "navigation"],
},
{
title: "TOC",
path: "/docs/headless/components/toc",
description: "Table of Contents",
section: "headless",
keywords: ["toc", "table of contents", "navigation"],
},
{
title: "Content Collections",
path: "/docs/headless/content-collections",
description: "Use Content Collections for Fumadocs",
section: "headless",
keywords: ["content", "collections", "astro"],
},
{
title: "Headings",
path: "/docs/headless/mdx/headings",
description: "Process headings from your document",
section: "headless",
keywords: ["headings", "mdx", "process"],
},
{
title: "MDX Plugins",
path: "/docs/headless/mdx",
description: "Useful remark & rehype plugins for your docs",
section: "headless",
keywords: ["mdx", "plugins", "remark", "rehype"],
},
{
title: "Rehype Code",
path: "/docs/headless/mdx/rehype-code",
description: "Code syntax highlighter",
section: "headless",
keywords: ["rehype", "code", "syntax", "highlighter", "shiki"],
},
{
title: "Search",
path: "/docs/headless/search",
description: "Configure Search in Fumadocs",
section: "headless",
keywords: ["search", "configure"],
},
{
title: "Orama Search",
path: "/docs/headless/search/orama",
description: "Built-in document search of Fumadocs",
section: "headless",
keywords: ["search", "orama", "built-in"],
},
{
title: "Algolia Search",
path: "/docs/headless/search/algolia",
description: "Integrate Algolia Search with Fumadocs",
section: "headless",
keywords: ["search", "algolia", "integration"],
},
{
title: "Loader API",
path: "/docs/headless/source-api",
description: "Turn content sources into a unified interface",
section: "headless",
keywords: ["loader", "api", "source", "content"],
},
// Framework section
{
title: "Quick Start",
path: "/docs",
description: "Getting Started with Fumadocs",
section: "framework",
keywords: ["getting started", "quick start", "introduction", "setup"],
},
{
title: "What is Fumadocs",
path: "/docs/what-is-fumadocs",
description: "Introducing Fumadocs, a docs framework that you can break",
section: "framework",
keywords: ["introduction", "what is", "overview"],
},
{
title: "Comparisons",
path: "/docs/comparisons",
description: "How is Fumadocs different from other existing frameworks?",
section: "framework",
keywords: ["comparison", "alternatives", "docusaurus", "nextra"],
},
{
title: "Manual Installation",
path: "/docs/manual-installation",
description: "Add Fumadocs to existing projects",
section: "framework",
keywords: ["manual", "installation", "existing", "project", "setup"],
},
{
title: "Manual Installation - Next.js",
path: "/docs/manual-installation/next",
description: "Setup Fumadocs on Next.js",
section: "framework",
keywords: ["manual", "installation", "nextjs", "next", "setup", "existing"],
},
{
title: "Manual Installation - React Router",
path: "/docs/manual-installation/react-router",
description: "Setup Fumadocs on React Router",
section: "framework",
keywords: ["manual", "installation", "react-router", "setup", "existing"],
},
{
title: "Manual Installation - Tanstack Start",
path: "/docs/manual-installation/tanstack-start",
description: "Setup Fumadocs on Tanstack Start",
section: "framework",
keywords: ["manual", "installation", "tanstack", "start", "setup", "existing"],
},
{
title: "Manual Installation - Waku",
path: "/docs/manual-installation/waku",
description: "Setup Fumadocs on Waku",
section: "framework",
keywords: ["manual", "installation", "waku", "setup", "existing"],
},
{
title: "Navigation",
path: "/docs/navigation",
description: "Configure navigation in your Fumadocs app",
section: "framework",
keywords: ["navigation", "sidebar", "menu", "configure"],
},
{
title: "Markdown",
path: "/docs/markdown",
description: "How to write documents",
section: "framework",
keywords: ["markdown", "mdx", "writing", "documents"],
},
{
title: "Search",
path: "/docs/search",
description: "Implement document search in your docs",
section: "framework",
keywords: ["search", "implement"],
},
{
title: "Deploying",
path: "/docs/deploying",
description: "Deploy your Fumadocs app",
section: "framework",
keywords: ["deploy", "deployment", "hosting", "vercel"],
},
{
title: "Internationalization",
path: "/docs/internationalization",
description: "Support multiple languages in your documentation",
section: "framework",
keywords: ["i18n", "internationalization", "languages", "localization"],
},
{
title: "Versioning",
path: "/docs/versioning",
description: "Implementing multi-version in your docs",
section: "framework",
keywords: ["versioning", "versions", "multi-version"],
},
// MDX section
{
title: "Getting Started",
path: "/docs/mdx",
description: "Introducing Fumadocs MDX, the official content source of Fumadocs",
section: "mdx",
keywords: ["mdx", "getting started", "content source"],
},
{
title: "Collections",
path: "/docs/mdx/collections",
description: "Collection of content data for your app",
section: "mdx",
keywords: ["collections", "content", "data"],
},
{
title: "Global Options",
path: "/docs/mdx/global",
description: "Customise Fumadocs MDX",
section: "mdx",
keywords: ["global", "options", "configure", "customize"],
},
{
title: "Next.js",
path: "/docs/mdx/next",
description: "Use Fumadocs MDX with Next.js",
section: "mdx",
keywords: ["nextjs", "next", "integration"],
},
{
title: "Vite",
path: "/docs/mdx/vite",
description: "Use Fumadocs MDX with Vite",
section: "mdx",
keywords: ["vite", "integration"],
},
{
title: "Accessing Collections",
path: "/docs/mdx/entry",
description: "Access collection outputs from entry files",
section: "mdx",
keywords: ["collections", "entry", "access"],
},
// UI section
{
title: "Overview",
path: "/docs/ui",
description: "The default theme of Fumadocs",
section: "ui",
keywords: ["ui", "theme", "overview", "default"],
},
{
title: "Themes",
path: "/docs/ui/theme",
description: "Add Theme to Fumadocs UI",
section: "ui",
keywords: ["theme", "dark", "light", "customize"],
},
{
title: "Search UI",
path: "/docs/ui/search",
description: "The UI for document search",
section: "ui",
keywords: ["search", "ui", "dialog"],
},
{
title: "Components",
path: "/docs/ui/components",
description: "Additional components to improve your docs",
section: "ui",
keywords: ["components", "ui"],
},
{
title: "Accordion",
path: "/docs/ui/components/accordion",
description: "Add Accordions to your documentation",
section: "ui",
keywords: ["accordion", "component", "collapse", "expand"],
},
{
title: "Auto Type Table",
path: "/docs/ui/components/auto-type-table",
description: "Auto-generated type table",
section: "ui",
keywords: ["type", "table", "auto", "typescript"],
},
{
title: "Banner",
path: "/docs/ui/components/banner",
description: "Add a banner to your site",
section: "ui",
keywords: ["banner", "announcement", "header"],
},
{
title: "Code Block",
path: "/docs/ui/components/codeblock",
description: "Displaying Shiki highlighted code blocks",
section: "ui",
keywords: ["code", "codeblock", "syntax", "highlight", "shiki"],
},
{
title: "Code Block (Dynamic)",
path: "/docs/ui/components/dynamic-codeblock",
description: "A codeblock that also highlights code",
section: "ui",
keywords: ["code", "codeblock", "dynamic", "highlight"],
},
{
title: "Files",
path: "/docs/ui/components/files",
description: "Display file structure in your documentation",
section: "ui",
keywords: ["files", "file tree", "structure", "directory"],
},
{
title: "GitHub Info",
path: "/docs/ui/components/github-info",
description: "Display your GitHub repository information",
section: "ui",
keywords: ["github", "repository", "info", "stars"],
},
{
title: "Graph View",
path: "/docs/ui/components/graph-view",
description: "A graph of all pages",
section: "ui",
keywords: ["graph", "view", "pages", "visualization"],
},
{
title: "Zoomable Image",
path: "/docs/ui/components/image-zoom",
description: "Allow zoom-in images in your documentation",
section: "ui",
keywords: ["image", "zoom", "lightbox"],
},
{
title: "Inline TOC",
path: "/docs/ui/components/inline-toc",
description: "Add Inline TOC into your documentation",
section: "ui",
keywords: ["toc", "table of contents", "inline"],
},
{
title: "Steps",
path: "/docs/ui/components/steps",
description: "Adding steps to your docs",
section: "ui",
keywords: ["steps", "stepper", "guide", "tutorial"],
},
{
title: "Tabs",
path: "/docs/ui/components/tabs",
description: "A Tabs component built with Radix UI, with additional features such as persistent and shared value",
section: "ui",
keywords: ["tabs", "tabbed", "radix", "persistent"],
},
{
title: "Type Table",
path: "/docs/ui/components/type-table",
description: "A table for documenting types",
section: "ui",
keywords: ["type", "table", "props", "api"],
},
{
title: "Layouts",
path: "/docs/ui/layouts",
description: "A list of layout components",
section: "ui",
keywords: ["layouts", "page", "structure"],
},
{
title: "Docs Layout",
path: "/docs/ui/layouts/docs",
description: "The layout of documentation",
section: "ui",
keywords: ["layout", "docs", "sidebar"],
},
{
title: "Home Layout",
path: "/docs/ui/layouts/home-layout",
description: "Shared layout for other pages",
section: "ui",
keywords: ["layout", "home", "landing"],
},
{
title: "Docs Page",
path: "/docs/ui/layouts/page",
description: "A page in your documentation",
section: "ui",
keywords: ["page", "docs", "layout"],
},
{
title: "Root Provider",
path: "/docs/ui/layouts/root-provider",
description: "The context provider of Fumadocs UI",
section: "ui",
keywords: ["provider", "context", "root"],
},
];
// Helper function to search the index
export function searchDocsIndex(
query: string,
section?: SectionId
): DocEntry[] {
const normalizedQuery = query.toLowerCase();
const queryWords = normalizedQuery.split(/\s+/);
let results = DOCS_INDEX;
// Filter by section if specified
if (section) {
results = results.filter((entry) => entry.section === section);
}
// Score and filter results
const scored = results
.map((entry) => {
let score = 0;
const titleLower = entry.title.toLowerCase();
const descLower = entry.description.toLowerCase();
for (const word of queryWords) {
// Title matches (highest weight)
if (titleLower.includes(word)) {
score += 10;
if (titleLower === word || titleLower.startsWith(word)) {
score += 5;
}
}
// Description matches
if (descLower.includes(word)) {
score += 5;
}
// Keyword matches
for (const keyword of entry.keywords) {
if (keyword.includes(word)) {
score += 3;
if (keyword === word) {
score += 2;
}
}
}
// Path matches
if (entry.path.toLowerCase().includes(word)) {
score += 2;
}
}
return { entry, score };
})
.filter((item) => item.score > 0)
.sort((a, b) => b.score - a.score);
return scored.map((item) => item.entry);
}
// Get entries by section
export function getEntriesBySection(section: SectionId): DocEntry[] {
return DOCS_INDEX.filter((entry) => entry.section === section);
}
// Get all sections with their entries
export function getAllSections(): { id: SectionId; name: string; entries: DocEntry[] }[] {
return (Object.keys(SECTIONS) as SectionId[]).map((id) => ({
id,
name: SECTIONS[id],
entries: getEntriesBySection(id),
}));
}