コンテンツへスキップ
Fumadocs

組み込み検索

Fumadocs の組み込みドキュメント検索

Fumadocs は ZBSearch によるドキュメント検索をサポートしています。これはデフォルトの選択肢であるだけでなく、セルフホストが可能で完全に無料で使えるため、推奨の選択肢でもあります。

セットアップ

検索リクエストを処理するサーバーをホストします。

ソースから作成する

ソースオブジェクトからサーバーを作成します。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

export const { GET } = createFromSource(source);

検索インデックスから作成する

検索インデックスからサーバーを作成します。各インデックスには structuredData フィールドが必要です。

通常、これはコンテンツソース (例:Fumadocs MDX) から提供されます。Remark Structure プラグインを使って、Markdown/MDX ドキュメントから抽出することもできます。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createSearchAPI } from 'fumadocs-core/search/server';

export const { GET } = createSearchAPI('advanced', {
  indexes: source.getPages().map((page) => ({
    title: page.data.title,
    description: page.data.description,
    url: page.url,
    id: page.url,
    structuredData: page.data.structuredData,
  })),
});

ドキュメントの検索

ドキュメントは次の方法で検索できます。

  • Fumadocs UI: 追加設定なしでサポートされています。詳しくは検索 UIを参照してください。
  • 検索クライアント:
import {  } from 'fumadocs-core/search/client';

const { , , ,  } = ();

プロパティ

型

設定

タグフィルター

タグで検索結果を絞り込めます。このドキュメントのような複数ドキュメント構成を実装する際に便利です。

import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

const server = createFromSource(source, {
  buildIndex(page) {
    return {
      title: page.data.title,
      description: page.data.description,
      url: page.url,
      id: page.url,
      structuredData: page.data.structuredData,
      // 任意の値を指定します(例: page.slugs[0])
      tag: '<value>',
    };
  },
});

次に、検索クライアントを更新します。

  • Fumadocs UI: 検索 UI でタグフィルターを設定します。
  • 検索クライアント: useFetchSearch() にタグを渡します。
import { useFetchSearch } from 'fumadocs-core/search/client';

const { search, onSearchChange, isLoading, data } = useFetchSearch({
  tag: '<value>', 
});

静的モード

静的サイトで使用する場合は、検索サーバーの staticGET を使用し、ルートを静的ルートにするか、プリレンダリングするように設定してください。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

// 静的にキャッシュ
export const revalidate = false;
export const { staticGET: GET } = createFromSource(source);

staticGET は createSearchAPI でも利用できます。

続いて、検索クライアントを更新してください。

  • Fumadocs UI: 検索 UI で静的クライアントを使用します。

  • 検索クライアント: useFetchSearch() の代わりに useStaticSearch() を使用します。

    import { useStaticSearch } from 'fumadocs-core/search/client';
    
    const { search, onSearchChange, isLoading, data } = useStaticSearch();

    プロパティ

    型

注意

静的検索では、エクスポートされた検索インデックスをクライアント側でダウンロードする必要があります。 大規模なドキュメントサイトでは、コストが高くなる可能性があります。

そのような場合は、Orama Cloud や Algolia などのクラウドソリューションを使用してください。

国際化

検索機能は、追加設定なしですべての言語に対応しています。デフォルトの multilingual モードでは Unicode の単語分割を使用するため、中国語や日本語を含むすべてのロケールが、設定不要で単一の検索データベースを共有できます。

app/api/search/route.ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

// i18n 用の追加設定は不要です
const server = createFromSource(source);

次に、検索クライアントを更新します。

  • Fumadocs UI: 変更は不要です。i18n が正しく設定されていれば、Fumadocs UI が自動的に処理します。
  • 検索クライアント: 検索クライアントに locale を追加します。これにより、ユーザーが検索できるのは指定したロケールのページのみになります。
import { useFetchSearch } from 'fumadocs-core/search/client';

const { search, onSearchChange, isLoading, data } = useFetchSearch({
  locale: 'cn',
});

これは 静的モード にも当てはまります。その場合は、代わりに useStaticSearch() に locale を渡してください。

言語固有のトークン化

multilingual モードでは、言語固有のステミングやストップワード除去は行われません。 ステミングがないと、recordings のような複数形のクエリは recording を含むページにマッチしません。

多言語のセグメンテーションと単一のデータベースを維持したままステマーを組み込むには、tokenizer を渡します。

import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import { stemmer } from '@zbsearch/stemmers/english';

const server = createFromSource(source, {
  tokenizer: { language: 'multilingual', stemming: true, stemmer }, 
});

または、localeMap を使用して、サポートされている言語の一覧にある言語をロケールごとに指定することもできます。

import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

const server = createFromSource(source, {
  localeMap: {
    // [locale]: 検索オプション
    ru: { language: 'russian' },
    en: { language: 'english' },
  },
});

localeMap を有効にすると、ロケールごとに個別の検索データベースが作成される点に注意してください。

静的モード

クライアント側でもクエリを同じ方法でトークン化する必要があるため、カスタムの tokenizer はクライアントにも渡す必要があります。 useStaticSearch() の initDB を介して渡してください。

ヘッドレス

検索サーバーは、Express や Elysia などの別のバックエンドでホストすることもできます。

import { initAdvancedSearch } from 'fumadocs-core/search/server';

const server = initAdvancedSearch({
  // この場合もインデックスを渡す必要があります
});

server.search('query', {
  // ここで `locale` と `tag` を指定できます
});

How is this guide?

最終更新日