원클릭으로
fumadocs-ui
// Customize documentation appearance and layouts using Fumadocs UI theme and component library
// Customize documentation appearance and layouts using Fumadocs UI theme and component library
Create and configure Fumadocs projects using CLI, selecting frameworks, content sources, and UI components
Build and deploy Fumadocs documentation sites, supporting static export, PDF, RSS, and more
Build documentation sites using Headless components library, including navigation, TOC, search API, and content collections
Configure internationalization support for Fumadocs, including multi-language routing and content organization
Configure and manage Fumadocs MDX content collections, including schema definition, type generation, and file imports
Configure and integrate document search engines for Fumadocs, supporting Orama, Algolia, Mixedbread, and other solutions
| name | Fumadocs UI |
| description | Customize documentation appearance and layouts using Fumadocs UI theme and component library |
Fumadocs UI provides beautiful documentation themes and interactive components.
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
<Accordions type="single">
<Accordion title="What is Fumadocs?">
Fumadocs is a documentation framework...
</Accordion>
<Accordion title="How to use?">
You can use it with Next.js, React Router, etc.
</Accordion>
</Accordions>
Props:
type: 'single' | 'multiple'disabled: booleanorientation: 'vertical' | 'horizontal'<Accordions>
<Accordion title="My Title" id="my-title">
Content
</Accordion>
</Accordions>
Automatically opens when navigating to the page with the specified id:
<Link href="/docs?#my-title">Jump to my title</Link>
import { Tabs, TabsContent, TabsList, TabsTrigger } from 'fumadocs-ui/components/tabs';
<Tabs defaultValue="docs">
<TabsList>
<TabsTrigger value="docs">Documentation</TabsTrigger>
<TabsTrigger value="api">API Reference</TabsTrigger>
<TabsTrigger value="examples">Examples</TabsTrigger>
</TabsList>
<TabsContent value="docs">
Documentation content...
</TabsContent>
<TabsContent value="api">
API documentation...
</TabsContent>
</Tabs>
Props:
value: Currently selected valuedefaultValue: Default valueimport { Steps, Step, StepList } from 'fumadocs-ui/components/steps';
<Steps>
<StepList>
<Step title="Install">npm install fumadocs</Step>
<Step title="Configure">Update config files</Step>
<Step title="Run">npm run dev</Step>
</StepList>
</Steps>
import { CodeBlock, DynamicCodeBlock } from 'fumadocs-ui/components/codeblock';
<CodeBlock filename="example.ts">
console.log('Hello, Fumadocs!');
</CodeBlock>
<CodeBlock
filename="index.tsx"
language="typescript"
showLineNumbers
>
export default function App() {
return <div>Hello World</div>;
}
</CodeBlock>
// Dynamic code block
<DynamicCodeBlock code={codeString} language="typescript" />
Props:
filename: File namelanguage: Language typeshowLineNumbers: Show line numberscopyButton: Show copy buttonimport { Banner } from 'fumadocs-ui/components/banner';
<Banner>
⚠️ New feature coming soon! Check out the beta version.
</Banner>
<Banner variant="info">
ℹ️ Documentation is being updated.
</Banner>
Props:
variant: 'default' | 'info' | 'warning' | 'success'import { Files } from 'fumadocs-ui/components/files';
<Files>
<Files.Item name="src" type="folder">
<Files.Item name="components" type="folder">
<Files.Item name="Button.tsx" type="file" />
<Files.Item name="Input.tsx" type="file" />
</Files.Item>
<Files.Item name="App.tsx" type="file" />
</Files.Item>
</Files>
import { GitHubInfo } from 'fumadocs-ui/components/github-info';
<GitHubInfo
repository="fuma-nama/fumadocs"
branch="main"
/>
import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
<InlineTOC />
Standard documentation layout (sidebar + header + TOC):
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { source } from '@/lib/source';
export default function DocsLayout({ children }: { children: React.ReactNode }) {
return (
<DocsLayout
tree={source.getPageTree()}
sidebar={{ enabled: true }}
header={{ title: 'My Documentation' }}
>
{children}
</DocsLayout>
);
}
<DocsLayout
tree={source.getPageTree()}
sidebar={{
enabled: true,
tabs: true, // Enable tabs
collapsible: true, // Collapsible
defaultOpenLevel: 2, // Default open level
prefetch: true, // Prefetch
}}
>
{children}
</DocsLayout>
<DocsLayout
tree={source.getPageTree()}
sidebar={{
enabled: true,
banner: <div>Welcome to our docs!</div>,
}}
>
{children}
</DocsLayout>
Minimalist layout, suitable for technical blogs:
import { FluxLayout } from 'fumadocs-ui/layouts/flux';
import { source } from '@/lib/source';
export default function FluxLayout({ children }: { children: React.ReactNode }) {
return (
<FluxLayout tree={source.getPageTree()}>
{children}
</FluxLayout>
);
}
Homepage layout, ideal as a website entry point:
import { HomeLayout } from 'fumadocs-ui/layouts/home-layout';
export default function HomeLayout({ children }: { children: React.ReactNode }) {
return (
<HomeLayout>
{children}
</HomeLayout>
);
}
Notebook-style layout, compact for technical documentation:
import { NotebookLayout } from 'fumadocs-ui/layouts/notebook';
import { source } from '@/lib/source';
export default function NotebookLayout({ children }: { children: React.ReactNode }) {
return (
<NotebookLayout tree={source.getPageTree()}>
{children}
</NotebookLayout>
);
}
'use client';
import { SearchDialog, SearchDialogList } from 'fumadocs-ui/components/dialog/search';
export default function SearchDialog() {
const { search, setSearch, query } = useDocsSearch();
return (
<SearchDialog search={search} onSearchChange={setSearch}>
<SearchDialogList items={query.data} />
</SearchDialog>
);
}
'use client';
import {
SearchDialog,
SearchDialogClose,
SearchDialogContent,
SearchDialogHeader,
SearchDialogList,
SearchDialogOverlay,
} from 'fumadocs-ui/components/dialog/search';
export default function CustomSearchDialog() {
const { search, setSearch, query } = useDocsSearch();
const [isFocused, setIsFocused] = useState(false);
return (
<SearchDialog search={search} onSearchChange={setSearch}>
<SearchDialogOverlay className={isFocused ? 'opacity-100' : 'opacity-0'} />
<SearchDialogContent className={isFocused ? 'scale-100' : 'scale-95'}>
<SearchDialogHeader>
<SearchDialogIcon />
<SearchDialogInput />
<SearchDialogClose />
</SearchDialogHeader>
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
</SearchDialogContent>
</SearchDialog>
);
}
'use client';
import {
SearchDialog,
SearchDialogContent,
SearchDialogFooter,
SearchDialogOverlay,
TagsList,
TagsListItem,
} from 'fumadocs-ui/components/dialog/search';
import { useState } from 'react';
export default function TagFilterSearchDialog() {
const [tag, setTag] = useState<string | undefined>();
const { search, setSearch, query } = useDocsSearch({
tag,
});
return (
<SearchDialog search={search} onSearchChange={setSearch}>
<SearchDialogOverlay />
<SearchDialogContent>
<SearchDialogHeader>
<SearchDialogIcon />
<SearchDialogInput />
<SearchDialogClose />
</SearchDialogHeader>
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
<SearchDialogFooter className="flex flex-row">
<TagsList tag={tag} onTagChange={setTag}>
<TagsListItem value="getting-started">Getting Started</TagsListItem>
<TagsListItem value="api">API Reference</TagsListItem>
<TagsListItem value="guides">Guides</TagsListItem>
</TagsList>
</SearchDialogFooter>
</SearchDialogContent>
</SearchDialog>
);
}
'use client';
import {
SearchDialog,
SearchDialogContent,
SearchDialogList,
SearchDialogOverlay,
} from 'fumadocs-ui/components/dialog/search';
export default function CustomSearchDialog() {
const { search, setSearch, query } = useDocsSearch();
return (
<SearchDialog search={search} onSearchChange={setSearch}>
<SearchDialogOverlay />
<SearchDialogContent>
<SearchDialogHeader>
<SearchDialogIcon />
<SearchDialogInput />
</SearchDialogHeader>
<SearchDialogList
items={query.data !== 'empty' ? query.data : null}
renderItem={(item) => (
<div className="p-4 border-b">
<h3 className="font-semibold">{item.title}</h3>
<p className="text-sm text-muted-foreground">{item.description}</p>
<Link href={item.url} className="text-blue-500">
Read more →
</Link>
</div>
)}
/>
</SearchDialogContent>
</SearchDialog>
);
}
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
fd: {
primary: '#3b82f6',
secondary: '#64748b',
accent: '#f59e0b',
background: '#ffffff',
foreground: '#0f172a',
muted: '#f1f5f9',
'muted-foreground': '#64748b',
border: '#e2e8f0',
},
},
},
},
};
Default uses Radix UI:
import { RootProvider } from 'fumadocs-ui/provider/nextjs';
<RootProvider>
{children}
</RootProvider>
Switch to Base UI:
// cli.json
{
"uiLibrary": "base-ui"
}
Fumadocs uses CSS variables for color customization:
:root {
--fd-primary: #3b82f6;
--fd-secondary: #64748b;
--fd-accent: #f59e0b;
--fd-background: #ffffff;
--fd-foreground: #0f172a;
--fd-muted: #f1f5f9;
--fd-muted-foreground: #64748b;
--fd-border: #e2e8f0;
--fd-sidebar-width: 280px;
--fd-header-height: 60px;
}
Reference Documentation: