Revert "cf: test remove docs pages and docs+blog content"
This reverts commit c3392320b3
.
This commit is contained in:
parent
f3b6603db7
commit
593333c3dd
78
content/blog/comparisons.mdx
Normal file
78
content/blog/comparisons.mdx
Normal file
@ -0,0 +1,78 @@
|
||||
---
|
||||
title: Comparisons
|
||||
description: How is Fumadocs different from other existing frameworks?
|
||||
image: /images/blog/post-2.png
|
||||
date: 2025-03-22T12:00:00.000Z
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: fox
|
||||
---
|
||||
|
||||
## 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.
|
72
content/blog/comparisons.zh.mdx
Normal file
72
content/blog/comparisons.zh.mdx
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
title: 对比
|
||||
description: Fumadocs 与其他现有框架有何不同?
|
||||
image: /images/blog/post-2.png
|
||||
date: 2025-03-22T12:00:00.000Z
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: fox
|
||||
---
|
||||
|
||||
## 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 的灵活性允许您自己实现它们,可能需要更长的时间来调整它以达到您的满意度。
|
278
content/blog/fumadocs.mdx
Normal file
278
content/blog/fumadocs.mdx
Normal file
@ -0,0 +1,278 @@
|
||||
---
|
||||
title: Quick Start
|
||||
description: Getting Started with Fumadocs
|
||||
image: /images/blog/post-8.png
|
||||
date: 2025-03-28T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
## 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>
|
||||
|
||||
## 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>
|
253
content/blog/fumadocs.zh.mdx
Normal file
253
content/blog/fumadocs.zh.mdx
Normal file
@ -0,0 +1,253 @@
|
||||
---
|
||||
title: 快速入门
|
||||
description: Fumadocs 入门指南
|
||||
image: /images/blog/post-8.png
|
||||
date: 2025-03-28T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
## 简介
|
||||
|
||||
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 和 MDX(Markdown 的超集)。
|
||||
|
||||
虽然不是必需的,但对 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>
|
||||
|
||||
## 了解更多
|
||||
|
||||
刚来这里?别担心,我们欢迎您的问题。
|
227
content/blog/internationalization.mdx
Normal file
227
content/blog/internationalization.mdx
Normal file
@ -0,0 +1,227 @@
|
||||
---
|
||||
title: Internationalization
|
||||
description: Support multiple languages in your documentation
|
||||
image: /images/blog/post-3.png
|
||||
date: 2025-03-15T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
<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>
|
||||
```
|
227
content/blog/internationalization.zh.mdx
Normal file
227
content/blog/internationalization.zh.mdx
Normal file
@ -0,0 +1,227 @@
|
||||
---
|
||||
title: 国际化
|
||||
description: 在您的文档中支持多种语言
|
||||
image: /images/blog/post-3.png
|
||||
date: 2025-03-15T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
<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>
|
||||
```
|
198
content/blog/manual-installation.mdx
Normal file
198
content/blog/manual-installation.mdx
Normal file
@ -0,0 +1,198 @@
|
||||
---
|
||||
title: Manual Installation
|
||||
description: Create a new fumadocs project from scratch.
|
||||
image: /images/blog/post-4.png
|
||||
date: 2025-03-14T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
> 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.
|
196
content/blog/manual-installation.zh.mdx
Normal file
196
content/blog/manual-installation.zh.mdx
Normal file
@ -0,0 +1,196 @@
|
||||
---
|
||||
title: 手动安装
|
||||
description: 从零开始创建一个新的 Fumadocs 项目
|
||||
image: /images/blog/post-4.png
|
||||
date: 2025-03-14T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
> 请先阅读[快速入门](/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 在构建期间可以访问您的配置文件。
|
385
content/blog/markdown.mdx
Normal file
385
content/blog/markdown.mdx
Normal file
@ -0,0 +1,385 @@
|
||||
---
|
||||
title: Markdown
|
||||
description: How to write documents
|
||||
image: /images/blog/post-5.png
|
||||
date: 2025-03-05T12:00:00.000Z
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
| 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
|
||||

|
||||
```
|
||||
|
||||

|
||||
|
||||
## 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.
|
345
content/blog/markdown.zh.mdx
Normal file
345
content/blog/markdown.zh.mdx
Normal file
@ -0,0 +1,345 @@
|
||||
---
|
||||
title: Markdown
|
||||
description: 如何撰写文档
|
||||
image: /images/blog/post-5.png
|
||||
date: 2025-03-05T12:00:00.000Z
|
||||
published: true
|
||||
categories: [news, company]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## 介绍
|
||||
|
||||
Fumadocs 为 MDX(一种标记语言)提供了许多有用的扩展。以下是 Fumadocs UI 默认 MDX 语法的简要介绍。
|
||||
|
||||
> MDX 不是 Fumadocs 唯一支持的格式。实际上,您可以使用任何渲染器,如 `next-mdx-remote` 或 CMS。
|
||||
|
||||
## Markdown
|
||||
|
||||
我们使用 GFM(GitHub 风格的 Markdown),这是 Markdown(CommonMark)的超集。
|
||||
参见 [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
|
||||
|
||||

|
||||
|
||||
| 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
|
||||

|
||||
```
|
||||
|
||||
## 可选功能
|
||||
|
||||
一些您可以启用的可选插件。
|
280
content/blog/search.mdx
Normal file
280
content/blog/search.mdx
Normal file
@ -0,0 +1,280 @@
|
||||
---
|
||||
title: Search
|
||||
description: Implement document search in your docs
|
||||
image: /images/blog/post-6.png
|
||||
date: 2025-02-15T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
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>
|
252
content/blog/search.zh.mdx
Normal file
252
content/blog/search.zh.mdx
Normal file
@ -0,0 +1,252 @@
|
||||
---
|
||||
title: 搜索
|
||||
description: 在您的文档中实现文档搜索
|
||||
image: /images/blog/post-6.png
|
||||
date: 2025-02-15T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, news]
|
||||
author: mksaas
|
||||
---
|
||||
|
||||
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)。
|
171
content/blog/theme.mdx
Normal file
171
content/blog/theme.mdx
Normal file
@ -0,0 +1,171 @@
|
||||
---
|
||||
title: Themes
|
||||
description: Add Theme to Fumadocs UI
|
||||
image: /images/blog/post-7.png
|
||||
date: 2025-01-15T12:00:00.000Z
|
||||
published: true
|
||||
categories: [product, news]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## 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'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='black'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='vitepress'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='dusk'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Catppuccin'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='ocean'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='purple'>
|
||||
|
||||

|
||||
|
||||
</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.
|
170
content/blog/theme.zh.mdx
Normal file
170
content/blog/theme.zh.mdx
Normal file
@ -0,0 +1,170 @@
|
||||
---
|
||||
title: 主题
|
||||
description: 为 Fumadocs UI 添加主题
|
||||
image: /images/blog/post-7.png
|
||||
date: 2025-01-15T12:00:00.000Z
|
||||
published: true
|
||||
categories: [product, news]
|
||||
author: mkdirs
|
||||
---
|
||||
|
||||
## 使用方法
|
||||
|
||||
注意只支持 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 provider(Radix 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'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='black'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='vitepress'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='dusk'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='Catppuccin'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='ocean'>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab value='purple'>
|
||||
|
||||

|
||||
|
||||
</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)以避免冲突。
|
62
content/blog/what-is-fumadocs.mdx
Normal file
62
content/blog/what-is-fumadocs.mdx
Normal file
@ -0,0 +1,62 @@
|
||||
---
|
||||
title: What is Fumadocs
|
||||
description: Introducing Fumadocs, a docs framework that you can break.
|
||||
image: /images/blog/post-1.png
|
||||
date: 2025-04-01T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: fox
|
||||
---
|
||||
|
||||
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 can’t 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!
|
60
content/blog/what-is-fumadocs.zh.mdx
Normal file
60
content/blog/what-is-fumadocs.zh.mdx
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
title: 什么是 Fumadocs
|
||||
description: 介绍 Fumadocs,一个可以打破常规的文档框架
|
||||
image: /images/blog/post-1.png
|
||||
date: 2025-04-01T12:00:00.000Z
|
||||
published: true
|
||||
categories: [company, product]
|
||||
author: fox
|
||||
---
|
||||
|
||||
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 变得更加有用!
|
Loading…
Reference in New Issue
Block a user