# Fumadocs (Framework Mode, Waku): 手動安裝
URL: /zh-TW/docs/waku/manual-installation
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/(framework)/[framework]/manual-installation.zh-TW.mdx

將 Fumadocs 加入現有的 Waku 專案。

您也可以使用 [Fumadocs CLI](/docs/cli#init) 自動完成設定：

```npm
npx @fumadocs/cli init
```

## 先決條件 [#prerequisites]

繼續之前，請確認您已設定好：

* Tailwind CSS 4。
* Fumadocs MDX：請依照 [Vite 設定指南](/docs/mdx/vite)操作，並建立 `lib/source.ts` 等必要檔案。

<Callout title="小提示">
Fumadocs 也支援其他內容來源，包括 [Content Collections](/docs/headless/content-collections) 與無頭式 CMS。
</Callout>

## 開始使用 [#getting-started]

安裝套件：

```npm
npm i fumadocs-core fumadocs-ui@npm:@fumadocs/base-ui
```

與範本相同，此指令會將 `fumadocs-ui` 安裝為 `@fumadocs/base-ui` 的別名，也就是 Fumadocs UI 的 [Base UI](/docs/ui/component-library) 版本。若要使用 Radix UI 版本，請直接安裝 `fumadocs-ui`，不要使用別名。

### 樣式 [#styles]

請將以下內容加入您的 Tailwind CSS 檔案：

```css
@import 'tailwindcss';
/* [!code ++:2] */
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
```

### Root Provider [#root-provider]

請在用戶端元件中，用 [Root Provider](/docs/ui/layouts/root-provider) 包住整個應用程式：

```tsx tab="src/components/provider.tsx"
'use client';
import type { ReactNode } from 'react';
import { RootProvider } from 'fumadocs-ui/provider/waku';

export function Provider({ children }: { children: ReactNode }) {
  return <RootProvider>{children}</RootProvider>;
}
```

```tsx tab="src/pages/_layout.tsx"
import '@/styles/globals.css';
import type { ReactNode } from 'react';
import { Provider } from '@/components/provider';

// [!code ++:3]
export default function RootLayout({ children }: { children: ReactNode }) {
  return <Provider>{children}</Provider>;
}

export const getConfig = async () => {
  return {
    render: 'static',
  };
};
```

### 路由 [#routes]

請將各版面配置共用的選項放在同一個檔案中：

```tsx title="src/lib/layout.shared.tsx"
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
import { appName, gitConfig } from './shared';

export function baseOptions(): BaseLayoutProps {
  return {
    nav: {
      // JSX supported
      title: appName,
    },
    githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
  };
}
```

請建立下列檔案：

```tsx tab="src/components/mdx.tsx"
import defaultMdxComponents from 'fumadocs-ui/mdx';
import type { MDXComponents } from 'mdx/types';

export function getMDXComponents(components?: MDXComponents) {
  return {
    ...defaultMdxComponents,
    ...components,
  } satisfies MDXComponents;
}

export const useMDXComponents = getMDXComponents;

declare global {
  type MDXProvidedComponents = ReturnType<typeof getMDXComponents>;
}
```

```tsx tab="src/pages/docs/_layout.tsx"
import type { ReactNode } from 'react';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { source } from '@/lib/source';
import { baseOptions } from '@/lib/layout.shared';

export default function Layout({ children }: { children: ReactNode }) {
  return (
    <DocsLayout {...baseOptions()} tree={source.getPageTree()}>
      {children}
    </DocsLayout>
  );
}
```

```tsx tab="src/pages/docs/[...slugs].tsx"
import { source } from '@/lib/source';
import { PageProps } from 'waku/router';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import {
  DocsBody,
  DocsDescription,
  DocsPage,
  DocsTitle,
  MarkdownCopyButton,
  ViewOptionsPopover,
} from 'fumadocs-ui/layouts/docs/page';
import { unstable_notFound } from 'waku/router/server';
import { getMDXComponents } from '@/components/mdx';
import { getPageImageUrl, gitConfig } from '@/lib/shared';

export default function Page({ slugs }: PageProps<'/docs/[...slugs]'>) {
  const page = source.getPage(slugs);
  if (!page) unstable_notFound();

  const MDX = page.data.body;
  const markdownUrl = `/llms.mdx${page.url}.md`;
  return (
    <DocsPage toc={page.data.toc}>
      <meta property="og:image" content={getPageImageUrl(page).url} />
      <DocsTitle>{page.data.title}</DocsTitle>
      <DocsDescription className="mb-0">{page.data.description}</DocsDescription>
      <div className="flex flex-row gap-2 items-center border-b pt-2 pb-6">
        <MarkdownCopyButton markdownUrl={markdownUrl} />
        <ViewOptionsPopover
          markdownUrl={markdownUrl}
          githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/content/docs/${encodeURI(page.path)}`}
        />
      </div>
      <DocsBody>
        <MDX
          components={getMDXComponents({
            // this allows you to link to other pages with relative file paths
            a: createRelativeLink(source, page),
          })}
        />
      </DocsBody>
    </DocsPage>
  );
}

export async function getConfig() {
  const pages = source
    .generateParams()
    .map((item) => (item.lang ? [item.lang, ...item.slug] : item.slug));

  return {
    render: 'static' as const,
    staticPaths: pages,
  } as const;
}
```

```ts tab="src/pages/_api/api/search.ts"
import { createFromSource } from 'fumadocs-core/search/server';
import { source } from '@/lib/source';

export const { GET } = createFromSource(source);
```

搜尋路由採用 ZBSearch，設定方式請參閱[文件搜尋](/docs/headless/search)。

### 完成 [#finish]

啟動開發伺服器，即可在 `content/docs` 中撰寫您的文件：

```mdx title="content/docs/index.mdx"
---
title: Hello World
---

## Introduction

I love Fumadocs.
```