Skip to main content

Overview

The Search API provides server and client-side search capabilities for Fumadocs. It supports multiple search backends including Orama, Algolia, and custom implementations.

Server API

createSearchAPI()

Create a search API endpoint with Orama.
function createSearchAPI<T extends 'simple' | 'advanced'>(
  type: T,
  options: T extends 'simple' ? SimpleOptions : AdvancedOptions
): SearchAPI;
type
'simple' | 'advanced'
required
Search implementation type:
  • 'simple': Basic full-text search
  • 'advanced': Search with structured content and headings
options
SimpleOptions | AdvancedOptions
required
Configuration options for the search implementation
SearchAPI
object
Object containing:
  • search(query, options?): Search function
  • export(): Export search indexes
  • GET: Route handler for search requests
  • staticGET: Route handler for exporting indexes
Example:
import { createSearchAPI } from 'fumadocs-core/search/server';

export const { GET } = createSearchAPI('advanced', {
  indexes: [
    {
      id: 'intro',
      title: 'Introduction',
      url: '/docs/intro',
      structuredData: {
        headings: [
          { id: 'overview', content: 'Overview', tag: 'h2' }
        ],
        contents: [
          { heading: 'overview', content: 'Getting started...' }
        ]
      }
    }
  ]
});

SimpleOptions

Options for simple search.
interface SimpleOptions {
  indexes: Index[] | (() => Index[] | Promise<Index[]>);
  language?: string;
  tokenizer?: Tokenizer;
  search?: Partial<SearchParams>;
  sort?: SortOptions;
  components?: Components;
  plugins?: Plugin[];
}
indexes
Index[] | Dynamic<Index>
required
Array of search indexes or function that returns indexes
language
string
Language for search (affects tokenization and stemming)
Custom search parameters passed to Orama

AdvancedOptions

Options for advanced search with structured content.
interface AdvancedOptions {
  indexes: AdvancedIndex[] | (() => AdvancedIndex[] | Promise<AdvancedIndex[]>);
  language?: string;
  tokenizer?: Tokenizer;
  search?: Partial<SearchParams>;
  sort?: SortOptions;
  components?: Components;
  plugins?: Plugin[];
}
indexes
AdvancedIndex[] | Dynamic<AdvancedIndex>
required
Array of advanced search indexes with structured data

Index

Simple search index structure.
interface Index {
  title: string;
  description?: string;
  breadcrumbs?: string[];
  content: string;
  url: string;
  keywords?: string;
}
title
string
required
Page title
content
string
required
Searchable content
url
string
required
Page URL
description
string
Page description
breadcrumbs
string[]
Navigation breadcrumbs
keywords
string
Additional keywords for search

AdvancedIndex

Advanced search index with structured content.
interface AdvancedIndex {
  id: string;
  title: string;
  description?: string;
  breadcrumbs?: string[];
  tag?: string | string[];
  structuredData: StructuredData;
  url: string;
}
id
string
required
Unique identifier for the page
title
string
required
Page title
structuredData
StructuredData
required
Preprocessed MDX content with headings and sections
url
string
required
Page URL
tag
string | string[]
Tags for filtering search results

createFromSource()

Create a search API directly from a loader source.
function createFromSource<C extends LoaderConfig>(
  source: LoaderOutput<C>,
  options?: {
    localeMap?: Record<string, Language>;
    buildIndex?: (page: Page) => Awaitable<AdvancedIndex>;
  } & Omit<AdvancedOptions, 'indexes'>
): SearchAPI;
source
LoaderOutput
required
Output from the loader function
options.buildIndex
function
Custom function to build search index from page data
options.localeMap
Record<string, Language>
Map language codes to Orama language settings
SearchAPI
SearchAPI
Search API instance with route handlers
Example:
import { createFromSource } from 'fumadocs-core/search/server';
import { source } from './source';

export const { GET } = createFromSource(source);

createI18nSearchAPI()

Create a search API with internationalization support.
function createI18nSearchAPI(
  type: 'simple' | 'advanced',
  options: {
    i18n: I18nConfig;
    indexes: (Index & { locale: string })[] | Dynamic<Index & { locale: string }>;
    localeMap?: Record<string, Language>;
  } & (SimpleOptions | AdvancedOptions)
): SearchAPI;
type
'simple' | 'advanced'
required
Search implementation type
options.i18n
I18nConfig
required
Internationalization configuration
options.indexes
Array
required
Indexes with locale property
options.localeMap
Record<string, Language>
Map locale codes to Orama languages
Example:
import { createI18nSearchAPI } from 'fumadocs-core/search/server';

export const { GET } = createI18nSearchAPI('advanced', {
  i18n: { languages: ['en', 'zh'], defaultLanguage: 'en' },
  indexes: [
    {
      locale: 'en',
      id: 'intro-en',
      title: 'Introduction',
      url: '/en/docs/intro',
      structuredData: { /* ... */ }
    },
    {
      locale: 'zh',
      id: 'intro-zh',
      title: '介绍',
      url: '/zh/docs/intro',
      structuredData: { /* ... */ }
    }
  ]
});

Client API

useDocsSearch()

React hook for search functionality.
function useDocsSearch(
  clientOptions: Client & {
    delayMs?: number;
    allowEmpty?: boolean;
  },
  deps?: DependencyList
): UseDocsSearch;

interface UseDocsSearch {
  search: string;
  setSearch: (v: string) => void;
  query: {
    isLoading: boolean;
    data?: SortedResult[] | 'empty';
    error?: Error;
  };
}
clientOptions
Client
required
Search client configuration (see Client types)
clientOptions.delayMs
number
default:"100"
Debounce delay for search requests (in milliseconds)
clientOptions.allowEmpty
boolean
default:"false"
Perform search even when query is empty
deps
DependencyList
Dependency array for re-querying (like useEffect)
Object containing:
  • search: Current search query string
  • setSearch: Function to update search query
  • query.isLoading: Whether search is in progress
  • query.data: Search results or ‘empty’
  • query.error: Error if search failed
Example:
import { useDocsSearch } from 'fumadocs-core/search/client';

function SearchDialog() {
  const { search, setSearch, query } = useDocsSearch({
    type: 'fetch',
    api: '/api/search'
  });

  return (
    <div>
      <input
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        placeholder="Search docs..."
      />
      {query.isLoading && <div>Searching...</div>}
      {query.data && query.data !== 'empty' && (
        <div>
          {query.data.map((result) => (
            <a key={result.id} href={result.url}>
              {result.content}
            </a>
          ))}
        </div>
      )}
    </div>
  );
}

Client Types

Supported search client configurations.
type Client =
  | { type: 'fetch'; api: string; }
  | { type: 'static'; db: RawData; }
  | { type: 'algolia'; appId: string; apiKey: string; indexName: string; }
  | { type: 'orama-cloud'; endpoint: string; apiKey: string; }
  | { type: 'orama-cloud-legacy'; cloudConfig: CloudConfig; }
  | { type: 'mixedbread'; apiKey: string; endpoint: string; };
type='fetch'
Fetch search results from an API endpoint
  • api: API endpoint URL
type='static'
Use a static exported database for client-side search
  • db: Exported Orama database
type='algolia'
Use Algolia for search
  • appId: Algolia application ID
  • apiKey: Algolia search API key
  • indexName: Index name
type='orama-cloud'
Use Orama Cloud for search
  • endpoint: Orama Cloud endpoint
  • apiKey: Orama Cloud API key

SortedResult

Search result structure.
interface SortedResult {
  id: string;
  url: string;
  type: 'page' | 'heading' | 'text';
  content: string;
  breadcrumbs?: string[];
}
id
string
Unique result identifier
url
string
Result URL (may include hash for headings)
type
'page' | 'heading' | 'text'
Result type
content
string
Result content with search term highlights (using <mark> tags)
breadcrumbs
string[]
Navigation breadcrumbs for the result

createContentHighlighter()

Create a highlighter for search results.
function createContentHighlighter(query: string | RegExp): {
  highlight(content: string): HighlightedText[];
  highlightMarkdown(content: string): string;
};

interface HighlightedText {
  type: 'text';
  content: string;
  styles?: { highlight?: boolean };
}
query
string | RegExp
required
Search query or regex pattern
highlighter
object
Object with methods:
  • highlight(content): Returns array of text segments with highlight flags
  • highlightMarkdown(content): Returns markdown with <mark> tags
Example:
import { createContentHighlighter } from 'fumadocs-core/search';

const highlighter = createContentHighlighter('react');
const highlighted = highlighter.highlightMarkdown(
  'Learn React with our guide'
);
// => 'Learn <mark>React</mark> with our guide'

Build docs developers (and LLMs) love