
# SEO 및 검색

검색 기능은 Fumadocs에서 제공됩니다. Onedocs은 사이트맵, robots.txt 및 llms.txt 파일용 도우미를 추가하며, 모두 Next.js App Router 경로로 설정됩니다. 페이지 메타데이터와 Open Graph 이미지에 대해서는 `onedocs/metadata` 및 `onedocs/og`의 [API 레퍼런스](https://onedocs.inline0.dev/ko/docs/api-reference#metadata)를 참조하세요.

## 검색

Onedocs은 Fumadocs의 내장 Orama 검색을 사용합니다. API 경로를 만드세요:

```ts title="src/app/api/search/route.ts"
import { source } from "@/lib/source";
import { createFromSource } from "fumadocs-core/search/server";

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

`RootProvider`이 추가하는 검색 대화상자는 기본적으로 `/api/search`를 쿼리하므로 별도의 설정이 필요하지 않습니다.

## 사이트맵

`/sitemap.xml`에 사이트맵을 생성합니다:

```ts title="src/app/sitemap.ts"
import { generateSitemap } from "onedocs/seo";
import meta from "../../content/docs/meta.json";

const baseUrl = "https://yourdomain.com";

export default function sitemap() {
  return generateSitemap({
    baseUrl,
    pages: meta.pages ?? [],
  });
}
```

`generateSitemap`은 사이트 루트를 나열한 다음 `/docs` 아래 `pages`의 각 항목에 대해 URL 하나를 나열합니다. `---`(사이드바 구분자)로 시작하는 항목은 건너뛰며, `index`는 그 자체인 `/docs`에 매핑됩니다. 항목을 입력된 그대로 읽으므로 하위 폴더의 페이지에는 자체 항목이 필요합니다. 예: `"guides/setup"`.

## Robots.txt

`/robots.txt`에 robots.txt를 생성합니다:

```ts title="src/app/robots.ts"
import { generateRobots } from "onedocs/seo";

const baseUrl = "https://yourdomain.com";

export default function robots() {
  return generateRobots({ baseUrl });
}
```

다음이 생성됩니다:

```
User-Agent: *
Allow: /

Host: https://yourdomain.com
Sitemap: https://yourdomain.com/sitemap.xml
```

## LLMs.txt

[LLMs.txt](https://llmstxt.org/)는 AI 어시스턴트가 문서를 이해하도록 돕습니다. Onedocs은 요약 버전과 전체 콘텐츠 버전을 모두 생성할 수 있습니다.

### 요약 버전

페이지 제목과 설명이 포함된 `/llms.txt`를 만듭니다:

```ts title="src/app/llms.txt/route.ts"
import { createLLMsSource, generateLLMsText } from "onedocs/llms";
import { source } from "@/lib/source";
import config from "../../../onedocs.config";

export async function GET() {
  const llmsSource = createLLMsSource(source);
  const text = await generateLLMsText(llmsSource, {
    title: config.title,
    description: config.description,
  });

  return new Response(text, {
    headers: { "Content-Type": "text/plain; charset=utf-8" },
  });
}
```

파일은 제목과 설명으로 시작하고, 모든 페이지를 설명과 함께 `- Title: URL`로 나열한 다음 `/llms-full.txt`에 대한 참조로 끝납니다. 두 함수 모두 `createLLMsSource`의 래핑된 소스를 사용하며 Fumadocs 소스 자체를 사용하지 않고, Promise를 반환합니다.

### 전체 콘텐츠 버전

전체 문서가 포함된 `/llms-full.txt`를 만듭니다:

```ts title="src/app/llms-full.txt/route.ts"
import { createLLMsSource, generateLLMsFullText } from "onedocs/llms";
import { source } from "@/lib/source";

export async function GET() {
  const llmsSource = createLLMsSource(source);
  const text = await generateLLMsFullText(llmsSource);

  return new Response(text, {
    headers: { "Content-Type": "text/plain; charset=utf-8" },
  });
}
```

각 페이지는 제목, URL, 설명, 처리된 Markdown 순으로 작성되며, 페이지 사이에는 `---`가 들어갑니다.

페이지 텍스트는 Fumadocs MDX의 처리된 Markdown에서 가져오며, 기본적으로 꺼져 있습니다. 이 기능을 사용하지 않으면 `llms-full.txt`에는 제목, URL, 설명만 포함됩니다([#3](https://github.com/inline0/onedocs/issues/3)). `source.config.ts`에서 켜세요:

```ts title="source.config.ts"
import { defineDocs } from "fumadocs-mdx/config";

export const docs = defineDocs({
  dir: "content/docs",
  docs: {
    postprocess: {
      includeProcessedMarkdown: true,
    },
  },
});
```

## 구성 옵션

### 사이트맵 옵션

```ts
generateSitemap({
  baseUrl: "https://yourdomain.com",
  pages: ["index", "getting-started", "configuration"],
  docsPath: "/docs", // Default: "/docs"
});
```

### Robots 옵션

```ts
generateRobots({
  baseUrl: "https://yourdomain.com",
  sitemapPath: "/sitemap.xml", // Default: "/sitemap.xml"
});
```

## 제공 기능

이 경로들을 설정한 뒤:

| URL | 기능 |
|-----|--------------|
| `/api/search?query=...` | 검색 API 엔드포인트 |
| `/sitemap.xml` | 검색 엔진용 XML 사이트맵 |
| `/robots.txt` | 사이트맵 참조가 포함된 Robots 파일 |
| `/llms.txt` | AI 어시스턴트용 요약 |
| `/llms-full.txt` | AI 어시스턴트용 전체 문서 |
