cf: test remove docs pages and content only

This commit is contained in:
javayhu 2025-06-09 00:05:32 +08:00
parent ec124640f1
commit 708fac652f
82 changed files with 0 additions and 6277 deletions

View File

@ -1,74 +0,0 @@
---
title: Comparisons
description: How is Fumadocs different from other existing frameworks?
icon: GitCompareArrows
---
## Nextra
Fumadocs is highly inspired by Nextra. For example, the Routing Conventions. That is why
`meta.json` also exists in Fumadocs.
Nextra is more opinionated than Fumadocs. Fumadocs is accelerated by App Router. As a result, It provides many server-side functions, and you have to
configure things manually compared to simply editing a configuration file.
Fumadocs works great if you want more control over everything, such as
adding it to an existing codebase or implementing advanced routing.
### Feature Table
| Feature | Fumadocs | Nextra |
| ------------------- | ------------ | ------------------------- |
| Static Generation | Yes | Yes |
| Cached | Yes | Yes |
| Light/Dark Mode | Yes | Yes |
| Syntax Highlighting | Yes | Yes |
| Table of Contents | Yes | Yes |
| Full-text Search | Yes | Yes |
| i18n | Yes | Yes |
| Last Git Edit Time | Yes | Yes |
| Page Icons | Yes | Yes, via `_meta.js` files |
| RSC | Yes | Yes |
| Remote Source | Yes | Yes |
| SEO | Via Metadata | Yes |
| Built-in Components | Yes | Yes |
| RTL Layout | Yes | Yes |
### Additional Features
Features supported via 3rd party libraries like [TypeDoc](https://typedoc.org) will not be listed here.
| Feature | Fumadocs | Nextra |
| -------------------------- | -------- | ------ |
| OpenAPI Integration | Yes | No |
| TypeScript Docs Generation | Yes | No |
| TypeScript Twoslash | Yes | Yes |
## Mintlify
Mintlify is a documentation service, as compared to Fumadocs, it offers a free tier but isn't completely free and open source.
Fumadocs is not as powerful as Mintlify, for example, the OpenAPI integration of Mintlify.
As the creator of Fumadocs, I wouldn't recommend switching to Fumadocs from Mintlify if you're satisfied with the current way you build docs.
However, I believe Fumadocs is a suitable tool for all Next.js developers who want to have elegant docs.
## Docusaurus
Docusaurus is a powerful framework based on React.js. It offers many cool
features with plugins and custom themes.
### Better DX
Since Fumadocs is built on the top of Next.js, you'll have to start the Next.js dev
server every time to review changes, and initial boilerplate code is relatively more
compared to Docusaurus.
For a simple docs, Docusaurus might be a better choice if you don't need any Next.js specific functionality.
However, when you want to use Next.js, or seek extra customizability like tuning default UI components, Fumadocs could be a better choice.
### Plugins
You can easily achieve many things with plugins, their ecosystem is indeed larger and maintained by many contributors.
In comparison, the flexibility of Fumadocs allows you to implement them on your own, it may take longer to tune it to your satisfaction.

View File

@ -1,68 +0,0 @@
---
title: 对比
description: Fumadocs 与其他现有框架有何不同?
icon: GitCompareArrows
---
## Nextra
Fumadocs 深受 Nextra 启发。例如,路由约定。这就是为什么 Fumadocs 中也存在 `meta.json`。
Nextra 比 Fumadocs 更加固执己见。Fumadocs 由 App Router 加速。因此,它提供了许多服务器端功能,与简单编辑配置文件相比,您必须手动配置一些内容。
如果您想要对一切都有更多的控制比如将其添加到现有代码库或实现高级路由Fumadocs 会表现得很出色。
### 功能表
| 功能 | Fumadocs | Nextra |
| ------------------- | ------------ | ------------------------- |
| 静态生成 | 是 | 是 |
| 缓存 | 是 | 是 |
| 明/暗模式 | 是 | 是 |
| 语法高亮 | 是 | 是 |
| 目录 | 是 | 是 |
| 全文搜索 | 是 | 是 |
| 国际化 | 是 | 是 |
| 最后 Git 编辑时间 | 是 | 是 |
| 页面图标 | 是 | 是,通过 `_meta.js` 文件 |
| RSC | 是 | 是 |
| 远程源 | 是 | 是 |
| SEO | 通过元数据 | 是 |
| 内置组件 | 是 | 是 |
| RTL 布局 | 是 | 是 |
### 附加功能
通过第三方库支持的功能(如 [TypeDoc](https://typedoc.org))不会在此列出。
| 功能 | Fumadocs | Nextra |
| -------------------------- | -------- | ------ |
| OpenAPI 集成 | 是 | 否 |
| TypeScript 文档生成 | 是 | 否 |
| TypeScript Twoslash | 是 | 是 |
## Mintlify
Mintlify 是一项文档服务,与 Fumadocs 相比,它提供免费套餐,但并非完全免费和开源。
Fumadocs 不如 Mintlify 强大,例如 Mintlify 的 OpenAPI 集成。
作为 Fumadocs 的创建者,如果您对当前构建文档的方式感到满意,我不建议从 Mintlify 切换到 Fumadocs。
然而,我相信 Fumadocs 是所有想要拥有优雅文档的 Next.js 开发者的合适工具。
## Docusaurus
Docusaurus 是一个基于 React.js 的强大框架。它通过插件和自定义主题提供了许多酷炫的功能。
### 更好的开发者体验
由于 Fumadocs 构建在 Next.js 之上,您每次都必须启动 Next.js 开发服务器来查看更改,并且相对于 Docusaurus初始样板代码较多。
对于简单的文档,如果您不需要任何特定于 Next.js 的功能Docusaurus 可能是更好的选择。
然而,当您想要使用 Next.js或寻求更多的可定制性如调整默认 UI 组件时Fumadocs 可能是更好的选择。
### 插件
您可以通过插件轻松实现许多功能,他们的生态系统确实更大,并由许多贡献者维护。
相比之下Fumadocs 的灵活性允许您自己实现它们,可能需要更长的时间来调整它以达到您的满意度。

View File

@ -1,43 +0,0 @@
---
title: Accordion
description: Add Accordions to your documentation
preview: accordion
---
## Usage
Based on
[Radix UI Accordion](https://www.radix-ui.com/primitives/docs/components/accordion), useful for FAQ sections.
```tsx
import React from 'react';
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
<Accordions type="single">
<Accordion title="My Title">My Content</Accordion>
</Accordions>;
```
### Accordions
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionsProps" /> */}
### Accordion
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionProps" /> */}
### Linking to Accordion
You can specify an `id` for accordion. The accordion will automatically open when the user is navigating to the page with the specified `id` in hash parameter.
```mdx
<Accordions>
<Accordion title="My Title" id="my-title">
My Content
</Accordion>
</Accordions>
```
> The value of accordion is same as title by default. When an id presents, it will be used as the value instead.

View File

@ -1,42 +0,0 @@
---
title: 手风琴
description: 在文档中添加手风琴组件
preview: accordion
---
## 使用方法
基于 [Radix UI Accordion](https://www.radix-ui.com/primitives/docs/components/accordion),对 FAQ 部分特别有用。
```tsx
import React from 'react';
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
<Accordions type="single">
<Accordion title="我的标题">我的内容</Accordion>
</Accordions>;
```
### Accordions
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionsProps" /> */}
### Accordion
{/* <AutoTypeTable path="./content/docs/props.ts" name="AccordionProps" /> */}
### 链接到手风琴
您可以为手风琴指定一个 `id`。当用户导航到带有指定 `id` 的哈希参数的页面时,手风琴将自动打开。
```mdx
<Accordions>
<Accordion title="我的标题" id="my-title">
我的内容
</Accordion>
</Accordions>
```
> 手风琴的值默认与标题相同。当存在 id 时,它将被用作值。

View File

@ -1,61 +0,0 @@
---
title: Banner
description: Add a banner to your site
preview: banner
---
## Usage
Put the element at the top of your root layout, you can use it for displaying announcements.
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}): React.ReactElement {
return (
<html lang="en">
<body>
<Banner>Hello World</Banner>
{children}
</body>
</html>
);
}
```
### Variant
Change the default variant.
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
<Banner variant="rainbow">Hello World</Banner>;
```
### Change Layout
By default, the banner uses a `style` tag to modify Fumadocs layouts (e.g. reduce the sidebar height).
You can disable it with:
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
<Banner changeLayout={false}>Hello World</Banner>;
```
### Close
To allow users to close the banner, give the banner an ID.
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
<Banner id="hello-world">Hello World</Banner>;
```
The state will be automatically persisted.

View File

@ -1,61 +0,0 @@
---
title: 横幅
description: 在您的网站添加横幅
preview: banner
---
## 使用方法
将元素放在根布局的顶部,您可以用它来显示公告。
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}): React.ReactElement {
return (
<html lang="en">
<body>
<Banner>Hello World</Banner>
{children}
</body>
</html>
);
}
```
### 变体
更改默认变体。
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
<Banner variant="rainbow">Hello World</Banner>;
```
### 更改布局
默认情况下,横幅使用 `style` 标签来修改 Fumadocs 布局(例如减少侧边栏高度)。
您可以通过以下方式禁用它:
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
<Banner changeLayout={false}>Hello World</Banner>;
```
### 关闭
要允许用户关闭横幅,请给横幅一个 ID。
```tsx
import { Banner } from 'fumadocs-ui/components/banner';
<Banner id="hello-world">Hello World</Banner>;
```
状态将自动保持。

View File

@ -1,38 +0,0 @@
---
title: Code Block (Dynamic)
description: A codeblock that also highlights code
preview: dynamicCodeBlock
---
## Usage
```tsx
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
<DynamicCodeBlock lang="ts" code='console.log("Hello World")' />;
```
This component, different from the MDX [`CodeBlock`](/docs/mdx/codeblock) component, can be used without MDX.
It highlights the code with Shiki and use the default component to render it.
Features:
- Can be pre-rendered on server
- load languages and themes on browser lazily
### Options
```tsx
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
<DynamicCodeBlock
lang="ts"
code='console.log("Hello World")'
options={{
components: {
// add/override components
},
// or Shiki options
}}
/>;
```

View File

@ -1,38 +0,0 @@
---
title: 代码块(动态)
description: 也能高亮代码的代码块
preview: dynamicCodeBlock
---
## 使用方法
```tsx
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
<DynamicCodeBlock lang="ts" code='console.log("Hello World")' />;
```
这个组件与 MDX [`CodeBlock`](/docs/mdx/codeblock) 组件不同,可以在不使用 MDX 的情况下使用。
它使用 Shiki 高亮代码,并使用默认组件渲染它。
特点:
- 可以在服务器上预渲染
- 在浏览器上懒加载语言和主题
### 选项
```tsx
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
<DynamicCodeBlock
lang="ts"
code='console.log("Hello World")'
options={{
components: {
// 添加/覆盖组件
},
// 或 Shiki 选项
}}
/>;
```

View File

@ -1,35 +0,0 @@
---
title: Files
description: Display file structure in your documentation
preview: 'files'
---
## Usage
Wrap file components in `Files`.
```mdx
import { File, Folder, Files } from 'fumadocs-ui/components/files';
<Files>
<Folder name="app" defaultOpen>
<File name="layout.tsx" />
<File name="page.tsx" />
<File name="global.css" />
</Folder>
<Folder name="components">
<File name="button.tsx" />
<File name="tabs.tsx" />
<File name="dialog.tsx" />
</Folder>
<File name="package.json" />
</Files>
```
### File
{/* <AutoTypeTable path="./content/docs/props.ts" name="FileProps" /> */}
### Folder
{/* <AutoTypeTable path="./content/docs/props.ts" name="FolderProps" /> */}

View File

@ -1,35 +0,0 @@
---
title: 文件
description: 在文档中显示文件结构
preview: 'files'
---
## 使用方法
将文件组件包装在 `Files` 中。
```mdx
import { File, Folder, Files } from 'fumadocs-ui/components/files';
<Files>
<Folder name="app" defaultOpen>
<File name="layout.tsx" />
<File name="page.tsx" />
<File name="global.css" />
</Folder>
<Folder name="components">
<File name="button.tsx" />
<File name="tabs.tsx" />
<File name="dialog.tsx" />
</Folder>
<File name="package.json" />
</Files>
```
### File
{/* <AutoTypeTable path="./content/docs/props.ts" name="FileProps" /> */}
### Folder
{/* <AutoTypeTable path="./content/docs/props.ts" name="FolderProps" /> */}

View File

@ -1,45 +0,0 @@
---
title: GitHub Info
description: Display your GitHub repository information
preview: githubInfo
---
## Usage
```tsx
import { GithubInfo } from 'fumadocs-ui/components/github-info';
<GithubInfo
owner="fuma-nama"
repo="fumadocs"
// your own GitHub access token (optional)
token={process.env.GITHUB_TOKEN}
/>;
```
It's recommended to add it to your docs layout with `links` option:
```tsx title="app/docs/layout.tsx"
import { DocsLayout, type DocsLayoutProps } from 'fumadocs-ui/layouts/notebook';
import type { ReactNode } from 'react';
import { baseOptions } from '@/app/layout.config';
import { source } from '@/lib/source';
import { GithubInfo } from 'fumadocs-ui/components/github-info';
const docsOptions: DocsLayoutProps = {
...baseOptions,
tree: source.pageTree,
links: [
{
type: 'custom',
children: (
<GithubInfo owner="fuma-nama" repo="fumadocs" className="lg:-mx-2" />
),
},
],
};
export default function Layout({ children }: { children: ReactNode }) {
return <DocsLayout {...docsOptions}>{children}</DocsLayout>;
}
```

View File

@ -1,45 +0,0 @@
---
title: GitHub 信息
description: 显示您的 GitHub 仓库信息
preview: githubInfo
---
## 使用方法
```tsx
import { GithubInfo } from 'fumadocs-ui/components/github-info';
<GithubInfo
owner="fuma-nama"
repo="fumadocs"
// 您自己的 GitHub 访问令牌(可选)
token={process.env.GITHUB_TOKEN}
/>;
```
建议将其添加到您的文档布局中,使用 `links` 选项:
```tsx title="app/docs/layout.tsx"
import { DocsLayout, type DocsLayoutProps } from 'fumadocs-ui/layouts/notebook';
import type { ReactNode } from 'react';
import { baseOptions } from '@/app/layout.config';
import { source } from '@/lib/source';
import { GithubInfo } from 'fumadocs-ui/components/github-info';
const docsOptions: DocsLayoutProps = {
...baseOptions,
tree: source.pageTree,
links: [
{
type: 'custom',
children: (
<GithubInfo owner="fuma-nama" repo="fumadocs" className="lg:-mx-2" />
),
},
],
};
export default function Layout({ children }: { children: ReactNode }) {
return <DocsLayout {...docsOptions}>{children}</DocsLayout>;
}
```

View File

@ -1,34 +0,0 @@
---
title: Zoomable Image
description: Allow zoom-in images in your documentation
preview: zoomImage
---
## Usage
Replace `img` with `ImageZoom` in your MDX components.
```tsx title="app/docs/[[...slug]]/page.tsx"
import { ImageZoom } from 'fumadocs-ui/components/image-zoom';
import defaultMdxComponents from 'fumadocs-ui/mdx';
return (
<MdxContent
components={{
...defaultMdxComponents,
img: (props) => <ImageZoom {...(props as any)} />,
// other Mdx components
}}
/>
);
```
Now image zoom will be automatically enabled on all images.
```mdx
![Test](/banner.png)
```
### Image Optimization
A default [`sizes` property](https://nextjs.org/docs/app/api-reference/components/image#sizes) will be defined for Next.js `<Image />` component if not specified.

View File

@ -1,34 +0,0 @@
---
title: 可缩放图片
description: 在文档中允许放大图片
preview: zoomImage
---
## 使用方法
在 MDX 组件中用 `ImageZoom` 替换 `img`。
```tsx title="app/docs/[[...slug]]/page.tsx"
import { ImageZoom } from 'fumadocs-ui/components/image-zoom';
import defaultMdxComponents from 'fumadocs-ui/mdx';
return (
<MdxContent
components={{
...defaultMdxComponents,
img: (props) => <ImageZoom {...(props as any)} />,
// 其他 Mdx 组件
}}
/>
);
```
现在,所有图片都将自动启用图片缩放功能。
```mdx
![Test](/banner.png)
```
### 图片优化
如果未指定,将为 Next.js `<Image />` 组件定义默认的 [`sizes` 属性](https://nextjs.org/docs/app/api-reference/components/image#sizes)。

View File

@ -1,5 +0,0 @@
---
title: Components
description: Additional components to improve your docs
index: true
---

View File

@ -1,5 +0,0 @@
---
title: 组件
description: 改进文档的额外组件
index: true
---

View File

@ -1,31 +0,0 @@
---
title: Inline TOC
description: Add Inline TOC into your documentation
preview: inlineTOC
---
## Usage
Pass TOC items to the component.
```mdx
import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
<InlineTOC items={toc} />
```
### Use in Pages
You can add inline TOC into every page.
```tsx
<DocsPage>
...
<InlineTOC items={toc} />
...
</DocsPage>
```
## Reference
{/* <AutoTypeTable path="./content/docs/props.ts" name="InlineTOCProps" /> */}

View File

@ -1,31 +0,0 @@
---
title: 内联目录
description: 在文档中添加内联目录
preview: inlineTOC
---
## 使用方法
将 TOC 项目传递给组件。
```mdx
import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
<InlineTOC items={toc} />
```
### 在页面中使用
您可以在每个页面中添加内联目录。
```tsx
<DocsPage>
...
<InlineTOC items={toc} />
...
</DocsPage>
```
## 参考
{/* <AutoTypeTable path="./content/docs/props.ts" name="InlineTOCProps" /> */}

View File

@ -1,35 +0,0 @@
---
title: Root Toggle
description: Switch between page trees
preview: rootToggle
---
## Usages
Add this component to your sidebar or other places you want.
```tsx
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { RootToggle } from 'fumadocs-ui/components/layout/root-toggle';
<DocsLayout
sidebar={{
banner: (
<RootToggle
options={[
{
title: 'Folder 1',
description: 'Pages in folder 1',
url: '/path/to/page-tree-1',
},
{
title: 'Folder 2',
description: 'Pages in folder 2',
url: '/path/to/page-tree-2',
},
]}
/>
),
}}
/>;
```

View File

@ -1,35 +0,0 @@
---
title: 根切换器
description: 在页面树之间切换
preview: rootToggle
---
## 使用方法
将此组件添加到您的侧边栏或您想要的其他地方。
```tsx
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { RootToggle } from 'fumadocs-ui/components/layout/root-toggle';
<DocsLayout
sidebar={{
banner: (
<RootToggle
options={[
{
title: '文件夹 1',
description: '文件夹 1 中的页面',
url: '/path/to/page-tree-1',
},
{
title: '文件夹 2',
description: '文件夹 2 中的页面',
url: '/path/to/page-tree-2',
},
]}
/>
),
}}
/>;
```

View File

@ -1,57 +0,0 @@
---
title: Steps
description: Adding steps to your docs
preview: steps
---
## Usage
Put your steps into the `Steps` container.
```mdx
import { Step, Steps } from 'fumadocs-ui/components/steps';
<Steps>
<Step>
### Hello World
</Step>
<Step>
### Hello World
</Step>
</Steps>
```
> We recommend using Tailwind CSS utility classes directly on Tailwind CSS projects.
### Without imports
You can use the Tailwind CSS utilities without importing it.
```mdx
<div className="fd-steps">
<div className="fd-step" />
</div>
```
It supports adding step styles to only headings with arbitrary variants.
```mdx
<div className='fd-steps [&_h3]:fd-step'>
### Hello World
</div>
```
<div className='fd-steps [&_h3]:fd-step'>
### Hello World
You no longer need to use the step component anymore.
</div>

View File

@ -1,57 +0,0 @@
---
title: 步骤
description: 在文档中添加步骤
preview: steps
---
## 使用方法
将您的步骤放入 `Steps` 容器中。
```mdx
import { Step, Steps } from 'fumadocs-ui/components/steps';
<Steps>
<Step>
### 你好世界
</Step>
<Step>
### 你好世界
</Step>
</Steps>
```
> 我们建议在 Tailwind CSS 项目中直接使用 Tailwind CSS 实用类。
### 不使用导入
您可以在不导入的情况下使用 Tailwind CSS 实用工具。
```mdx
<div className="fd-steps">
<div className="fd-step" />
</div>
```
它支持仅对带有任意变体的标题添加步骤样式。
```mdx
<div className='fd-steps [&_h3]:fd-step'>
### 你好世界
</div>
```
<div className='fd-steps [&_h3]:fd-step'>
### 你好世界
您不再需要使用步骤组件了。
</div>

View File

@ -1,146 +0,0 @@
---
title: Tabs
description:
A Tabs component built with Radix UI, with additional features such as
persistent and shared value.
preview: tabs
---
## Usage
Import it in your MDX documents.
```mdx
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
<Tabs items={['Javascript', 'Rust']}>
<Tab value="Javascript">Javascript is weird</Tab>
<Tab value="Rust">Rust is fast</Tab>
</Tabs>
```
### Without `value`
Without a `value`, it detects from the children index. Note that it might cause errors on re-renders, it's not encouraged if the tabs might change.
```mdx
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
<Tabs items={['Javascript', 'Rust']}>
<Tab>Javascript is weird</Tab>
<Tab>Rust is fast</Tab>
</Tabs>
```
#### Demo with Re-renders
<Tabs items={['Javascript', 'Rust']}>
<Tab>Javascript is weird</Tab>
<Tab>Rust is fast</Tab>
</Tabs>
{/* <WithoutValueTest /> */}
### Shared Value
By passing an `groupId` property, you can share a value across all tabs with the same
id.
```mdx
<Tabs groupId="language" items={['Javascript', 'Rust']}>
<Tab value="Javascript">Javascript is weird</Tab>
<Tab value="Rust">Rust is fast</Tab>
</Tabs>
```
### Persistent
You can enable persistent by passing a `persist` property. The value will be
stored in `localStorage`, with its id as the key.
```mdx
<Tabs groupId="language" items={['Javascript', 'Rust']} persist>
<Tab value="Javascript">Javascript is weird</Tab>
<Tab value="Rust">Rust is fast</Tab>
</Tabs>
```
> Persistent only works if you have passed an `id`.
### Default Value
Set a default value by passing `defaultIndex`.
```mdx
<Tabs items={['Javascript', 'Rust']} defaultIndex={1}>
<Tab value="Javascript">Javascript is weird</Tab>
<Tab value="Rust">Rust is fast</Tab>
</Tabs>
```
### Link to Tab
Use HTML `id` attribute to link to a specific tab.
```mdx
<Tabs items={['Javascript', 'Rust', 'C++']}>
<Tab value="Javascript">Javascript is weird</Tab>
<Tab value="Rust">Rust is fast</Tab>
<Tab id="tab-cpp" value="C++">
`Hello World`
</Tab>
</Tabs>
```
You can add the hash `#tab-cpp` to your URL and reload, the C++ tab will be activated.
<Tabs items={['Javascript', 'Rust', 'C++']}>
<Tab value="Javascript">Javascript is weird</Tab>
<Tab value="Rust">Rust is fast</Tab>
<Tab id="tab-cpp" value="C++">
`Hello World`
</Tab>
</Tabs>
Additionally, the `updateAnchor` property can be set to `true` in the `Tabs` component
to automatically update the URL hash whenever time a new tab is selected:
```mdx
<Tabs items={['Javascript', 'Rust', 'C++']} updateAnchor>
<Tab id="tab-js" value="Javascript">
Javascript is weird
</Tab>
<Tab id="tab-rs" value="Rust">
Rust is fast
</Tab>
<Tab id="tab-cpp" value="C++">
`Hello World`
</Tab>
</Tabs>
```
{/* <UrlBar /> */}
<Tabs items={['Hello', 'World']} updateAnchor>
<Tab id="tab-hello" value="Hello">
Hello!
</Tab>
<Tab id="tab-world" value="World">
World!
</Tab>
</Tabs>
### Advanced
You can use the styled Radix UI primitive directly from exported `Primitive`.
```mdx
import { Primitive } from 'fumadocs-ui/components/tabs';
<Primitive.Tabs>
<Primitive.TabsList>
<Primitive.TabsTrigger />
</Primitive.TabsList>
<Primitive.TabsContent />
</Primitive.Tabs>
```

View File

@ -1,114 +0,0 @@
---
title: 选项卡
description:
使用 Radix UI 构建的选项卡组件,具有持久性和共享值等附加功能。
preview: tabs
---
## 使用方法
在 MDX 文档中导入它。
```mdx
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
<Tabs items={['Javascript', 'Rust']}>
<Tab value="Javascript">Javascript 很奇怪</Tab>
<Tab value="Rust">Rust 很快</Tab>
</Tabs>
```
### 不使用 `value`
如果没有 `value`,它会从子元素索引中检测。请注意,这可能会在重新渲染时导致错误,如果选项卡可能会改变,不建议这样做。
```mdx
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
<Tabs items={['Javascript', 'Rust']}>
<Tab>Javascript 很奇怪</Tab>
<Tab>Rust 很快</Tab>
</Tabs>
```
### 共享值
通过传递 `groupId` 属性,您可以在具有相同 ID 的所有选项卡之间共享值。
```mdx
<Tabs groupId="language" items={['Javascript', 'Rust']}>
<Tab value="Javascript">Javascript 很奇怪</Tab>
<Tab value="Rust">Rust 很快</Tab>
</Tabs>
```
### 持久性
您可以通过传递 `persist` 属性启用持久性。该值将存储在 `localStorage` 中,以其 ID 作为键。
```mdx
<Tabs groupId="language" items={['Javascript', 'Rust']} persist>
<Tab value="Javascript">Javascript 很奇怪</Tab>
<Tab value="Rust">Rust 很快</Tab>
</Tabs>
```
> 持久性仅在您传递了 `id` 时有效。
### 默认值
通过传递 `defaultIndex` 设置默认值。
```mdx
<Tabs items={['Javascript', 'Rust']} defaultIndex={1}>
<Tab value="Javascript">Javascript 很奇怪</Tab>
<Tab value="Rust">Rust 很快</Tab>
</Tabs>
```
### 链接到选项卡
使用 HTML `id` 属性链接到特定选项卡。
```mdx
<Tabs items={['Javascript', 'Rust', 'C++']}>
<Tab value="Javascript">Javascript 很奇怪</Tab>
<Tab value="Rust">Rust 很快</Tab>
<Tab id="tab-cpp" value="C++">
`Hello World`
</Tab>
</Tabs>
```
您可以在 URL 中添加哈希 `#tab-cpp` 并重新加载C++ 选项卡将被激活。
此外,可以在 `Tabs` 组件中将 `updateAnchor` 属性设置为 `true`,以便在每次选择新选项卡时自动更新 URL 哈希:
```mdx
<Tabs items={['Javascript', 'Rust', 'C++']} updateAnchor>
<Tab id="tab-js" value="Javascript">
Javascript 很奇怪
</Tab>
<Tab id="tab-rs" value="Rust">
Rust 很快
</Tab>
<Tab id="tab-cpp" value="C++">
`Hello World`
</Tab>
</Tabs>
```
### 高级用法
您可以直接从导出的 `Primitive` 中使用样式化的 Radix UI 原语。
```mdx
import { Primitive } from 'fumadocs-ui/components/tabs';
<Primitive.Tabs>
<Primitive.TabsList>
<Primitive.TabsTrigger />
</Primitive.TabsList>
<Primitive.TabsContent />
</Primitive.Tabs>
```

View File

@ -1,34 +0,0 @@
---
title: Type Table
description: A table for documenting types
preview: typeTable
---
## Usage
It accepts a `type` property.
```mdx
import { TypeTable } from 'fumadocs-ui/components/type-table';
<TypeTable
type={{
percentage: {
description:
'The percentage of scroll position to display the roll button',
type: 'number',
default: 0.2,
},
}}
/>
```
## References
### Type Table
{/* <AutoTypeTable path="./content/docs/props.ts" name="TypeTableProps" /> */}
### Object Type
{/* <AutoTypeTable path="./content/docs/props.ts" name="ObjectTypeProps" /> */}

View File

@ -1,34 +0,0 @@
---
title: 类型表格
description: 用于记录类型的表格
preview: typeTable
---
## 使用方法
它接受一个 `type` 属性。
```mdx
import { TypeTable } from 'fumadocs-ui/components/type-table';
<TypeTable
type={{
percentage: {
description:
'显示滚动按钮的滚动位置百分比',
type: 'number',
default: 0.2,
},
}}
/>
```
## 参考
### Type Table
{/* <AutoTypeTable path="./content/docs/props.ts" name="TypeTableProps" /> */}
### Object Type
{/* <AutoTypeTable path="./content/docs/props.ts" name="ObjectTypeProps" /> */}

View File

@ -1,51 +0,0 @@
---
title: Overview
description: An overview of Fumadocs UI
---
## Architecture
### Page Tree
Navigation elements like sidebar take a [Page Tree](/docs/headless/page-tree) to render navigation links, it's a tree that describes all available pages and folders.
Normally, it is generated from your file structure using [`loader()`](/docs/headless/source-api), you can learn [how to organize pages](/docs/page-conventions).
## Customisation
### Layouts
You can use the exposed options of different layouts:
<Cards>
<Card title="Docs Layout" href="/docs/layouts/docs">
Layout for docs
</Card>
<Card title="Docs Page" href="/docs/layouts/page">
Layout for docs content
</Card>
<Card title="Notebook Layout" href="/docs/layouts/notebook">
A more compact version of Docs Layout
</Card>
<Card title="Home Layout" href="/docs/layouts/home-layout">
Layout for other pages
</Card>
</Cards>
### Components
Fumadocs UI also offers styled components for interactive examples to enhance your docs, you can customise them with exposed props like `style` and `className`.
See [Components](/docs/components).
### Design System
Since the design system is built on Tailwind CSS, you can customise it [with CSS Variables](/docs/theme#colors).
### CLI
If none of them suits you, Fumadocs CLI is a tool to install Fumadocs UI components and layouts to your codebase, similar to Shadcn UI. Allowing you to fully customise Fumadocs UI:
```package-install
npx fumadocs add
```

View File

@ -1,51 +0,0 @@
---
title: 概览
description: Fumadocs UI 的概览
---
## 架构
### 页面树
侧边栏等导航元素使用[页面树](/docs/headless/page-tree)来渲染导航链接,它是描述所有可用页面和文件夹的树形结构。
通常,它是使用 [`loader()`](/docs/headless/source-api) 从您的文件结构生成的,您可以了解[如何组织页面](/docs/page-conventions)。
## 自定义
### 布局
您可以使用不同布局的暴露选项:
<Cards>
<Card title="文档布局" href="/docs/layouts/docs">
文档的布局
</Card>
<Card title="文档页面" href="/docs/layouts/page">
文档内容的布局
</Card>
<Card title="笔记本布局" href="/docs/layouts/notebook">
文档布局的更紧凑版本
</Card>
<Card title="主页布局" href="/docs/layouts/home-layout">
其他页面的布局
</Card>
</Cards>
### 组件
Fumadocs UI 还提供了样式化组件,用于交互式示例以增强您的文档,您可以使用暴露的道具如 `style` 和 `className` 来自定义它们。
参见[组件](/docs/components)。
### 设计系统
由于设计系统是基于 Tailwind CSS 构建的,您可以[通过 CSS 变量](/docs/theme#colors)自定义它。
### CLI
如果这些都不适合您Fumadocs CLI 是一个工具,可以将 Fumadocs UI 组件和布局安装到您的代码库中,类似于 Shadcn UI。允许您完全自定义 Fumadocs UI
```package-install
npx fumadocs add
```

View File

@ -1,278 +0,0 @@
---
title: Quick Start
description: Getting Started with Fumadocs
icon: Album
---
## Introduction
Fumadocs <span className='text-fd-muted-foreground text-sm'>(Foo-ma docs)</span> is a **documentation framework** based on Next.js, designed to be fast, flexible,
and composes seamlessly into Next.js App Router.
Fumadocs has different parts:
<Cards>
<Card icon={<CpuIcon className="text-purple-300" />} title='Fumadocs Core'>
Handles most of the logic, including document search, content source adapters, and Markdown extensions.
</Card>
<Card icon={<PanelsTopLeft className="text-blue-300" />} title='Fumadocs UI'>
The default theme of Fumadocs offers a beautiful look for documentation sites and interactive components.
</Card>
<Card icon={<Database />} title='Content Source'>
The source of your content, can be a CMS or local data layers like [Content Collections](https://www.content-collections.dev) and [Fumadocs MDX](/docs/mdx), the official content source.
</Card>
<Card icon={<Terminal />} title='Fumadocs CLI'>
A command line tool to install UI components and automate things, useful for customizing layouts.
</Card>
</Cards>
<Callout title="Want to learn more?">
Read our in-depth [What is Fumadocs](/docs/what-is-fumadocs) introduction.
</Callout>
### Terminology
**Markdown/MDX:** Markdown is a markup language for creating formatted text. Fumadocs supports Markdown and MDX (superset of Markdown) out-of-the-box.
Although not required, some basic knowledge of Next.js App Router would be useful for further customisations.
## Automatic Installation
A minimum version of Node.js 18 required, note that Node.js 23.1 might have problems with Next.js production build.
<Tabs groupId='package-manager' persist items={['npm', 'pnpm', 'yarn', 'bun']}>
```bash tab="npm"
npm create fumadocs-app
```
```bash tab="pnpm"
pnpm create fumadocs-app
```
```bash tab="yarn"
yarn create fumadocs-app
```
```bash tab="bun"
bun create fumadocs-app
```
</Tabs>
It will ask you the framework and content source to use, a new fumadocs app should be initialized. Now you can start hacking!
<Callout title='From Existing Codebase?'>
You can follow the [Manual Installation](/docs/manual-installation) guide to get started.
</Callout>
### Enjoy!
Create your first MDX file in the docs folder.
```mdx title="content/docs/index.mdx"
---
title: Hello World
---
## Yo what's up
```
Run the app in development mode and see http://localhost:3000/docs.
```package-install
npm run dev
```
## Explore
In the project, you can see:
- `lib/source.ts`: Code for content source adapter, [`loader()`](/docs/headless/source-api) provides an interface to interact with your content source, and assigns URL to your pages.
- `app/layout.config.tsx`: Shared options for layouts, optional but preferred to keep.
| Route | Description |
| ------------------------- | ------------------------------------------------------ |
| `app/(home)` | The route group for your landing page and other pages. |
| `app/docs` | The documentation layout and pages. |
| `app/api/search/route.ts` | The Route Handler for search. |
### Writing Content
For authoring docs, make sure to read:
<Cards>
<Card href="/docs/markdown" title="Markdown">
Fumadocs has some additional features for authoring content too.
</Card>
<Card href="/docs/navigation" title="Navigation">
Learn how to customise navigation links/sidebar items.
</Card>
</Cards>
### Content Source
Content source handles all your content, like compiling Markdown files and validating frontmatter.
<Tabs items={['Fumadocs MDX', 'Custom Source']}>
<Tab value='Fumadocs MDX'>
Read the [Introduction](/docs/mdx) to learn how it handles your content.
A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
</Tab>
<Tab value='Custom Source'>
Fumadocs is not Markdown-exclusive. For other sources like Sanity, you can build a [custom content source](/docs/headless/custom-source).
</Tab>
</Tabs>
### Customise UI
See [Customisation Guide](/docs/customisation).
## FAQ
Some common questions you may encounter.
<Accordions>
<Accordion id='fix-monorepo-styling' title="How to fix stylings not being applied in Monorepo?">
Sometimes, `fumadocs-ui` is not installed in the workspace of your Tailwind CSS configuration file. (e.g. a monorepo setup).
You have to ensure the `fumadocs-ui` package is scanned by Tailwind CSS, and give a correct relative path to `@source`.
For example, add `../../` to point to the `node_modules` folder in root workspace.
```css
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
/* [!code --] */
@source '../node_modules/fumadocs-ui/dist/**/*.js';
/* [!code ++] */
@source '../../../node_modules/fumadocs-ui/dist/**/*.js';
```
</Accordion>
<Accordion id='change-base-url' title="How to change the base route of /docs?">
You can change the base route of docs (e.g. from `/docs/page` to `/info/page`).
Since Fumadocs uses Next.js App Router, you can simply rename the route:
<Files>
<Folder name="app/docs" defaultOpen className="opacity-50" disabled>
<File name="layout.tsx" />
</Folder>
<Folder name="app/info" defaultOpen>
<File name="layout.tsx" />
</Folder>
</Files>
And tell Fumadocs to use the new route in `source.ts`:
```ts title="lib/source.ts"
import { loader } from 'fumadocs-core/source';
export const source = loader({
baseUrl: '/info',
// other options
});
```
</Accordion>
<Accordion id='dynamic-route' title="It uses Dynamic Route, will it be poor in performance?">
Next.js turns dynamic route into static routes when `generateStaticParams` is configured.
Hence, it is as fast as static pages.
You can enable Static Exports on Next.js to get a static build output. (Notice that Route Handler doesn't work with static export, you have to configure static search)
</Accordion>
<Accordion id='custom-layout-docs-page' title='How to create a page in /docs without docs layout?'>
Same as managing layouts in Next.js App Router, remove the original MDX file from content directory (`/content/docs`).
This ensures duplicated pages will not cause errors.
Now, You can add the page to another route group, which isn't a descendant of docs layout.
For example, under your `app` folder:
<Files>
<File name="(home)/docs/page.tsx" />
<Folder name="docs">
<File name="layout.tsx" />
<File name="[[...slug]]/page.tsx" />
</Folder>
</Files>
will replace the `/docs` page with your `page.tsx`.
</Accordion>
<Accordion id='multi-versions' title="How to implement docs with multi-version?">
Use a separate deployment for each version.
On Vercel, this can be done by creating another branch for a specific version on your GitHub repository.
To link to the sites of other versions, use the Links API or a custom navigation component.
</Accordion>
<Accordion id='multi-docs' title="How to implement multi-docs?">
We recommend to use [Sidebar Tabs](/docs/navigation/sidebar#sidebar-tabs).
</Accordion>
</Accordions>
## Video Tutorials
<YoutubeVideo url="https://www.youtube.com/embed/BPnK-YbISHQ?si=TH_tI3e4MCgMHzGr" />
## Learn More
New to here? Don't worry, we are welcome for your questions.
If you find anything confusing, please give your feedback on [Github Discussion](https://github.com/fuma-nama/fumadocs/discussions)!
<Cards>
<Card
href="/docs/static-export"
title="Configure Static Export"
description="Learn how to enable static export on your docs"
/>
<Card
href="/docs/search"
title="Customise Search"
description="Learn how to customise document search"
/>
<Card
href="/docs/theme"
title="Theming"
description="Add themes to Fumadocs UI"
/>
<Card
href="/docs/components"
title="Components"
description="See all available components to enhance your docs"
/>
</Cards>

View File

@ -1,253 +0,0 @@
---
title: 快速入门
description: Fumadocs 入门指南
icon: Album
---
## 简介
Fumadocs <span className='text-fd-muted-foreground text-sm'>(Foo-ma docs)</span> 是一个基于 Next.js 的**文档框架**,设计为快速、灵活,
并无缝集成到 Next.js App Router 中。
Fumadocs 由不同部分组成:
<Cards>
<Card icon={<CpuIcon className="text-purple-300" />} title='Fumadocs Core'>
处理大部分逻辑,包括文档搜索、内容源适配器和 Markdown 扩展。
</Card>
<Card icon={<PanelsTopLeft className="text-blue-300" />} title='Fumadocs UI'>
Fumadocs 的默认主题为文档站点提供了美观的外观和交互式组件。
</Card>
<Card icon={<Database />} title='Content Source'>
您内容的来源,可以是 CMS 或本地数据层,如 [Content Collections](https://www.content-collections.dev) 和 [Fumadocs MDX](/docs/mdx),即官方内容源。
</Card>
<Card icon={<Terminal />} title='Fumadocs CLI'>
一个命令行工具,用于安装 UI 组件和自动化操作,对于自定义布局非常有用。
</Card>
</Cards>
<Callout title="想了解更多?">
阅读我们深入的 [什么是 Fumadocs](/docs/what-is-fumadocs) 介绍。
</Callout>
### 术语
**Markdown/MDX:** Markdown 是一种用于创建格式化文本的标记语言。Fumadocs 默认支持 Markdown 和 MDXMarkdown 的超集)。
虽然不是必需的,但对 Next.js App Router 的基本了解对于进一步的自定义会很有帮助。
## 自动安装
需要 Node.js 18 或更高版本,请注意 Node.js 23.1 可能在 Next.js 生产构建中存在问题。
<Tabs groupId='package-manager' persist items={['npm', 'pnpm', 'yarn', 'bun']}>
```bash tab="npm"
npm create fumadocs-app
```
```bash tab="pnpm"
pnpm create fumadocs-app
```
```bash tab="yarn"
yarn create fumadocs-app
```
```bash tab="bun"
bun create fumadocs-app
```
</Tabs>
它会询问您要使用的框架和内容源,随后将初始化一个新的 fumadocs 应用程序。现在您可以开始动手了!
<Callout title='从现有代码库开始?'>
您可以按照 [手动安装](/docs/manual-installation) 指南开始。
</Callout>
### 尽情使用!
在 docs 文件夹中创建您的第一个 MDX 文件。
```mdx title="content/docs/index.mdx"
---
title: Hello World
---
## Yo what's up
```
在开发模式下运行应用程序并查看 http://localhost:3000/docs。
```package-install
npm run dev
```
## 探索
在项目中,您可以看到:
- `lib/source.ts`:内容源适配器的代码,[`loader()`](/docs/headless/source-api) 提供了与内容源交互的接口,并为您的页面分配 URL。
- `app/layout.config.tsx`:布局的共享选项,可选但建议保留。
| 路由 | 描述 |
| ------------------------- | -------------------------------------- |
| `app/(home)` | 您的登陆页面和其他页面的路由组。 |
| `app/docs` | 文档布局和页面。 |
| `app/api/search/route.ts` | 搜索的路由处理器。 |
### 编写内容
对于编写文档,请务必阅读:
<Cards>
<Card href="/docs/markdown" title="Markdown">
Fumadocs 还有一些额外的内容创作功能。
</Card>
<Card href="/docs/navigation" title="Navigation">
了解如何自定义导航链接/侧边栏项目。
</Card>
</Cards>
### 内容源
内容源处理您的所有内容,例如编译 Markdown 文件和验证前言。
<Tabs items={['Fumadocs MDX', 'Custom Source']}>
<Tab value='Fumadocs MDX'>
阅读 [介绍](/docs/mdx) 了解它如何处理您的内容。
项目中已包含 `source.config.ts` 配置文件,您可以自定义不同的选项,如前言模式。
</Tab>
<Tab value='Custom Source'>
Fumadocs 不仅限于 Markdown。对于其他源如 Sanity您可以构建 [自定义内容源](/docs/headless/custom-source)。
</Tab>
</Tabs>
### 自定义 UI
请参阅 [自定义指南](/docs/customisation)。
## 常见问题
您可能遇到的一些常见问题。
<Accordions>
<Accordion id='fix-monorepo-styling' title="如何修复 Monorepo 中样式不应用的问题?">
有时,`fumadocs-ui` 没有安装在您的 Tailwind CSS 配置文件的工作区中(例如,在 monorepo 设置中)。
您必须确保 Tailwind CSS 扫描 `fumadocs-ui` 包,并为 `@source` 提供正确的相对路径。
例如,添加 `../../` 指向根工作区中的 `node_modules` 文件夹。
```css
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
/* [!code --] */
@source '../node_modules/fumadocs-ui/dist/**/*.js';
/* [!code ++] */
@source '../../../node_modules/fumadocs-ui/dist/**/*.js';
```
</Accordion>
<Accordion id='change-base-url' title="如何更改 /docs 的基本路由?">
您可以更改文档的基本路由(例如,从 `/docs/page` 更改为 `/info/page`)。
由于 Fumadocs 使用 Next.js App Router您可以简单地重命名路由
<Files>
<Folder name="app/docs" defaultOpen className="opacity-50" disabled>
<File name="layout.tsx" />
</Folder>
<Folder name="app/info" defaultOpen>
<File name="layout.tsx" />
</Folder>
</Files>
并在 `source.ts` 中告诉 Fumadocs 使用新的路由:
```ts title="lib/source.ts"
import { loader } from 'fumadocs-core/source';
export const source = loader({
baseUrl: '/info',
// other options
});
```
</Accordion>
<Accordion id='dynamic-route' title="它使用动态路由,性能会很差吗?">
当配置了 `generateStaticParams` 时Next.js 会将动态路由转换为静态路由。
因此,它与静态页面一样快。
您可以在 Next.js 上启用静态导出,获得静态构建输出。(请注意,路由处理器不适用于静态导出,您必须配置静态搜索)
</Accordion>
<Accordion id='custom-layout-docs-page' title='如何在 /docs 中创建没有文档布局的页面?'>
与在 Next.js App Router 中管理布局相同,从内容目录(`/content/docs`)中删除原始 MDX 文件。
这确保重复的页面不会导致错误。
现在,您可以将页面添加到另一个路由组,该组不是文档布局的后代。
例如,在您的 `app` 文件夹下:
<Files>
<File name="(home)/docs/page.tsx" />
<Folder name="docs">
<File name="layout.tsx" />
<File name="[[...slug]]/page.tsx" />
</Folder>
</Files>
将用您的 `page.tsx` 替换 `/docs` 页面。
</Accordion>
<Accordion id='multi-versions' title="如何实现多版本文档?">
为每个版本使用单独的部署。
在 Vercel 上,可以通过在 GitHub 存储库中为特定版本创建另一个分支来实现。
要链接到其他版本的站点,请使用 Links API 或自定义导航组件。
</Accordion>
<Accordion id='multi-docs' title="如何实现多文档?">
我们建议使用 [侧边栏标签](/docs/navigation/sidebar#sidebar-tabs)。
</Accordion>
</Accordions>
## 视频教程
<YoutubeVideo url="https://www.youtube.com/embed/BPnK-YbISHQ?si=TH_tI3e4MCgMHzGr" />
## 了解更多
刚来这里?别担心,我们欢迎您的问题。

View File

@ -1,222 +0,0 @@
---
title: Internationalization
description: Support multiple languages in your documentation
---
<Callout title='Before you get started'>
Fumadocs is not a full-powered i18n library, it manages only its own components and utilities.
You can use other libraries like [next-intl](https://github.com/amannn/next-intl) for the rest of your app.
Read the [Next.js Docs](https://nextjs.org/docs/app/building-your-application/routing/internationalization) to learn more about implementing I18n in Next.js.
</Callout>
## Manual Setup
Define the i18n configurations in a file, we will import it with `@/ilb/i18n` in this guide.
{/* <include cwd meta='title="lib/i18n.ts"'>
../../examples/i18n/lib/i18n.ts
</include> */}
Pass it to the source loader.
```ts title="lib/source.ts"
import { i18n } from '@/lib/i18n';
import { loader } from 'fumadocs-core/source';
export const source = loader({
i18n, // [!code highlight]
// other options
});
```
And update Fumadocs UI layout options.
```tsx title="app/layout.config.tsx"
import { i18n } from '@/lib/i18n';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
export function baseOptions(locale: string): BaseLayoutProps {
return {
i18n,
// different props based on `locale`
};
}
```
### Middleware
Create a middleware that redirects users to appropriate locale.
```json doc-gen:file
{
"file": "../../examples/i18n/middleware.ts",
"codeblock": {
"lang": "ts",
"meta": "title=\"middleware.ts\""
}
}
```
See [Middleware](/docs/headless/internationalization#middleware) for customisable options.
> Note that this is optional, you can also use your own middleware or the one provided by i18n libraries.
### Routing
Create a `/app/[lang]` folder, and move all files (e.g. `page.tsx`, `layout.tsx`) from `/app` to the folder.
Wrap the root provider inside `I18nProvider`, and provide available languages & translations to it.
Note that only English translations are provided by default.
```tsx title="app/[lang]/layout.tsx"
import { RootProvider } from 'fumadocs-ui/provider';
import { I18nProvider, type Translations } from 'fumadocs-ui/i18n';
const cn: Partial<Translations> = {
search: 'Translated Content',
// other translations
};
// available languages that will be displayed on UI
// make sure `locale` is consistent with your i18n config
const locales = [
{
name: 'English',
locale: 'en',
},
{
name: 'Chinese',
locale: 'cn',
},
];
export default async function RootLayout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: React.ReactNode;
}) {
const lang = (await params).lang;
return (
<html lang={lang}>
<body>
<I18nProvider
locale={lang}
locales={locales}
translations={{ cn }[lang]}
>
<RootProvider>{children}</RootProvider>
</I18nProvider>
</body>
</html>
);
}
```
### Pass Locale
Pass the locale to Fumadocs in your pages and layouts.
{/* ```tsx title="/app/[lang]/(home)/layout.tsx" tab="Home Layout"
import type { ReactNode } from 'react';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/app/layout.config';
export default async function Layout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: ReactNode;
}) {
const { lang } = await params;
return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
}
```
```tsx title="/app/[lang]/docs/layout.tsx" tab="Docs Layout"
import type { ReactNode } from 'react';
import { source } from '@/lib/source';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/app/layout.config';
export default async function Layout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: ReactNode;
}) {
const { lang } = await params;
return (
<DocsLayout {...baseOptions(lang)} tree={source.pageTree[lang]}>
{children}
</DocsLayout>
);
}
```
```ts title="page.tsx" tab="Docs Page"
import { source } from '@/lib/source';
export default async function Page({
params,
}: {
params: Promise<{ lang: string; slug?: string[] }>;
}) {
const { slug, lang } = await params;
// get page
source.getPage(slug); // [!code --]
source.getPage(slug, lang); // [!code ++]
// get pages
source.getPages(); // [!code --]
source.getPages(lang); // [!code ++]
}
``` */}
### Search
Configure i18n on your search solution.
- **Built-in Search (Orama):**
For [Supported Languages](https://docs.orama.com/open-source/supported-languages#officially-supported-languages), no further changes are needed.
Otherwise, additional config is required (e.g. Chinese & Japanese). See [Special Languages](/docs/headless/search/orama#special-languages).
- **Cloud Solutions (e.g. Algolia):**
They usually have official support for multilingual.
## Writing Documents
{/* <include>../../shared/page-conventions.i18n.mdx</include> */}
## Navigation
Fumadocs only handles navigation for its own layouts (e.g. sidebar).
For other places, you can use the `useParams` hook to get the locale from url, and attend it to `href`.
```tsx
import Link from 'next/link';
import { useParams } from 'next/navigation';
const { lang } = useParams();
return <Link href={`/${lang}/another-page`}>This is a link</Link>;
```
In addition, the [`fumadocs-core/dynamic-link`](/docs/headless/components/link#dynamic-hrefs) component supports dynamic hrefs, you can use it to attend the locale prefix.
It is useful for Markdown/MDX content.
```mdx title="content.mdx"
import { DynamicLink } from 'fumadocs-core/dynamic-link';
<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>
```

View File

@ -1,222 +0,0 @@
---
title: 国际化
description: 在您的文档中支持多种语言
---
<Callout title='开始之前'>
Fumadocs 不是一个功能齐全的 i18n 库,它只管理自己的组件和工具。
您可以使用其他库,如 [next-intl](https://github.com/amannn/next-intl),用于应用程序的其余部分。
阅读 [Next.js 文档](https://nextjs.org/docs/app/building-your-application/routing/internationalization),了解更多关于在 Next.js 中实现 I18n 的信息。
</Callout>
## 手动设置
在一个文件中定义 i18n 配置,我们将在本指南中使用 `@/ilb/i18n` 导入它。
{/* <include cwd meta='title="lib/i18n.ts"'>
../../examples/i18n/lib/i18n.ts
</include> */}
将其传递给源加载器。
```ts title="lib/source.ts"
import { i18n } from '@/lib/i18n';
import { loader } from 'fumadocs-core/source';
export const source = loader({
i18n, // [!code highlight]
// other options
});
```
并更新 Fumadocs UI 布局选项。
```tsx title="app/layout.config.tsx"
import { i18n } from '@/lib/i18n';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
export function baseOptions(locale: string): BaseLayoutProps {
return {
i18n,
// different props based on `locale`
};
}
```
### 中间件
创建一个将用户重定向到适当语言环境的中间件。
```json doc-gen:file
{
"file": "../../examples/i18n/middleware.ts",
"codeblock": {
"lang": "ts",
"meta": "title=\"middleware.ts\""
}
}
```
查看[中间件](/docs/headless/internationalization#middleware)了解可自定义选项。
> 请注意,这是可选的,您也可以使用自己的中间件或 i18n 库提供的中间件。
### 路由
创建一个 `/app/[lang]` 文件夹,并将所有文件(例如 `page.tsx`、`layout.tsx`)从 `/app` 移动到该文件夹。
将根提供程序包装在 `I18nProvider` 中,并向其提供可用语言和翻译。
请注意,默认情况下只提供英文翻译。
```tsx title="app/[lang]/layout.tsx"
import { RootProvider } from 'fumadocs-ui/provider';
import { I18nProvider, type Translations } from 'fumadocs-ui/i18n';
const cn: Partial<Translations> = {
search: 'Translated Content',
// other translations
};
// available languages that will be displayed on UI
// make sure `locale` is consistent with your i18n config
const locales = [
{
name: 'English',
locale: 'en',
},
{
name: 'Chinese',
locale: 'cn',
},
];
export default async function RootLayout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: React.ReactNode;
}) {
const lang = (await params).lang;
return (
<html lang={lang}>
<body>
<I18nProvider
locale={lang}
locales={locales}
translations={{ cn }[lang]}
>
<RootProvider>{children}</RootProvider>
</I18nProvider>
</body>
</html>
);
}
```
### 传递区域设置
在您的页面和布局中将区域设置传递给 Fumadocs。
{/* ```tsx title="/app/[lang]/(home)/layout.tsx" tab="Home Layout"
import type { ReactNode } from 'react';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/app/layout.config';
export default async function Layout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: ReactNode;
}) {
const { lang } = await params;
return <HomeLayout {...baseOptions(lang)}>{children}</HomeLayout>;
}
```
```tsx title="/app/[lang]/docs/layout.tsx" tab="Docs Layout"
import type { ReactNode } from 'react';
import { source } from '@/lib/source';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/app/layout.config';
export default async function Layout({
params,
children,
}: {
params: Promise<{ lang: string }>;
children: ReactNode;
}) {
const { lang } = await params;
return (
<DocsLayout {...baseOptions(lang)} tree={source.pageTree[lang]}>
{children}
</DocsLayout>
);
}
```
```ts title="page.tsx" tab="Docs Page"
import { source } from '@/lib/source';
export default async function Page({
params,
}: {
params: Promise<{ lang: string; slug?: string[] }>;
}) {
const { slug, lang } = await params;
// get page
source.getPage(slug); // [!code --]
source.getPage(slug, lang); // [!code ++]
// get pages
source.getPages(); // [!code --]
source.getPages(lang); // [!code ++]
}
``` */}
### 搜索
在您的搜索解决方案上配置 i18n。
- **内置搜索 (Orama)**
对于[支持的语言](https://docs.orama.com/open-source/supported-languages#officially-supported-languages),无需进一步更改。
否则,需要额外配置(例如中文和日语)。请参阅[特殊语言](/docs/headless/search/orama#special-languages)。
- **云解决方案(例如 Algolia**
它们通常官方支持多语言。
## 编写文档
{/* <include>../../shared/page-conventions.i18n.mdx</include> */}
## 导航
Fumadocs 只处理其自己的布局(例如侧边栏)的导航。
对于其他地方,您可以使用 `useParams` 钩子从 url 获取区域设置,并将其添加到 `href`。
```tsx
import Link from 'next/link';
import { useParams } from 'next/navigation';
const { lang } = useParams();
return <Link href={`/${lang}/another-page`}>This is a link</Link>;
```
另外,[`fumadocs-core/dynamic-link`](/docs/headless/components/link#dynamic-hrefs) 组件支持动态 hrefs您可以使用它来添加区域设置前缀。
这对于 Markdown/MDX 内容很有用。
```mdx title="content.mdx"
import { DynamicLink } from 'fumadocs-core/dynamic-link';
<DynamicLink href="/[lang]/another-page">This is a link</DynamicLink>
```

View File

@ -1,166 +0,0 @@
---
title: Docs Layout
description: The layout of documentation
---
The layout of documentation pages, it includes a sidebar and mobile-only navbar.
> It is a server component, you should not reference it in a client component.
## Usage
Pass your page tree to the component.
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/app/layout.config';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout {...baseOptions} tree={tree}>
{children}
</DocsLayout>
);
}
```
{/* <AutoTypeTable
path="./content/docs/props.ts"
type="Omit<DocsLayoutProps, 'children' | 'disableThemeSwitch'>"
/> */}
## Sidebar
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
<DocsLayout
sidebar={{
// sidebar options:
enabled: true,
}}
/>;
```
{/* <AutoTypeTable path="./content/docs/props.ts" name="SidebarProps" /> */}
### Sidebar Tabs
See [Navigation Guide](/docs/navigation/sidebar#sidebar-tabs) for usages.
#### Decoration
Change the icon/styles of tabs.
```tsx
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
<DocsLayout
sidebar={{
tabs: {
transform: (option, node) => ({
...option,
icon: 'my icon',
}),
},
}}
/>;
```
## Nav
A mobile-only navbar, we recommend to customise it from `baseOptions`.
<div className='max-w-[460px] mx-auto'>
![Docs Nav](/images/docs/docs-nav.png)
</div>
```tsx
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
export const baseOptions: BaseLayoutProps = {
githubUrl: 'https://github.com/fuma-nama/fumadocs',
nav: {
title: 'My App',
},
};
```
{/* <AutoTypeTable
path="./content/docs/props.ts"
type="Omit<NavbarProps, 'children'>"
/> */}
### Transparent Mode
To make the navbar background transparent, you can configure transparent mode.
```tsx
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
export const baseOptions: BaseLayoutProps = {
nav: {
transparentMode: 'top',
},
};
```
| Mode | Description |
| -------- | ---------------------------------------- |
| `always` | Always use a transparent background |
| `top` | When at the top of page |
| `none` | Disable transparent background (default) |
### Replace Navbar
To replace the navbar in Docs Layout, set `nav.component` to your own component.
```tsx title="layout.tsx"
import { baseOptions } from '@/app/layout.config';
import { DocsLayout } from 'fumadocs-ui/layouts/notebook';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
{...baseOptions}
nav={{
component: <CustomNavbar />,
}}
>
{children}
</DocsLayout>
);
}
```
Fumadocs uses **CSS Variables** to share the size of layout components, and fit each layout component into appropriate position.
You need to override `--fd-nav-height` to the exact height of your custom navbar, this can be done with a CSS stylesheet (e.g. in `global.css`):
```css
:root {
--fd-nav-height: 80px !important;
}
```
## Advanced
### Disable Prefetching
By default, it uses the Next.js Link component with prefetch enabled.
When the link component appears into the browser viewport, the content (RSC payload) will be prefetched.
On Vercel, this may cause a high usage of serverless functions and Data Cache.
It can also hit the limits of some other hosting platforms.
You can disable prefetching to reduce the amount of RSC requests.
```tsx
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
<DocsLayout sidebar={{ prefetch: false }} />;
```

View File

@ -1,160 +0,0 @@
---
title: 文档布局
description: 文档的布局
---
文档页面的布局,它包括一个侧边栏和仅限移动设备的导航栏。
> 它是一个服务器组件,您不应该在客户端组件中引用它。
## 使用方法
将您的页面树传递给组件。
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/app/layout.config';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout {...baseOptions} tree={tree}>
{children}
</DocsLayout>
);
}
```
{/* <AutoTypeTable
path="./content/docs/props.ts"
type="Omit<DocsLayoutProps, 'children' | 'disableThemeSwitch'>"
/> */}
## 侧边栏
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
<DocsLayout
sidebar={{
// sidebar options:
enabled: true,
}}
/>;
```
{/* <AutoTypeTable path="./content/docs/props.ts" name="SidebarProps" /> */}
### 侧边栏标签
有关用法,请参见[导航指南](/docs/navigation/sidebar#sidebar-tabs)。
#### 装饰
更改标签的图标/样式。
```tsx
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
<DocsLayout
sidebar={{
tabs: {
transform: (option, node) => ({
...option,
icon: 'my icon',
}),
},
}}
/>;
```
## 导航栏
一个仅限移动设备的导航栏,我们建议从 `baseOptions` 自定义它。
```tsx
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
export const baseOptions: BaseLayoutProps = {
githubUrl: 'https://github.com/fuma-nama/fumadocs',
nav: {
title: 'My App',
},
};
```
{/* <AutoTypeTable
path="./content/docs/props.ts"
type="Omit<NavbarProps, 'children'>"
/> */}
### 透明模式
要使导航栏背景透明,您可以配置透明模式。
```tsx
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
export const baseOptions: BaseLayoutProps = {
nav: {
transparentMode: 'top',
},
};
```
| 模式 | 描述 |
| -------- | ------------------------------ |
| `always` | 始终使用透明背景 |
| `top` | 在页面顶部时 |
| `none` | 禁用透明背景(默认) |
### 替换导航栏
要替换文档布局中的导航栏,将 `nav.component` 设置为您自己的组件。
```tsx title="layout.tsx"
import { baseOptions } from '@/app/layout.config';
import { DocsLayout } from 'fumadocs-ui/layouts/notebook';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
{...baseOptions}
nav={{
component: <CustomNavbar />,
}}
>
{children}
</DocsLayout>
);
}
```
Fumadocs 使用 **CSS 变量**来共享布局组件的大小,并将每个布局组件放置在适当的位置。
您需要将 `--fd-nav-height` 覆盖为自定义导航栏的确切高度,这可以通过 CSS 样式表(例如在 `global.css` 中)完成:
```css
:root {
--fd-nav-height: 80px !important;
}
```
## 高级
### 禁用预取
默认情况下,它使用启用了预取的 Next.js Link 组件。
当链接组件出现在浏览器视口中时内容RSC 有效载荷)将被预取。
在 Vercel 上,这可能会导致大量使用无服务器函数和数据缓存。
它也可能会达到一些其他托管平台的限制。
您可以禁用预取以减少 RSC 请求的数量。
```tsx
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
<DocsLayout sidebar={{ prefetch: false }} />;
```

View File

@ -1,33 +0,0 @@
---
title: Home Layout
description: Shared layout for other pages
---
## Usage
Add a navbar and search dialog across other pages.
```tsx title="/app/(home)/layout.tsx"
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/app/layout.config';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return <HomeLayout {...baseOptions}>{children}</HomeLayout>;
}
```
Create a [Route Group](https://nextjs.org/docs/app/building-your-application/routing/route-groups) to share the same layout across multiple pages.
<Files>
<Folder name="(home)" defaultOpen>
<File name="page.tsx" />
<File name="layout.tsx" />
</Folder>
<Folder name="/docs">
<Folder name={'[[..slugs]]'}>
<File name="page.tsx" />
</Folder>
<File name="layout.tsx" />
</Folder>
</Files>

View File

@ -1,33 +0,0 @@
---
title: 主页布局
description: 其他页面的共享布局
---
## 使用方法
在其他页面上添加导航栏和搜索对话框。
```tsx title="/app/(home)/layout.tsx"
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/app/layout.config';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return <HomeLayout {...baseOptions}>{children}</HomeLayout>;
}
```
创建一个[路由组](https://nextjs.org/docs/app/building-your-application/routing/route-groups)来在多个页面之间共享相同的布局。
<Files>
<Folder name="(home)" defaultOpen>
<File name="page.tsx" />
<File name="layout.tsx" />
</Folder>
<Folder name="/docs">
<Folder name={'[[..slugs]]'}>
<File name="page.tsx" />
</Folder>
<File name="layout.tsx" />
</Folder>
</Files>

View File

@ -1,32 +0,0 @@
---
title: Notebook
description: A more compact version of Docs Layout
---
## Usage
Enable the notebook layout with `fumadocs-ui/layouts/notebook`, it's a more compact layout than the default one.
![Notebook](/images/docs/notebook.png)
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/notebook';
import { baseOptions } from '@/app/layout.config';
import { source } from '@/lib/source';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
{...baseOptions}
// the position of navbar
nav={{ ...baseOptions.nav, mode: 'top' }}
// the position of Sidebar Tabs
tabMode="navbar"
tree={source.pageTree}
>
{children}
</DocsLayout>
);
}
```

View File

@ -1,32 +0,0 @@
---
title: 笔记本
description: 文档布局的更紧凑版本
---
## 使用方法
使用 `fumadocs-ui/layouts/notebook` 启用笔记本布局,它比默认布局更加紧凑。
![Notebook](/images/docs/notebook.png)
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/notebook';
import { baseOptions } from '@/app/layout.config';
import { source } from '@/lib/source';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
{...baseOptions}
// the position of navbar
nav={{ ...baseOptions.nav, mode: 'top' }}
// the position of Sidebar Tabs
tabMode="navbar"
tree={source.pageTree}
>
{children}
</DocsLayout>
);
}
```

View File

@ -1,217 +0,0 @@
---
title: Docs Page
description: A page in your documentation
---
Page is the base element of a documentation, it includes Table of contents,
Footer, and Breadcrumb.
## Usage
```tsx title="page.tsx"
import {
DocsPage,
DocsDescription,
DocsTitle,
DocsBody,
} from 'fumadocs-ui/page';
<DocsPage>
<DocsTitle>title</DocsTitle>
<DocsDescription>description</DocsDescription>
<DocsBody>...</DocsBody>
</DocsPage>;
```
<Callout type='info' title='Good to know'>
Instead of rendering the title with `DocsTitle` in `page.tsx`, you can put the title into MDX file.
This will render the title in the MDX body.
</Callout>
### Body
It applies the [Typography](/docs/theme#typography) styles, wrap your content inside.
```tsx
import { DocsBody } from 'fumadocs-ui/page';
<DocsBody>
<h1>This heading looks good!</h1>
</DocsBody>;
```
### Category
Optional, link the other pages in its (page tree) folder with cards.
> You can use this component without `<DocsPage />`.
```tsx title="page.tsx"
import { source } from '@/lib/source';
import { DocsCategory } from 'fumadocs-ui/page';
const page = source.getPage(['...']);
<DocsCategory page={page} from={source} />;
```
**Demo:**
{/* DocsCategory is not supported */}
{/* <DocsCategory /> */}
## Configurations
### Full Mode
To extend the page to fill up all available space, pass `full` to the page component.
This will force TOC to be shown as a popover.
```tsx
import { DocsPage } from 'fumadocs-ui/page';
<DocsPage full>...</DocsPage>;
```
### Table of Contents
An overview of all the headings in your article, it requires an array of headings.
For Markdown and MDX documents, You can obtain it using the
[TOC Utility](/docs/headless/utils/get-toc). Content sources like Fumadocs MDX offer this out-of-the-box.
```tsx
import { DocsPage } from 'fumadocs-ui/page';
<DocsPage toc={headings}>...</DocsPage>;
```
Customise or disable TOC from your documentation with the `tableOfContent` option.
```tsx
import { DocsPage } from 'fumadocs-ui/page';
<DocsPage tableOfContent={options}>...</DocsPage>;
```
{/* <AutoTypeTable path="./content/docs/props.ts" name="TOCProps" /> */}
#### Style
You can choose another style for TOC, like `clerk` inspired by https://clerk.com:
```tsx
import { DocsPage } from 'fumadocs-ui/page';
<DocsPage
tableOfContent={{
style: 'clerk',
}}
>
...
</DocsPage>;
```
#### Popover Mode
On smaller devices, it is shown on a popover instead.
Customise it with the `tableOfContentPopover` option.
```tsx
import { DocsPage } from 'fumadocs-ui/page';
<DocsPage tableOfContentPopover={options}>...</DocsPage>;
```
{/* <AutoTypeTable path="./content/docs/props.ts" name="TOCPopoverProps" /> */}
### Last Updated Time
Display last updated time of the page.
```tsx
import { DocsPage } from 'fumadocs-ui/page';
<DocsPage lastUpdate={new Date(lastModifiedTime)} />;
```
Since you might have different version controls (e.g. Github) or it's from
remote sources like Sanity, Fumadocs UI doesn't display the last updated time by
default.
For Github hosted documents, you can use
the [`getGithubLastEdit`](/docs/headless/utils/git-last-edit) utility.
```tsx
import { DocsPage } from 'fumadocs-ui/page';
import { getGithubLastEdit } from 'fumadocs-core/server';
const time = await getGithubLastEdit({
owner: 'fuma-nama',
repo: 'fumadocs',
path: `content/docs/${page.file.path}`,
});
<DocsPage lastUpdate={new Date(time)} />;
```
<Callout type='info' title='Note'>
You can also specify the last updated time of documents (e.g. using frontmatter).
Don't forget to [update the schema type](/docs/mdx/collections#schema) on Fumadocs MDX first.
</Callout>
### Edit on GitHub
Add "Edit on GitHub" button to the page.
```tsx
import { DocsPage } from 'fumadocs-ui/page';
<DocsPage
editOnGithub={{
owner: 'fuma-nama',
repo: 'fumadocs',
sha: 'main',
// file path, make sure it's valid
path: `content/docs/${page.file.path}`,
}}
/>;
```
### Footer
Footer is a navigation element that has two buttons to jump to the next and previous pages. When not specified, it shows the neighbour pages found from page tree.
Customise the footer with the `footer` option.
```tsx
import { DocsPage, DocsBody } from 'fumadocs-ui/page';
<DocsPage footer={options}>
<DocsBody>...</DocsBody>
</DocsPage>;
```
{/* <AutoTypeTable path="./content/docs/props.ts" name="FooterProps" /> */}
### Breadcrumb
A navigation element, shown only when user is navigating in folders.
{/* <AutoTypeTable path="./content/docs/props.ts" name="BreadcrumbProps" /> */}
### MDX Page
In conjunction of Fumadocs MDX, you may create a `page.mdx` file and add the following.
```mdx
export { withArticle as default } from 'fumadocs-ui/page';
## Hello World
```
This creates a page with MDX, with proper typography styles applied.

View File

@ -1,238 +0,0 @@
---
title: 文档页面
description: 文档中的页面
---
可以渲染完整页面的组件(标题、目录等)。
## 正文
```tsx title="page.tsx"
import { DocsPage } from 'fumadocs-ui/page';
export default function Page({ params }: { params: { slug?: string[] } }) {
const page = getPage(params);
return (
<DocsPage
title={page.title}
description={page.description}
mdx={page.body}
toc={page.toc}
/>
);
}
```
{/* <AutoTypeTable
path="./content/docs/props.ts"
type="Omit<DocsPageProps, 'children'>"
/> */}
### SEO
为页面添加 SEO 优化,有几种方法。首先,允许文档生成器提供 `metadata` 帮助程序:
```tsx title="api.ts"
export { createMetadata } from 'fumadocs-core/docs';
```
默认值包括 **标题**、**描述**、**开放图形**Open Graph和 **Twitter** 图片、**规范**CanonicalURL 和 locale 元数据。
现在您可以直接使用它:
```tsx title="page.tsx"
import type { Metadata } from 'next';
import { createMetadata } from '@/app/api';
export async function generateMetadata({
params,
}: {
params: { slug?: string[] };
}): Promise<Metadata> {
const page = await getPage(params);
return createMetadata({
page,
params,
});
}
```
或者您可以手动构建它:
```tsx title="page.tsx"
import type { Metadata } from 'next';
import { absoluteUrl } from 'fumadocs-core/utils/absolute-url';
export const metadata: Metadata = {
title: 'My Page',
description: 'Page Description',
openGraph: {
title: 'My Page',
description: 'Page Description',
type: 'article',
url: absoluteUrl('/docs/my-page'),
},
twitter: {
title: 'My Page',
description: 'Page Description',
card: 'summary_large_image',
},
alternates: {
canonical: absoluteUrl('/docs/my-page'),
},
};
```
## 内容目录
支持无限级别的标题。从页面内容中提取,您应该通过 `toc` 字段传递它。
```tsx title="page.tsx"
import { DocsPage } from 'fumadocs-ui/page';
import { getToc } from 'fumadocs-core';
export default function Page() {
const toc = getToc(content);
return <DocsPage toc={toc} />;
}
```
{/* <AutoTypeTable path="./content/docs/props.ts" name="TOCItemProps[]" /> */}
### 自定义内容目录
可以定制 TOC目录的呈现方式但您仍然需要通过 `toc` 字段传递真实的 TOC 项目。
```tsx title="page.tsx"
import { DocsPage } from 'fumadocs-ui/page';
export default function Page() {
return (
<DocsPage tocClassName="hidden lg:block" toc={toc}>
<div>Custom TOC</div>
</DocsPage>
);
}
```
## 最后更新时间
```tsx title="page.tsx"
import { DocsPage } from 'fumadocs-ui/page';
export default function Page() {
return <DocsPage lastUpdatedAt={new Date()} />;
}
```
## 页脚
```tsx title="layout.tsx"
import { DocsPage } from 'fumadocs-ui/page';
import { baseOptions } from '@/app/layout.config';
export default function Page() {
return (
<DocsPage
footer={{
text: 'Built with Fumadocs',
}}
/>
);
}
```
### 使用基础配置
您可以创建一个 `baseOptions` 对象,用于所有页面和布局组件。
```tsx title="layout.config.ts"
import type { BasePageConfig } from 'fumadocs-ui/page';
export const baseOptions: BasePageConfig = {
githubUrl: 'https://github.com/fuma-nama/fumadocs',
footer: {
text: 'Built with Fumadocs',
},
};
```
```tsx title="page.tsx"
import { DocsPage } from 'fumadocs-ui/page';
import { baseOptions } from '@/app/layout.config';
export default function Page() {
return <DocsPage {...baseOptions} />;
}
```
### 编辑链接
```tsx
import { DocsPage } from 'fumadocs-ui/page';
export default function Page() {
return (
<DocsPage
gitTimestamp={true}
footer={{
// Edit Link
editLink: {
text: 'Edit this page',
url: 'https://github.com/username/repo/blob/main',
},
}}
/>
);
}
```
### 页面导航
```tsx
import { DocsPage } from 'fumadocs-ui/page';
import { getPagesPath } from 'fumadocs-core';
export default function Page({ params }: { params: { slug?: string[] } }) {
const pagePath = getPagesPath(params);
const prev = getAdjacentPages({ current: pagePath, dir: 'prev' });
const next = getAdjacentPages({ current: pagePath, dir: 'next' });
return (
<DocsPage
footer={{
navigation: {
prev: prev?.url
? {
title: prev.title,
href: prev.url,
}
: undefined,
next: next?.url
? {
title: next.title,
href: next.url,
}
: undefined,
},
}}
/>
);
}
```
#### 自定义获取相邻页面
您可以在 `createAdjacentPages` 方法中应用 `includeInPageNav` 过滤器,该方法由文档生成器创建:
```tsx title="api.ts"
import { createAdjacentPages } from 'fumadocs-core/docs';
import { tree } from '@/app/source';
export const getAdjacentPages = createAdjacentPages(tree, {
includeInPageNav: (page) => !page.data.preview,
});
```

View File

@ -1,54 +0,0 @@
---
title: Root Provider
description: The context provider of Fumadocs UI.
---
The context provider of all the components, including `next-themes` and context
for search dialog. It should be located at the root layout.
## Usage
```jsx
import { RootProvider } from 'fumadocs-ui/provider';
export default function Layout({ children }) {
return (
<html lang="en">
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
```
### Search Dialog
Customize or disable the search dialog with `search` option.
```jsx
<RootProvider
search={{
enabled: false,
}}
>
{children}
</RootProvider>
```
Learn more from [Search](/docs/search).
### Theme Provider
Fumadocs supports light/dark modes with [`next-themes`](https://github.com/pacocoursey/next-themes).
Customise or disable it with `theme` option.
```jsx
<RootProvider
theme={{
enabled: false,
}}
>
{children}
</RootProvider>
```

View File

@ -1,53 +0,0 @@
---
title: 根提供者
description: Fumadocs UI 的上下文提供者
---
所有组件的上下文提供者,包括 `next-themes` 和搜索对话框的上下文。它应该位于根布局中。
## 使用方法
```jsx
import { RootProvider } from 'fumadocs-ui/provider';
export default function Layout({ children }) {
return (
<html lang="en">
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
```
### 搜索对话框
使用 `search` 选项自定义或禁用搜索对话框。
```jsx
<RootProvider
search={{
enabled: false,
}}
>
{children}
</RootProvider>
```
从[搜索](/docs/search)了解更多信息。
### 主题提供者
Fumadocs 通过 [`next-themes`](https://github.com/pacocoursey/next-themes) 支持明/暗模式。
使用 `theme` 选项自定义或禁用它。
```jsx
<RootProvider
theme={{
enabled: false,
}}
>
{children}
</RootProvider>
```

View File

@ -1,193 +0,0 @@
---
title: Manual Installation
description: Create a new fumadocs project from scratch.
---
> Read the [Quick Start](/docs) guide first for basic concept.
## Getting Started
Create a new Next.js application with `create-next-app`, and install required packages.
```package-install
fumadocs-ui fumadocs-core
```
### Content Source
Fumadocs supports different content sources, you can choose one you prefer.
There is a list of officially supported sources:
- [Setup Fumadocs MDX](/docs/mdx)
- [Setup Content Collections](/docs/headless/content-collections)
Make sure to configure the library correctly following their setup guide before continuing, we will import the source adapter using `@/lib/source.ts` in this guide.
### Root Layout
Wrap the entire application inside [Root Provider](/docs/layouts/root-provider), and add required styles to `body`.
```tsx
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body
// you can use Tailwind CSS too
style={{
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
}}
>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
```
### Styles
Setup Tailwind CSS v4 on your Next.js app, add the following to `global.css`.
```css title="Tailwind CSS"
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
/* path of `fumadocs-ui` relative to the CSS file */
@source '../node_modules/fumadocs-ui/dist/**/*.js';
```
> It doesn't come with a default font, you may choose one from `next/font`.
### Layout
Create a `app/layout.config.tsx` file to put the shared options for our layouts.
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/layout.config.tsx",
"codeblock": {
"meta": "title=\"app/layout.config.tsx\""
}
}
```
Create a folder `/app/docs` for our docs, and give it a proper layout.
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/docs/layout.tsx",
"codeblock": {
"meta": "title=\"app/docs/layout.tsx\""
}
}
```
> `pageTree` refers to Page Tree, it should be provided by your content source.
### Page
Create a catch-all route `/app/docs/[[...slug]]` for docs pages.
In the page, wrap your content in the [Page](/docs/layouts/page) component.
It may vary depending on your content source. You should configure static rendering with `generateStaticParams` and metadata with `generateMetadata`.
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
<Tab value='Fumadocs MDX'>
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/docs/[[...slug]]/page.tsx",
"codeblock": {
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Fumadocs MDX\""
}
}
```
</Tab>
<Tab value='Content Collections'>
```json doc-gen:file
{
"file": "../../examples/content-collections/app/docs/[[...slug]]/page.tsx",
"codeblock": {
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Content Collections\""
}
}
```
</Tab>
</Tabs>
### Search
Use the default document search based on Orama.
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
<Tab value='Fumadocs MDX'>
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/api/search/route.ts",
"codeblock": {
"meta": "title=\"app/api/search/route.ts\" tab=\"Fumadocs MDX\""
}
}
```
</Tab>
<Tab value='Content Collections'>
```json doc-gen:file
{
"file": "../../examples/content-collections/app/api/search/route.ts",
"codeblock": {
"meta": "title=\"app/api/search/route.ts\" tab=\"Content Collections\""
}
}
```
</Tab>
</Tabs>
Learn more about [Document Search](/docs/headless/search).
### Done
You can start the dev server and create MDX files.
```mdx title="content/docs/index.mdx"
---
title: Hello World
---
## Introduction
I love Anime.
```
## Customise
You can use [Home Layout](/docs/layouts/home-layout) for other pages of the site, it includes a navbar with theme toggle.
## Deploying
It should work out-of-the-box with Vercel & Netlify.
### Docker Deployment
If you want to deploy your Fumadocs app using Docker with **Fumadocs MDX configured**, make sure to add the `source.config.ts` file to the `WORKDIR` in the Dockerfile.
The following snippet is taken from the official [Next.js Dockerfile Example](https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile):
```zsh title="Dockerfile"
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* source.config.ts ./
```
This ensures Fumadocs MDX can access your configuration file during builds.

View File

@ -1,191 +0,0 @@
---
title: 手动安装
description: 从零开始创建一个新的 Fumadocs 项目
---
> 请先阅读[快速入门](/docs)指南了解基本概念。
## 入门
使用 `create-next-app` 创建一个新的 Next.js 应用程序,并安装所需的包。
```package-install
fumadocs-ui fumadocs-core
```
### 内容源
Fumadocs 支持不同的内容源,您可以选择您喜欢的一种。
以下是官方支持的源列表:
- [设置 Fumadocs MDX](/docs/mdx)
- [设置 Content Collections](/docs/headless/content-collections)
请确保在继续之前按照其设置指南正确配置库,我们将在本指南中使用 `@/lib/source.ts` 导入源适配器。
### 根布局
将整个应用程序包装在 [Root Provider](/docs/layouts/root-provider) 中,并为 `body` 添加所需的样式。
```tsx
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body
// you can use Tailwind CSS too
style={{
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
}}
>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
```
### 样式
在您的 Next.js 应用程序上设置 Tailwind CSS v4将以下内容添加到 `global.css`。
```css title="Tailwind CSS"
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
/* path of `fumadocs-ui` relative to the CSS file */
@source '../node_modules/fumadocs-ui/dist/**/*.js';
```
> 它不附带默认字体,您可以从 `next/font` 中选择一个。
### 布局
创建一个 `app/layout.config.tsx` 文件,放置我们布局的共享选项。
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/layout.config.tsx",
"codeblock": {
"meta": "title=\"app/layout.config.tsx\""
}
}
```
为我们的文档创建一个文件夹 `/app/docs`,并给它一个适当的布局。
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/docs/layout.tsx",
"codeblock": {
"meta": "title=\"app/docs/layout.tsx\""
}
}
```
> `pageTree` 指的是页面树,应该由您的内容源提供。
### 页面
为文档页面创建一个捕获所有路由 `/app/docs/[[...slug]]`。
在页面中,将您的内容包装在 [Page](/docs/layouts/page) 组件中。
这可能因您的内容源而异。您应该使用 `generateStaticParams` 配置静态渲染,并使用 `generateMetadata` 配置元数据。
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
<Tab value='Fumadocs MDX'>
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/docs/[[...slug]]/page.tsx",
"codeblock": {
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Fumadocs MDX\""
}
}
```
</Tab>
<Tab value='Content Collections'>
```json doc-gen:file
{
"file": "../../examples/content-collections/app/docs/[[...slug]]/page.tsx",
"codeblock": {
"meta": "title=\"app/docs/[[...slug]]/page.tsx\" tab=\"Content Collections\""
}
}
```
</Tab>
</Tabs>
### 搜索
使用基于 Orama 的默认文档搜索。
<Tabs items={['Fumadocs MDX', 'Content Collections']}>
<Tab value='Fumadocs MDX'>
```json doc-gen:file
{
"file": "../../examples/next-mdx/app/api/search/route.ts",
"codeblock": {
"meta": "title=\"app/api/search/route.ts\" tab=\"Fumadocs MDX\""
}
}
```
</Tab>
<Tab value='Content Collections'>
```json doc-gen:file
{
"file": "../../examples/content-collections/app/api/search/route.ts",
"codeblock": {
"meta": "title=\"app/api/search/route.ts\" tab=\"Content Collections\""
}
}
```
</Tab>
</Tabs>
了解更多关于[文档搜索](/docs/headless/search)的信息。
### 完成
您可以启动开发服务器并创建 MDX 文件。
```mdx title="content/docs/index.mdx"
---
title: Hello World
---
## Introduction
I love Anime.
```
## 自定义
您可以为网站的其他页面使用 [Home Layout](/docs/layouts/home-layout),它包含一个带有主题切换的导航栏。
## 部署
它应该在 Vercel 和 Netlify 上开箱即用。
### Docker 部署
如果您想使用 Docker 部署您的 Fumadocs 应用程序,并且已**配置了 Fumadocs MDX**,请确保将 `source.config.ts` 文件添加到 Dockerfile 中的 `WORKDIR`。
以下片段取自官方 [Next.js Dockerfile 示例](https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile)
```zsh title="Dockerfile"
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* source.config.ts ./
```
这确保 Fumadocs MDX 在构建期间可以访问您的配置文件。

View File

@ -1,380 +0,0 @@
---
title: Markdown
description: How to write documents
---
## Introduction
Fumadocs provides many useful extensions to MDX, a markup language. Here is a brief introduction to the default MDX syntax of Fumadocs UI.
> MDX is not the only supported format of Fumadocs. In fact, you can use any renderers such as `next-mdx-remote` or CMS.
## Markdown
We use GFM (GitHub Flavored Markdown), a superset of Markdown (CommonMark).
See [GFM Specification](https://github.github.com/gfm).
````md
# Heading
## Heading
### Heading
#### Heading
Hello World, **Bold**, _Italic_, ~~Hidden~~
```js
console.log('Hello World');
```
1. First
2. Second
3. Third
- Item 1
- Item 2
> Quote here
![alt](/image.png)
| Table | Description |
| ----- | ----------- |
| Hello | World |
````
### Auto Links
Internal links use the `next/link` component to allow prefetching and avoid hard-reload.
External links will get the default `rel="noreferrer noopener" target="_blank"` attributes for security.
```mdx
[My Link](https://github.github.com/gfm)
This also works: https://github.github.com/gfm.
```
## MDX
MDX is a superset of Markdown, with support of JSX syntax.
It allows you to import components, and use them right in the document, or even export values.
```mdx
import { Component } from './component';
<Component name="Hello" />
```
see [MDX Syntax](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax) to learn more.
### Cards
Useful for adding links, it is included by default.
```mdx
<Cards>
<Card
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
title="Fetching, Caching, and Revalidating"
>
Learn more about caching in Next.js
</Card>
</Cards>
```
<Cards>
<Card
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
title="Fetching, Caching, and Revalidating"
>
Learn more about caching in Next.js
</Card>
</Cards>
#### Icon
You can specify an icon to cards.
```mdx
import { HomeIcon } from 'lucide-react';
<Cards>
<Card icon={<HomeIcon />} href="/" title="Home">
Go back to home
</Card>
</Cards>
```
<Cards>
<Card icon={<HomeIcon />} href="/" title="Go back to home">
The home page of Fumadocs.
</Card>
</Cards>
#### Without href
```mdx
<Cards>
<Card title="Fetching, Caching, and Revalidating">
Learn more about `fetch` in Next.js.
</Card>
</Cards>
```
<Cards>
<Card title="Fetching, Caching, and Revalidating">
Learn more about `fetch` in Next.js.
</Card>
</Cards>
### Callouts
Useful for adding tips/warnings, it is included by default.
```mdx
<Callout>Hello World</Callout>
```
<Callout>Hello World</Callout>
#### Title
Specify a callout title.
```mdx
<Callout title="Title">Hello World</Callout>
```
<Callout title="Title">Hello World</Callout>
#### Types
You can specify the type of callout.
- `info` (default)
- `warn`
- `error`
```mdx
<Callout title="Title" type="error">
Hello World
</Callout>
```
<Callout title="Title" type="error">
Hello World
</Callout>
### Customise Components
See [all MDX components and available options](/docs/mdx).
## Headings
An anchor is automatically applied to each heading, it sanitizes invalid characters like spaces. (e.g. `Hello World` to `hello-world`)
```md
# Hello `World`
```
### TOC Settings
The table of contents (TOC) will be generated based on headings, you can also customise the effects of headings:
```md
# Heading [!toc]
This heading will be hidden from TOC.
# Another Heading [toc]
This heading will **only** be visible in TOC, you can use it to add additional TOC items.
Like headings rendered in a React component:
<MyComp />
```
### Custom Anchor
You can add `[#slug]` to customise heading anchors.
```md
# heading [#my-heading-id]
```
You can also chain it with TOC settings like:
```md
# heading [toc] [#my-heading-id]
```
To link people to a specific heading, add the heading id to hash fragment: `/page#my-heading-id`.
## Frontmatter
We support YAML frontmatter. It is a way to specify common information of the document (e.g. title).
Place it at the top of document.
```mdx
---
title: Hello World
---
## Title
```
See [Page Conventions](/docs/page-conventions#frontmatter) for a list of properties available for frontmatter.
## Codeblock
Syntax Highlighting is supported by default using [Rehype Code](/docs/headless/mdx/rehype-code).
````mdx
```js
console.log('Hello World');
```
````
You can add a title to the codeblock.
````mdx
```js title="My Title"
console.log('Hello World');
```
````
### Highlight Lines
You can highlight specific lines by adding `[!code highlight]`.
````md
```tsx
<div>Hello World</div> // [\!code highlight]
<div>Hello World</div>
<div>Goodbye</div>
<div>Hello World</div>
```
````
### Highlight Words
You can highlight a specific word by adding `[!code word:<match>]`.
````md
```js
// [\!code word:config]
const config = {
reactStrictMode: true,
};
```
````
### Diffs
````mdx
```ts
console.log('hewwo'); // [\!code --]
console.log('hello'); // [\!code ++]
```
````
```ts
console.log('hewwo'); // [!code --]
console.log('hello'); // [!code ++]
```
### Tab Groups
You can use code blocks with the `<Tab />` component.
````mdx
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
<Tabs items={['Tab 1', 'Tab 2']}>
<Tab value='Tab 1'>
```ts
console.log('A');
```
</Tab>
<Tab value='Tab 2'>
```ts
console.log('B');
```
</Tab>
</Tabs>
````
> Note that you can add MDX components instead of importing them in MDX files.
<Tabs items={['Tab 1', 'Tab 2']}>
<Tab value='Tab 1'>
```ts
console.log('A');
```
</Tab>
<Tab value='Tab 2'>
```ts
console.log('B');
```
</Tab>
</Tabs>
### Using Typescript Twoslash
Write Typescript codeblocks with hover type information and detected types errors.
Not enabled by default. See [Twoslash](/docs/twoslash).
## Images
All built-in content sources handle images properly.
Images are automatically optimized for `next/image`.
```mdx
![Image](/image.png)
```
![Image](/images/docs/notebook.png)
## Optional
Some optional plugins you can enable.
### Math Equations
Write math equations with TeX.
````md
```math
f(x) = x * e^{2 pi i \xi x}
```
````
```math
f(x) = x * e^{2 pi i \xi x}
```
To enable, see [Math Integration](/docs/math).
### Package Install
Generate code blocks for installing packages via package managers (JS/Node.js).
````md
```package-install
npm i next -D
```
````
```package-install
npm i next -D
```
To enable, see [Remark Install](/docs/headless/mdx/install).
### More
You can see [a list of plugins](/docs/headless/mdx) supported by Fumadocs.

View File

@ -1,342 +0,0 @@
---
title: Markdown
description: 如何撰写文档
---
## 介绍
Fumadocs 为 MDX一种标记语言提供了许多有用的扩展。以下是 Fumadocs UI 默认 MDX 语法的简要介绍。
> MDX 不是 Fumadocs 唯一支持的格式。实际上,您可以使用任何渲染器,如 `next-mdx-remote` 或 CMS。
## Markdown
我们使用 GFMGitHub 风格的 Markdown这是 MarkdownCommonMark的超集。
参见 [GFM 规范](https://github.github.com/gfm)。
````md
# Heading
## Heading
### Heading
#### Heading
Hello World, **Bold**, _Italic_, ~~Hidden~~
```js
console.log('Hello World');
```
1. First
2. Second
3. Third
- Item 1
- Item 2
> Quote here
![alt](/image.png)
| Table | Description |
| ----- | ----------- |
| Hello | World |
````
### 自动链接
内部链接使用 `next/link` 组件,允许预取并避免硬重载。
外部链接将获得默认的 `rel="noreferrer noopener" target="_blank"` 属性以增强安全性。
```mdx
[My Link](https://github.github.com/gfm)
This also works: https://github.github.com/gfm.
```
## MDX
MDX 是 Markdown 的超集,支持 JSX 语法。
它允许您导入组件,并直接在文档中使用它们,甚至导出值。
```mdx
import { Component } from './component';
<Component name="Hello" />
```
参见 [MDX 语法](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax) 了解更多信息。
### 卡片
对于添加链接很有用,默认包含。
```mdx
<Cards>
<Card
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
title="Fetching, Caching, and Revalidating"
>
Learn more about caching in Next.js
</Card>
</Cards>
```
<Cards>
<Card
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
title="Fetching, Caching, and Revalidating"
>
Learn more about caching in Next.js
</Card>
</Cards>
#### 图标
您可以为卡片指定图标。
```mdx
import { HomeIcon } from 'lucide-react';
<Cards>
<Card icon={<HomeIcon />} href="/" title="Home">
Go back to home
</Card>
</Cards>
```
<Cards>
<Card icon={<HomeIcon />} href="/" title="Go back to home">
The home page of Fumadocs.
</Card>
</Cards>
#### 无 href
```mdx
<Cards>
<Card title="Fetching, Caching, and Revalidating">
Learn more about `fetch` in Next.js.
</Card>
</Cards>
```
<Cards>
<Card title="Fetching, Caching, and Revalidating">
Learn more about `fetch` in Next.js.
</Card>
</Cards>
### 提示框
对于添加提示/警告很有用,默认包含。
```mdx
<Callout>Hello World</Callout>
```
<Callout>Hello World</Callout>
#### 标题
指定提示框标题。
```mdx
<Callout title="Title">Hello World</Callout>
```
<Callout title="Title">Hello World</Callout>
#### 类型
您可以指定提示框的类型。
- `info`(默认)
- `warn`
- `error`
```mdx
<Callout title="Title" type="error">
Hello World
</Callout>
```
<Callout title="Title" type="error">
Hello World
</Callout>
### 自定义组件
参见[所有 MDX 组件和可用选项](/docs/mdx)。
## 标题
每个标题会自动应用锚点,它会清理空格等无效字符。(例如,`Hello World` 变为 `hello-world`
```md
# Hello `World`
```
### 目录设置
目录 (TOC) 将基于标题生成,您还可以自定义标题的效果:
```md
# Heading [!toc]
This heading will be hidden from TOC.
# Another Heading [toc]
This heading will **only** be visible in TOC, you can use it to add additional TOC items.
Like headings rendered in a React component:
<MyComp />
```
### 自定义锚点
您可以添加 `[#slug]` 来自定义标题锚点。
```md
# heading [#my-heading-id]
```
您也可以将其与目录设置链接起来,例如:
```md
# heading [toc] [#my-heading-id]
```
要将人们链接到特定标题,请将标题 ID 添加到哈希片段:`/page#my-heading-id`。
## 前言
我们支持 YAML 前言。这是一种指定文档常见信息(例如标题)的方式。
将其放在文档顶部。
```mdx
---
title: Hello World
---
## Title
```
有关前言可用属性的列表,请参见[页面约定](/docs/page-conventions#frontmatter)。
## 代码块
默认使用 [Rehype Code](/docs/headless/mdx/rehype-code) 支持语法高亮。
````mdx
```js
console.log('Hello World');
```
````
您可以为代码块添加标题。
````mdx
```js title="My Title"
console.log('Hello World');
```
````
### 高亮行
````md
```tsx
<div>Hello World</div> // [\!code highlight]
<div>Hello World</div>
<div>Goodbye</div>
<div>Hello World</div>
```
````
### 高亮单词
您可以通过添加 `[!code word:<match>]` 来高亮特定单词。
````md
```js
// [\!code word:config]
const config = {
reactStrictMode: true,
};
```
````
### 差异
````mdx
```ts
console.log('hewwo'); // [\!code --]
console.log('hello'); // [\!code ++]
```
````
```ts
console.log('hewwo'); // [!code --]
console.log('hello'); // [!code ++]
```
### 标签组
您可以使用 `<Tab />` 组件与代码块一起使用。
````mdx
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
<Tabs items={['Tab 1', 'Tab 2']}>
<Tab value='Tab 1'>
```ts
console.log('A');
```
</Tab>
<Tab value='Tab 2'>
```ts
console.log('B');
```
</Tab>
</Tabs>
````
> 注意,您可以在 MDX 文件中添加 MDX 组件,而不必导入它们。
<Tabs items={['Tab 1', 'Tab 2']}>
<Tab value='Tab 1'>
```ts
console.log('A');
```
</Tab>
<Tab value='Tab 2'>
```ts
console.log('B');
```
</Tab>
</Tabs>
### 使用 Typescript Twoslash
编写带有悬停类型信息和检测到类型错误的 Typescript 代码块。
默认情况下未启用。参见 [Twoslash](/docs/twoslash)。
## 图片
所有内置内容源都能正确处理图片。
图片会自动为 `next/image` 优化。
```mdx
![Image](/image.png)
```
![Image](/images/docs/notebook.png)
## 可选功能
一些您可以启用的可选插件。

View File

@ -1,25 +0,0 @@
---
title: Callout
description: Add callout to your docs
preview: callout
---
## Usage
Add it to your MDX components.
```tsx
import { Callout } from 'fumadocs-ui/components/callout';
<MDX
components={{
Callout,
}}
/>;
```
See [Markdown](/docs/markdown#callouts) for usages.
### Reference
{/* <AutoTypeTable path="./content/docs/props.ts" name="CalloutProps" /> */}

View File

@ -1,25 +0,0 @@
---
title: 提示框
description: 在文档中添加提示框
preview: callout
---
## 使用方法
将其添加到您的 MDX 组件中。
```tsx
import { Callout } from 'fumadocs-ui/components/callout';
<MDX
components={{
Callout,
}}
/>;
```
有关用法,请参见 [Markdown](/docs/markdown#callouts)。
### 参考
{/* <AutoTypeTable path="./content/docs/props.ts" name="CalloutProps" /> */}

View File

@ -1,56 +0,0 @@
---
title: Card
description: Use the Card component in your MDX documentation
preview: card
---
## Usage
Add it to your MDX components.
```tsx
import { Card, Cards } from 'fumadocs-ui/components/card';
<MDX
components={{
Card,
Cards,
}}
/>;
```
See [Markdown](/docs/markdown#cards) for usages.
### Cards
The container of cards.
### Card
Based on Next.js `<Link />`.
{/* <AutoTypeTable path="./content/docs/props.ts" name="CardProps" /> */}
<Callout title="Tree Shaking on icons" type="warn">
If you're not using Fumadocs MDX for rendering MDX (e.g. using Contentlayer), ensure that
tree shaking is working properly.
Most of the icon libraries support importing icons individually.
```tsx
import HomeIcon from 'lucide-react/dist/esm/icons/home';
```
As a workaround, you can pass icons to MDX Components too. (this uses Next.js bundler instead of content source)
```tsx title="page.tsx"
import { HomeIcon } from 'lucide-react';
const components = {
...defaultComponents,
HomeIcon,
};
```
</Callout>

View File

@ -1,56 +0,0 @@
---
title: 卡片
description: 在 MDX 文档中使用卡片组件
preview: card
---
## 使用方法
将其添加到您的 MDX 组件中。
```tsx
import { Card, Cards } from 'fumadocs-ui/components/card';
<MDX
components={{
Card,
Cards,
}}
/>;
```
有关用法,请参见 [Markdown](/docs/markdown#cards)。
### Cards
卡片的容器。
### Card
基于 Next.js 的 `<Link />`。
{/* <AutoTypeTable path="./content/docs/props.ts" name="CardProps" /> */}
<Callout title="图标的树摇优化" type="warn">
如果您没有使用 Fumadocs MDX 来渲染 MDX例如使用 Contentlayer请确保
树摇优化正常工作。
大多数图标库支持单独导入图标。
```tsx
import HomeIcon from 'lucide-react/dist/esm/icons/home';
```
作为解决方法,您也可以将图标传递给 MDX 组件。(这使用 Next.js 打包器而不是内容源)
```tsx title="page.tsx"
import { HomeIcon } from 'lucide-react';
const components = {
...defaultComponents,
HomeIcon,
};
```
</Callout>

View File

@ -1,79 +0,0 @@
---
title: Code Block
description: Adding code blocks to your docs
---
<Wrapper>
<div className="bg-fd-background rounded-lg prose-no-margin">
```js title="config.js"
import createMDX from 'fumadocs-mdx/config';
const withMDX = createMDX();
// [!code word:config]
/** @type {import('next').NextConfig} */
const config = {
// [!code highlight]
reactStrictMode: true, // [!code highlight]
}; // [!code highlight]
export default withMDX(config);
```
</div>
</Wrapper>
Display code blocks, added by default.
- Copy button
- Custom titles and icons
## Usage
Wrap the pre element in `<CodeBlock />`, which acts as the wrapper of code block.
```tsx
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
<MDX
components={{
// HTML `ref` attribute conflicts with `forwardRef`
pre: ({ ref: _ref, ...props }) => (
<CodeBlock {...props}>
<Pre>{props.children}</Pre> {/* [!code highlight] */}
</CodeBlock>
),
}}
/>;
```
See [Markdown](/docs/markdown#codeblock) for usages.
### Keep Background
Use the background color generated by Shiki (the Rehype Code plugin).
```tsx
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
<MDX
components={{
pre: ({ ref: _ref, ...props }) => (
<CodeBlock keepBackground {...props}>
<Pre>{props.children}</Pre>
</CodeBlock>
),
}}
/>;
```
### Icons
Specify a custom icon by passing an `icon` prop to `CodeBlock` component.
By default, the icon will be injected by the custom Shiki transformer.
```js title="config.js"
console.log('js');
```

View File

@ -1,79 +0,0 @@
---
title: 代码块
description: 在文档中添加代码块
---
<Wrapper>
<div className="bg-fd-background rounded-lg prose-no-margin">
```js title="config.js"
import createMDX from 'fumadocs-mdx/config';
const withMDX = createMDX();
// [!code word:config]
/** @type {import('next').NextConfig} */
const config = {
// [!code highlight]
reactStrictMode: true, // [!code highlight]
}; // [!code highlight]
export default withMDX(config);
```
</div>
</Wrapper>
显示代码块,默认添加。
- 复制按钮
- 自定义标题和图标
## 使用方法
将 pre 元素包装在 `<CodeBlock />` 中,它作为代码块的包装器。
```tsx
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
<MDX
components={{
// HTML `ref` attribute conflicts with `forwardRef`
pre: ({ ref: _ref, ...props }) => (
<CodeBlock {...props}>
<Pre>{props.children}</Pre> {/* [!code highlight] */}
</CodeBlock>
),
}}
/>;
```
有关用法,请参见 [Markdown](/docs/markdown#codeblock)。
### 保留背景
使用由 ShikiRehype Code 插件)生成的背景颜色。
```tsx
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
<MDX
components={{
pre: ({ ref: _ref, ...props }) => (
<CodeBlock keepBackground {...props}>
<Pre>{props.children}</Pre>
</CodeBlock>
),
}}
/>;
```
### 图标
通过向 `CodeBlock` 组件传递 `icon` 属性来指定自定义图标。
默认情况下,图标将由自定义 Shiki 转换器注入。
```js title="config.js"
console.log('js');
```

View File

@ -1,26 +0,0 @@
---
title: Heading
description: Heading components for your MDX documentation
preview: heading
---
The heading component which automatically adds the `id` prop.
## Usage
Add it to your MDX components, from `h1` to `h6`.
```mdx
import { Heading } from 'fumadocs-ui/components/heading';
<MDX
components={{
h1: (props) => <Heading as="h1" {...props} />,
h2: (props) => <Heading as="h2" {...props} />,
h3: (props) => <Heading as="h3" {...props} />,
h4: (props) => <Heading as="h4" {...props} />,
h5: (props) => <Heading as="h5" {...props} />,
h6: (props) => <Heading as="h6" {...props} />,
}}
/>
```

View File

@ -1,26 +0,0 @@
---
title: 标题
description: MDX 文档的标题组件
preview: heading
---
自动添加 `id` 属性的标题组件。
## 使用方法
将其添加到您的 MDX 组件中,从 `h1` 到 `h6`。
```mdx
import { Heading } from 'fumadocs-ui/components/heading';
<MDX
components={{
h1: (props) => <Heading as="h1" {...props} />,
h2: (props) => <Heading as="h2" {...props} />,
h3: (props) => <Heading as="h3" {...props} />,
h4: (props) => <Heading as="h4" {...props} />,
h5: (props) => <Heading as="h5" {...props} />,
h6: (props) => <Heading as="h6" {...props} />,
}}
/>
```

View File

@ -1,41 +0,0 @@
---
title: MDX
description: Default MDX Components
index: true
---
## Usage
The default MDX components include Cards, Callouts, Code Blocks and Headings.
```ts
import defaultMdxComponents from 'fumadocs-ui/mdx';
```
### Relative Link
To support links with relative file path in `href`, override the default `a` component with:
```tsx
import { createRelativeLink } from 'fumadocs-ui/mdx';
import { source } from '@/lib/source';
const page = source.getPage(['...']);
return (
<MdxContent
components={{
// override the `a` tag
a: createRelativeLink(source, page),
}}
/>
);
```
```mdx
[My Link](./file.mdx)
```
[Example: `../(integrations)/open-graph.mdx`](<../(integrations)/open-graph.mdx>)
<Callout type="warn">Server Component only.</Callout>

View File

@ -1,41 +0,0 @@
---
title: MDX
description: 默认 MDX 组件
index: true
---
## 使用方法
默认的 MDX 组件包括卡片、提示框、代码块和标题。
```ts
import defaultMdxComponents from 'fumadocs-ui/mdx';
```
### 相对链接
要支持 `href` 中带有相对文件路径的链接,请使用以下方式覆盖默认的 `a` 组件:
```tsx
import { createRelativeLink } from 'fumadocs-ui/mdx';
import { source } from '@/lib/source';
const page = source.getPage(['...']);
return (
<MdxContent
components={{
// override the `a` tag
a: createRelativeLink(source, page),
}}
/>
);
```
```mdx
[My Link](./file.mdx)
```
[示例: `../(integrations)/open-graph.mdx`](<../(integrations)/open-graph.mdx>)
<Callout type="warn">仅限服务器组件。</Callout>

View File

@ -1,25 +0,0 @@
{
"title": "Framework",
"description": "The docs framework",
"icon": "Building2",
"root": true,
"pages": [
"---Introduction---",
"index",
"what-is-fumadocs",
"comparisons",
"---Setup---",
"manual-installation",
"static-export",
"---Writing---",
"markdown",
"internationalization",
"---UI---",
"customisation",
"theme",
"search",
"components",
"mdx",
"layouts"
]
}

View File

@ -1,25 +0,0 @@
{
"title": "Framework",
"description": "The docs framework",
"icon": "Building2",
"root": true,
"pages": [
"---介绍---",
"index",
"what-is-fumadocs",
"comparisons",
"---设置---",
"manual-installation",
"static-export",
"---写作---",
"markdown",
"internationalization",
"---UI---",
"customisation",
"theme",
"search",
"components",
"mdx",
"layouts"
]
}

View File

@ -1,275 +0,0 @@
---
title: Search
description: Implement document search in your docs
---
Fumadocs UI provides a good-looking search UI for your docs, the search functionality is instead provided and documented on Fumadocs Core.
See [Document Search](/docs/headless/search).
## Search UI
Open with <kbd>⌘</kbd> <kbd>K</kbd> or <kbd>Ctrl</kbd> <kbd>K</kbd>.
### Configurations
You can customize search UI from the [Root Provider](/docs/layouts/root-provider) component in root layout.
When not specified, it uses the Default [`fetch` Search Client](/docs/headless/search/orama) powered by Orama.
### Custom Links
Add custom link items to search dialog.
They are shown as fallbacks when the query is empty.
```tsx title="app/layout.tsx"
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
links: [
['Home', '/'],
['Docs', '/docs'],
],
}}
>
{children}
</RootProvider>;
```
### Disable Search
To opt-out of document search, disable it from root provider.
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
enabled: false,
}}
>
{children}
</RootProvider>;
```
### Hot Keys
Customise the hot keys to trigger search dialog.
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
hotKey: [
{
display: 'K',
key: 'k', // key code, or a function determining whether the key is pressed
},
],
}}
>
{children}
</RootProvider>;
```
### Tag Filter
Add UI to change filters.
Make sure to configure [Tag Filter](/docs/headless/search/orama#tag-filter) on search server first.
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
options: {
defaultTag: 'value',
tags: [
{
name: 'Tag Name',
value: 'value',
},
],
},
}}
>
{children}
</RootProvider>;
```
### Search Options
Pass options to the search client, like changing the API endpoint for Orama search server:
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
options: {
api: '/api/search/docs',
},
}}
>
{children}
</RootProvider>;
```
### Replace Search Dialog
You can replace the default Search Dialog with:
```tsx title="components/search.tsx"
'use client';
import SearchDialog from 'fumadocs-ui/components/dialog/search-default';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
export default function CustomDialog(props: SharedProps) {
// your own logic here
return <SearchDialog {...props} />;
}
```
To pass it to the Root Provider, you need a wrapper with `use client` directive.
```tsx title="provider.tsx"
'use client';
import { RootProvider } from 'fumadocs-ui/provider';
import dynamic from 'next/dynamic';
import type { ReactNode } from 'react';
const SearchDialog = dynamic(() => import('@/components/search')); // lazy load
export function Provider({ children }: { children: ReactNode }) {
return (
<RootProvider
search={{
SearchDialog,
}}
>
{children}
</RootProvider>
);
}
```
Use it instead of your previous Root Provider
```tsx title="layout.tsx"
import { Provider } from './provider';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<Provider>{children}</Provider>
</body>
</html>
);
}
```
## Other Solutions
### Algolia
For the setup guide, see [Integrate Algolia Search](/docs/headless/search/algolia).
While generally we recommend building your own search with their client-side
SDK, you can also plug the built-in dialog interface.
```tsx title="components/search.tsx"
'use client';
import algo from 'algoliasearch/lite';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
const client = algo('appId', 'apiKey');
const index = client.initIndex('indexName');
export default function CustomSearchDialog(props: SharedProps) {
return <SearchDialog index={index} {...props} />;
}
```
1. Replace `appId`, `apiKey` and `indexName` with your desired values.
2. [Replace the default search dialog](#replace-search-dialog) with your new component.
<Callout title="Note" className='mt-4'>
The built-in implementation doesn't use instant search (their official
javascript client).
</Callout>
#### Tag Filter
Same as default search client, you can configure [Tag Filter](/docs/headless/search/algolia#tag-filter) on the dialog.
```tsx title="components/search.tsx"
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
<SearchDialog
defaultTag="value"
tags={[
{
name: 'Tag Name',
value: 'value',
},
]}
/>;
```
### Orama Cloud
For the setup guide, see [Integrate Orama Cloud](/docs/headless/search/orama-cloud).
```tsx title="components/search.tsx"
'use client';
import { OramaClient } from '@oramacloud/client';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
import SearchDialog from 'fumadocs-ui/components/dialog/search-orama';
const client = new OramaClient({
endpoint: 'endpoint',
api_key: 'apiKey',
});
export default function CustomSearchDialog(props: SharedProps) {
return <SearchDialog {...props} client={client} showOrama />;
}
```
1. Replace `endpoint`, `apiKey` with your desired values.
2. [Replace the default search dialog](#replace-search-dialog) with your new component.
### Community Integrations
A list of integrations maintained by community.
- [Trieve Search](/docs/headless/search/trieve)
## Built-in UI
If you want to use the built-in search dialog UI instead of building your own,
you may use the `SearchDialog` component.
```tsx
import {
SearchDialog,
type SharedProps,
} from 'fumadocs-ui/components/dialog/search';
export default function CustomSearchDialog(props: SharedProps) {
return <SearchDialog {...props} />;
}
```
<Callout type="warn" title="Unstable">
It is an internal API, might break during iterations
</Callout>

View File

@ -1,247 +0,0 @@
---
title: 搜索
description: 在您的文档中实现文档搜索
---
Fumadocs UI 为您的文档提供了一个美观的搜索界面,而搜索功能则由 Fumadocs Core 提供和记录。
参见[文档搜索](/docs/headless/search)。
## 搜索 UI
使用 <kbd>⌘</kbd> <kbd>K</kbd> 或 <kbd>Ctrl</kbd> <kbd>K</kbd> 打开。
### 配置
您可以通过根布局中的 [Root Provider](/docs/layouts/root-provider) 组件自定义搜索 UI。
当未指定时,它使用由 Orama 提供支持的默认 [`fetch` 搜索客户端](/docs/headless/search/orama)。
### 自定义链接
向搜索对话框添加自定义链接项。
当查询为空时,它们会显示为备选项。
```tsx title="app/layout.tsx"
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
links: [
['Home', '/'],
['Docs', '/docs'],
],
}}
>
{children}
</RootProvider>;
```
### 禁用搜索
要禁用文档搜索,请在根提供程序中禁用它。
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
enabled: false,
}}
>
{children}
</RootProvider>;
```
### 热键
自定义触发搜索对话框的热键。
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
hotKey: [
{
display: 'K',
key: 'k', // key code, or a function determining whether the key is pressed
},
],
}}
>
{children}
</RootProvider>;
```
### 标签过滤器
添加 UI 以更改过滤器。
确保首先在搜索服务器上配置[标签过滤器](/docs/headless/search/orama#tag-filter)。
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
options: {
defaultTag: 'value',
tags: [
{
name: 'Tag Name',
value: 'value',
},
],
},
}}
>
{children}
</RootProvider>;
```
### 搜索选项
向搜索客户端传递选项,例如更改 Orama 搜索服务器的 API 端点:
```tsx
import { RootProvider } from 'fumadocs-ui/root-provider';
<RootProvider
search={{
options: {
api: '/api/search/docs',
},
}}
>
{children}
</RootProvider>;
```
### 替换搜索对话框
您可以用以下内容替换默认搜索对话框:
```tsx title="components/search.tsx"
'use client';
import SearchDialog from 'fumadocs-ui/components/dialog/search-default';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
export default function CustomDialog(props: SharedProps) {
// your own logic here
return <SearchDialog {...props} />;
}
```
要将其传递给 Root Provider您需要一个带有 `use client` 指令的包装器。
```tsx title="provider.tsx"
'use client';
import { RootProvider } from 'fumadocs-ui/provider';
import dynamic from 'next/dynamic';
import type { ReactNode } from 'react';
const SearchDialog = dynamic(() => import('@/components/search')); // lazy load
export function Provider({ children }: { children: ReactNode }) {
return (
<RootProvider
search={{
SearchDialog,
}}
>
{children}
</RootProvider>
);
}
```
使用它替代您之前的 Root Provider
```tsx title="layout.tsx"
import { Provider } from './provider';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<Provider>{children}</Provider>
</body>
</html>
);
}
```
## 其他解决方案
### Algolia
关于设置指南,请参见[集成 Algolia 搜索](/docs/headless/search/algolia)。
虽然我们通常建议使用他们的客户端 SDK 构建您自己的搜索,但您也可以插入内置的对话框接口。
```tsx title="components/search.tsx"
'use client';
import algo from 'algoliasearch/lite';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
const client = algo('appId', 'apiKey');
const index = client.initIndex('indexName');
export default function CustomSearchDialog(props: SharedProps) {
return <SearchDialog index={index} {...props} />;
}
```
1. 将 `appId`、`apiKey` 和 `indexName` 替换为您想要的值。
2. 用您的新组件[替换默认搜索对话框](#replace-search-dialog)。
<Callout title="注意" className='mt-4'>
内置实现不使用即时搜索(他们的官方 JavaScript 客户端)。
</Callout>
#### 标签过滤器
与默认搜索客户端相同,您可以在对话框上配置[标签过滤器](/docs/headless/search/algolia#tag-filter)。
```tsx title="components/search.tsx"
import SearchDialog from 'fumadocs-ui/components/dialog/search-algolia';
<SearchDialog
defaultTag="value"
tags={[
{
name: 'Tag Name',
value: 'value',
},
]}
/>;
```
### Orama Cloud
关于设置指南,请参见[集成 Orama Cloud](/docs/headless/search/orama-cloud)。
```tsx title="components/search.tsx"
'use client';
import { OramaClient } from '@oramacloud/client';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
import SearchDialog from 'fumadocs-ui/components/dialog/search-orama';
const client = new OramaClient({
endpoint: 'endpoint',
api_key: 'apiKey',
});
export default function CustomSearchDialog(props: SharedProps) {
return <SearchDialog {...props} client={client} showOrama />;
}
```
1. 将 `endpoint`、`apiKey` 替换为您想要的值。
2. 用您的新组件[替换默认搜索对话框](#replace-search-dialog)。

View File

@ -1,55 +0,0 @@
---
title: Static Export
description: Enable static export with Fumadocs
---
## Overview
Fumadocs is fully compatible with Next.js static export, allowing you to export the app as a static HTML site without a Node.js server.
```js title="next.config.mjs"
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',
};
```
## Search
### Cloud Solutions
Since the search functionality is powered by remote servers, static export works without configuration.
### Built-in Search
The default search config of Orama Search uses route handlers, which is not supported by static export.
Instead, you can build the search indexes statically following the [Orama Search](/docs/headless/search/orama#static-export) guide.
And enable static mode on search client from Root Provider:
```tsx title="app/layout.tsx"
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<RootProvider
search={{
options: {
type: 'static', // [!code highlight]
},
}}
>
{children}
</RootProvider>
</body>
</html>
);
}
```
This allows the route handler to be statically cached into a single file, and search will be computed on browser instead.

View File

@ -1,55 +0,0 @@
---
title: 静态导出
description: 使用 Fumadocs 启用静态导出
---
## 概览
Fumadocs 完全兼容 Next.js 静态导出,允许您将应用程序导出为不需要 Node.js 服务器的静态 HTML 站点。
```js title="next.config.mjs"
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',
};
```
## 搜索
### 云解决方案
由于搜索功能由远程服务器提供支持,静态导出无需配置即可工作。
### 内置搜索
Orama 搜索的默认搜索配置使用路由处理器,静态导出不支持这种方式。
相反,您可以按照 [Orama 搜索](/docs/headless/search/orama#static-export) 指南静态构建搜索索引。
并从 Root Provider 在搜索客户端上启用静态模式:
```tsx title="app/layout.tsx"
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<RootProvider
search={{
options: {
type: 'static', // [!code highlight]
},
}}
>
{children}
</RootProvider>
</body>
</html>
);
}
```
这允许路由处理器被静态缓存到单个文件中,搜索将在浏览器中计算。

View File

@ -1,166 +0,0 @@
---
title: Themes
description: Add Theme to Fumadocs UI
---
## Usage
Note only Tailwind CSS v4 is supported:
```css title="Tailwind CSS"
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
/* path of `fumadocs-ui` relative to the CSS file */
@source '../node_modules/fumadocs-ui/dist/**/*.js';
```
### Preflight Changes
By using the Tailwind CSS plugin, or the pre-built stylesheet, your default border, text and background
colors will be changed.
### Light/Dark Modes
Fumadocs supports light/dark modes with [`next-themes`](https://github.com/pacocoursey/next-themes), it is included in Root Provider.
See [Root Provider](/docs/layouts/root-provider#theme-provider) to learn more.
### RTL Layout
RTL (Right-to-left) layout is supported.
To enable RTL, set the `dir` prop to `rtl` in body and root provider (required for Radix UI).
```tsx
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body dir="rtl">
<RootProvider dir="rtl">{children}</RootProvider>
</body>
</html>
);
}
```
### Prefix
Fumadocs UI has its own colors, animations, and utilities.
By default, it adds a `fd-` prefix to avoid conflicts with Shadcn UI or your own CSS variables.
You can use them without the prefix by adding some aliases:
```css title="Tailwind CSS"
@theme {
--color-primary: var(--color-fd-primary);
}
```
> You can use it with CSS media queries for responsive design.
### Layout Width
Customise the max width of docs layout with CSS Variables.
```css
:root {
--fd-layout-width: 1400px;
}
```
{/* <WidthTrigger /> */}
## Tailwind CSS Preset
The Tailwind CSS preset introduces new colors and extra utilities including `fd-steps`.
### Themes
It comes with many themes out-of-the-box, you can pick one you prefer.
```css
@import 'fumadocs-ui/css/<theme>.css';
/* Example */
@import 'fumadocs-ui/css/black.css';
```
<Tabs items={['neutral', 'black', 'vitepress', 'dusk', 'catppuccin', 'ocean', 'purple']}>
<Tab value='neutral'>
![Neutral](/images/docs/themes/neutral.png)
</Tab>
<Tab value='black'>
![Black](/images/docs/themes/black.png)
</Tab>
<Tab value='vitepress'>
![Vitepress](/images/docs/themes/vitepress.png)
</Tab>
<Tab value='dusk'>
![Dusk](/images/docs/themes/dusk.png)
</Tab>
<Tab value='Catppuccin'>
![Catppuccin](/images/docs/themes/catppuccin.png)
</Tab>
<Tab value='ocean'>
![Ocean](/images/docs/themes/ocean.png)
</Tab>
<Tab value='purple'>
![Purple](/images/docs/themes/purple.png)
</Tab>
</Tabs>
### Colors
The design system was inspired by [Shadcn UI](https://ui.shadcn.com), you can easily customize the colors using CSS variables.
```css title="global.css"
:root {
--color-fd-background: hsl(0, 0%, 100%);
}
.dark {
--color-fd-background: hsl(0, 0%, 0%);
}
```
### Typography
We have a built-in plugin forked from [Tailwind CSS Typography](https://tailwindcss.com/docs/typography-plugin).
The plugin adds a `prose` class and variants to customise it.
```tsx
<div className="prose">
<h1>Good Heading</h1>
</div>
```
> The plugin works with and only with Fumadocs UI's MDX components, it may conflict with `@tailwindcss/typography`.
> If you need to use `@tailwindcss/typography` over the default plugin, [set a class name option](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md#changing-the-default-class-name) to avoid conflicts.

View File

@ -1,165 +0,0 @@
---
title: 主题
description: 为 Fumadocs UI 添加主题
---
## 使用方法
注意只支持 Tailwind CSS v4
```css title="Tailwind CSS"
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
/* path of `fumadocs-ui` relative to the CSS file */
@source '../node_modules/fumadocs-ui/dist/**/*.js';
```
### 预设更改
通过使用 Tailwind CSS 插件或预构建的样式表,您的默认边框、文本和背景颜色将被更改。
### 明/暗模式
Fumadocs 通过 [`next-themes`](https://github.com/pacocoursey/next-themes) 支持明/暗模式,它包含在 Root Provider 中。
参见 [Root Provider](/docs/layouts/root-provider#theme-provider) 了解更多信息。
### RTL 布局
支持 RTL从右到左布局。
要启用 RTL请在 body 和 root providerRadix UI 需要)中将 `dir` 属性设置为 `rtl`。
```tsx
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body dir="rtl">
<RootProvider dir="rtl">{children}</RootProvider>
</body>
</html>
);
}
```
### 前缀
Fumadocs UI 有自己的颜色、动画和工具。
默认情况下,它添加了 `fd-` 前缀,以避免与 Shadcn UI 或您自己的 CSS 变量冲突。
您可以通过添加一些别名来使用它们,而无需前缀:
```css title="Tailwind CSS"
@theme {
--color-primary: var(--color-fd-primary);
}
```
> 您可以将其与 CSS 媒体查询一起使用,实现响应式设计。
### 布局宽度
使用 CSS 变量自定义文档布局的最大宽度。
```css
:root {
--fd-layout-width: 1400px;
}
```
{/* <WidthTrigger /> */}
## Tailwind CSS 预设
Tailwind CSS 预设引入了新的颜色和额外的工具,包括 `fd-steps`。
### 主题
它开箱即用地提供了许多主题,您可以选择一个您喜欢的。
```css
@import 'fumadocs-ui/css/<theme>.css';
/* Example */
@import 'fumadocs-ui/css/black.css';
```
<Tabs items={['neutral', 'black', 'vitepress', 'dusk', 'catppuccin', 'ocean', 'purple']}>
<Tab value='neutral'>
![Neutral](/images/docs/themes/neutral.png)
</Tab>
<Tab value='black'>
![Black](/images/docs/themes/black.png)
</Tab>
<Tab value='vitepress'>
![Vitepress](/images/docs/themes/vitepress.png)
</Tab>
<Tab value='dusk'>
![Dusk](/images/docs/themes/dusk.png)
</Tab>
<Tab value='Catppuccin'>
![Catppuccin](/images/docs/themes/catppuccin.png)
</Tab>
<Tab value='ocean'>
![Ocean](/images/docs/themes/ocean.png)
</Tab>
<Tab value='purple'>
![Purple](/images/docs/themes/purple.png)
</Tab>
</Tabs>
### 颜色
设计系统的灵感来自 [Shadcn UI](https://ui.shadcn.com),您可以使用 CSS 变量轻松自定义颜色。
```css title="global.css"
:root {
--color-fd-background: hsl(0, 0%, 100%);
}
.dark {
--color-fd-background: hsl(0, 0%, 0%);
}
```
### 排版
我们有一个内置插件,它是从 [Tailwind CSS Typography](https://tailwindcss.com/docs/typography-plugin) 派生而来的。
该插件添加了一个 `prose` 类和变体来自定义它。
```tsx
<div className="prose">
<h1>Good Heading</h1>
</div>
```
> 该插件仅与 Fumadocs UI 的 MDX 组件一起工作,它可能与 `@tailwindcss/typography` 冲突。
> 如果您需要使用 `@tailwindcss/typography` 而不是默认插件,请[设置类名选项](https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md#changing-the-default-class-name)以避免冲突。

View File

@ -1,58 +0,0 @@
---
title: What is Fumadocs
description: Introducing Fumadocs, a docs framework that you can break.
icon: CircleHelp
---
Fumadocs was created because I wanted a more customisable experience for building docs, to be a docs framework that is not opinionated, **a "framework" that you can break**.
## Philosophy
**Less Abstraction:** Fumadocs expects you to write code and cooperate with the rest of your software.
While most frameworks are configured with a configuration file, they usually lack flexibility when you hope to tune its details.
You cant control how they render the page nor the internal logic. Fumadocs shows you how the app works, instead of a single configuration file.
**Next.js Fundamentals:** It gives you the utilities and a good-looking UI.
You are still using features of Next.js App Router, like **Static Site Generation**. There is nothing new for Next.js developers, so you can use it with confidence.
**Opinionated on UI:** The only thing Fumadocs UI (the default theme) offers is **User Interface**. The UI is opinionated for bringing better mobile responsiveness and user experience.
Instead, we use a much more flexible approach inspired by Shadcn UI — [Fumadocs CLI](/docs/cli), so we can iterate our design quick, and welcome for more feedback about the UI.
## Why Fumadocs
Fumadocs is designed with flexibility in mind.
You can use `fumadocs-core` as a headless UI library and bring your own styles.
Fumadocs MDX is also a useful library to handle MDX content in Next.js. It also includes:
- Many built-in components.
- Typescript Twoslash, OpenAPI, and Math (KaTeX) integrations.
- Fast and optimized by default, natively built on App Router.
- Tight integration with Next.js, you can add it to an existing Next.js project easily.
You can read [Comparisons](/docs/comparisons) if you're interested.
### Documentation
Fumadocs focuses on **authoring experience**, it provides a beautiful theme and many docs automation tools.
It helps you to iterate your codebase faster while never leaving your docs behind.
You can take this site as an example of docs site built with Fumadocs.
### Blog sites
Since Next.js is already a powerful framework, most features can be implemented with **just Next.js**.
Fumadocs provides additional tooling for Next.js, including syntax highlighting, document search, and a default theme (Fumadocs UI).
It helps you to avoid reinventing the wheels.
## When to use Fumadocs
For most of the web applications, vanilla React.js is no longer enough.
Nowadays, we also wish to have a blog, a showcase page, a FAQ page, etc. With a
fancy UI that's breathtaking, in these cases, Fumadocs can help you build the
docs easier, with less boilerplate.
Fumadocs is maintained by Fuma and many contributors, with care on the maintainability of codebase.
While we don't aim to offer every functionality people wanted, we're more focused on making basic features perfect and well-maintained.
You can also help Fumadocs to be more useful by contributing!

View File

@ -1,56 +0,0 @@
---
title: 什么是 Fumadocs
description: 介绍 Fumadocs一个可以打破常规的文档框架
icon: CircleHelp
---
Fumadocs 的创建是因为我想要一种更加可定制化的文档构建体验,一个不固执己见的文档框架,**一个你可以"打破"的"框架"**。
## 理念
**更少的抽象:** Fumadocs 期望您编写代码并与您的其余软件协作。
虽然大多数框架都是通过配置文件进行配置,但当您希望调整其细节时,它们通常缺乏灵活性。
您无法控制它们如何渲染页面或内部逻辑。Fumadocs 向您展示应用程序如何工作,而不是仅提供单一的配置文件。
**Next.js 基础:** 它为您提供实用工具和美观的 UI。
您仍然使用 Next.js App Router 的功能,如**静态站点生成**。对于 Next.js 开发者来说没有新的东西,所以您可以放心使用。
**对 UI 有自己的看法:** Fumadocs UI默认主题提供的唯一东西是**用户界面**。UI 的设计理念是提供更好的移动响应性和用户体验。
相反,我们使用受 Shadcn UI 启发的更灵活的方法 — [Fumadocs CLI](/docs/cli),这样我们可以快速迭代设计,并欢迎更多关于 UI 的反馈。
## 为什么选择 Fumadocs
Fumadocs 的设计考虑了灵活性。
您可以将 `fumadocs-core` 用作无头 UI 库并带来您自己的样式。
Fumadocs MDX 也是处理 Next.js 中 MDX 内容的有用库。它还包括:
- 许多内置组件。
- Typescript Twoslash、OpenAPI 和 Math (KaTeX) 集成。
- 默认情况下快速且优化,原生构建在 App Router 上。
- 与 Next.js 紧密集成,您可以轻松将其添加到现有的 Next.js 项目中。
如果您感兴趣,可以阅读 [比较](/docs/comparisons)。
### 文档
Fumadocs 专注于**创作体验**,它提供了一个漂亮的主题和许多文档自动化工具。
它帮助您更快地迭代代码库,同时不会落下您的文档。
您可以将此站点作为使用 Fumadocs 构建的文档站点的示例。
### 博客站点
由于 Next.js 已经是一个强大的框架,大多数功能可以**仅使用 Next.js** 实现。
Fumadocs 为 Next.js 提供了额外的工具包括语法高亮、文档搜索和默认主题Fumadocs UI
它帮助您避免重新发明轮子。
## 何时使用 Fumadocs
对于大多数 Web 应用程序,原生 React.js 已经不够用了。
如今我们还希望有一个博客、展示页面、FAQ 页面等。带有令人惊叹的精美 UI在这些情况下Fumadocs 可以帮助您更轻松地构建文档,减少样板代码。
Fumadocs 由 Fuma 和许多贡献者维护,关注代码库的可维护性。
虽然我们不打算提供人们想要的每一项功能,但我们更专注于使基本功能完美且维护良好。
您也可以通过贡献来帮助 Fumadocs 变得更加有用!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 573 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 611 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 KiB

View File

@ -1,141 +0,0 @@
import * as Preview from '@/components/docs';
import { CustomMDXContent } from '@/components/shared/custom-mdx-content';
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from '@/components/ui/hover-card';
import { LOCALES } from '@/i18n/routing';
import { source } from '@/lib/docs/source';
import { constructMetadata } from '@/lib/metadata';
import { getUrlWithLocale } from '@/lib/urls/urls';
import Link from 'fumadocs-core/link';
import {
DocsBody,
DocsDescription,
DocsPage,
DocsTitle,
} from 'fumadocs-ui/page';
import type { Locale } from 'next-intl';
import { getTranslations } from 'next-intl/server';
import { notFound } from 'next/navigation';
import type { ReactNode } from 'react';
export function generateStaticParams() {
const slugParams = source.generateParams();
const params = LOCALES.flatMap((locale) =>
slugParams.map((param) => ({
locale,
slug: param.slug,
}))
);
return params;
}
export async function generateMetadata({ params }: DocPageProps) {
const { slug, locale } = await params;
const language = locale as string;
const page = source.getPage(slug, language);
if (!page) {
console.warn('docs page not found', slug, language);
notFound();
}
const t = await getTranslations({ locale, namespace: 'Metadata' });
return constructMetadata({
title: `${page.data.title} | ${t('title')}`,
description: page.data.description,
canonicalUrl: getUrlWithLocale(`/docs/${page.slugs.join('/')}`, locale),
});
}
function PreviewRenderer({ preview }: { preview: string }): ReactNode {
if (preview && preview in Preview) {
const Comp = Preview[preview as keyof typeof Preview];
return <Comp />;
}
return null;
}
export const revalidate = false;
interface DocPageProps {
params: Promise<{
slug?: string[];
locale: Locale;
}>;
}
/**
* Doc Page
*
* ref:
* https://github.com/fuma-nama/fumadocs/blob/dev/apps/docs/app/docs/%5B...slug%5D/page.tsx
*/
export default async function DocPage({ params }: DocPageProps) {
const { slug, locale } = await params;
const language = locale as string;
const page = source.getPage(slug, language);
if (!page) {
console.warn('docs page not found', slug, language);
notFound();
}
const preview = page.data.preview;
return (
<DocsPage
toc={page.data.toc}
full={page.data.full}
tableOfContent={{
style: 'clerk',
}}
>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
{/* Preview Rendered Component */}
{preview ? <PreviewRenderer preview={preview} /> : null}
{/* MDX Content */}
<CustomMDXContent
code={page.data.body}
customComponents={{
a: ({ href, ...props }: { href?: string; [key: string]: any }) => {
const found = source.getPageByHref(href ?? '', {
dir: page.file.dirname,
});
if (!found) return <Link href={href} {...props} />;
return (
<HoverCard>
<HoverCardTrigger asChild>
<Link
href={
found.hash
? `${found.page.url}#${found.hash}`
: found.page.url
}
{...props}
/>
</HoverCardTrigger>
<HoverCardContent className="text-sm">
<p className="font-medium">{found.page.data.title}</p>
<p className="text-fd-muted-foreground">
{found.page.data.description}
</p>
</HoverCardContent>
</HoverCard>
);
},
}}
/>
</DocsBody>
</DocsPage>
);
}

View File

@ -1,112 +0,0 @@
import { XTwitterIcon } from '@/components/icons/x';
import { Logo } from '@/components/layout/logo';
import { ModeSwitcher } from '@/components/layout/mode-switcher';
import { websiteConfig } from '@/config/website';
import { docsI18nConfig } from '@/lib/docs/i18n';
import { source } from '@/lib/docs/source';
import { getUrlWithLocale } from '@/lib/urls/urls';
import { I18nProvider, type Translations } from 'fumadocs-ui/i18n';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
import { BookIcon, HomeIcon } from 'lucide-react';
import type { Locale } from 'next-intl';
import { getTranslations } from 'next-intl/server';
import type { ReactNode } from 'react';
import '@/styles/mdx.css';
// available languages that will be displayed on UI
// make sure `locale` is consistent with your i18n config
const locales = Object.entries(websiteConfig.i18n.locales).map(
([locale, data]) => ({
name: data.name,
locale,
})
);
interface DocsLayoutProps {
children: ReactNode;
params: Promise<{ locale: Locale }>;
}
/**
* 1. Configure navigation
* https://fumadocs.dev/docs/ui/navigation/links
* https://fumadocs.dev/docs/ui/navigation/sidebar
*
* ref:
* https://github.com/fuma-nama/fumadocs/blob/dev/apps/docs/app/layout.config.tsx
*
* 2. Organizing Pages
* https://fumadocs.dev/docs/ui/page-conventions
*
* ref:
* https://github.com/fuma-nama/fumadocs/blob/dev/apps/docs/content/docs/ui/meta.json
*/
export default async function DocsRootLayout({
children,
params,
}: DocsLayoutProps) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: 'DocsPage' });
// Create translations object for fumadocs-ui from our message files
const translations: Partial<Translations> = {
toc: t('toc'),
search: t('search'),
lastUpdate: t('lastUpdate'),
searchNoResult: t('searchNoResult'),
previousPage: t('previousPage'),
nextPage: t('nextPage'),
chooseLanguage: t('chooseLanguage'),
};
// Docs layout configurations
const showLocaleSwitch = Object.keys(websiteConfig.i18n.locales).length > 1;
const docsOptions: BaseLayoutProps = {
i18n: showLocaleSwitch ? docsI18nConfig : undefined,
githubUrl: websiteConfig.metadata.social?.github ?? undefined,
nav: {
url: getUrlWithLocale('/docs', locale),
title: (
<>
<Logo className="size-6" />
{t('title')}
</>
),
},
links: [
{
text: t('homepage'),
url: getUrlWithLocale('/', locale),
icon: <HomeIcon />,
active: 'none',
external: false,
},
...(websiteConfig.metadata.social?.twitter
? [
{
type: 'icon' as const,
icon: <XTwitterIcon />,
text: 'X',
url: websiteConfig.metadata.social.twitter,
secondary: true,
},
]
: []),
],
themeSwitch: {
enabled: true,
mode: 'light-dark-system',
component: <ModeSwitcher />,
},
};
return (
<I18nProvider locales={locales} locale={locale} translations={translations}>
<DocsLayout tree={source.pageTree[locale]} {...docsOptions}>
{children}
</DocsLayout>
</I18nProvider>
);
}

View File

@ -1,5 +0,0 @@
import { Loader2Icon } from 'lucide-react';
export default function Loading() {
return <Loader2Icon className="my-32 mx-auto size-6 animate-spin" />;
}