---
title: "Search Clients"
description: "Search Clients in the Fumadocs ecosystem provide a unified interface for document search across diverse backends. They bridge the gap between UI components and search indexes, ensuring that users e..."
last_updated: "2026-07-02T09:46:38.966156+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/search-subsystem/search-clients"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/core/src/search/client.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client.ts)
- [packages/create-app/src/plugins/orama-cloud.ts](https://github.com/blade47/fumadocs/blob/main/packages/create-app/src/plugins/orama-cloud.ts)
- [packages/core/src/search/orama/create-server.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/orama/create-server.ts)
- [packages/core/src/search/client/orama-static.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/orama-static.ts)
- [packages/core/src/search/client/algolia.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/algolia.ts)
- [packages/radix-ui/src/components/dialog/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search.tsx)
- [packages/core/src/search/client/orama-cloud.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/orama-cloud.ts)
- [packages/core/src/search/client/orama-cloud-legacy.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/orama-cloud-legacy.ts)
- [packages/base-ui/src/components/dialog/search-orama.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-orama.tsx)
- [packages/radix-ui/src/components/dialog/search-orama.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search-orama.tsx)
- [packages/core/src/search/client/flexsearch-static.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/flexsearch-static.ts)
- [packages/radix-ui/src/components/dialog/search-algolia.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search-algolia.tsx)
- [packages/core/src/search/client/mixedbread.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/mixedbread.ts)
- [packages/base-ui/src/components/dialog/search-algolia.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-algolia.tsx)
- [packages/core/src/search/flexsearch/utils.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/flexsearch/utils.ts)
- [packages/core/src/search/algolia.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/algolia.ts)
- [packages/core/src/search/flexsearch.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/flexsearch.ts)
- [packages/base-ui/src/components/dialog/search-default.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-default.tsx)
- [packages/core/src/search/client/fetch.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/fetch.ts)
- [packages/create-app/template/+orama-cloud/@app/components/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/create-app/template/%2Borama-cloud/%40app/components/search.tsx)
- [packages/core/src/search/mixedbread.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/mixedbread.ts)
- [packages/base-ui/src/contexts/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/contexts/search.tsx)
- [packages/radix-ui/src/contexts/search.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/contexts/search.tsx)
- [packages/mdx/src/runtime/browser.tsx](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/runtime/browser.tsx)
- [packages/preview/src/pages/_api/api/search.ts](https://github.com/blade47/fumadocs/blob/main/packages/preview/src/pages/_api/api/search.ts)
- [packages/core/src/search/orama/create-db.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/orama/create-db.ts)
- [packages/core/src/search/orama-cloud.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/orama-cloud.ts)
- [packages/core/src/search/orama-cloud-legacy.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/orama-cloud-legacy.ts)
- [packages/core/src/search/orama/search/simple.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/orama/search/simple.ts)
- [packages/core/src/search/orama/search/advanced.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/orama/search/advanced.ts)
</details>

Search Clients in the Fumadocs ecosystem provide a unified interface for document search across diverse backends. They bridge the gap between UI components and search indexes, ensuring that users experience consistent behavior regardless of whether the search is performed against a local index (static/in-memory), a remote API, or a managed search provider.

By abstracting search logic behind a standard `SearchClient` interface, this subsystem allows developers to toggle between providers without refactoring UI components. This is achieved by utilizing the `useDocsSearch` hook, which manages loading states, result aggregation, and debouncing, enabling a seamless integration into documentation dialogs.

The design relies on a separation of concerns where the search engine handles indexing and querying, while the client implementation handles communication and result formatting. This architecture ensures that as indexing strategies evolve, the front-end remains decoupled from the low-level search implementation details.

## The `useDocsSearch` Orchestration Hook

The `useDocsSearch` hook is the primary entry point for managing search state in the browser. It implements a reactive workflow that responds to query updates and provider changes.

Mechanistically, it maintains four internal states: `search` (the current string), `results` (the `SortedResult` data), `error`, and `isLoading`. It utilizes `useDebounce` to throttle input updates, preventing excessive calls to remote APIs.

Crucially, it manages task cancellation using a `ref` object (`activeTaskRef`). When dependencies (like the client configuration or debounced query) change, the hook interrupts any pending execution to prevent race conditions. The core execution logic:

1.  Checks if the new query state is empty (respecting `allowEmpty` flag).
2.  Triggers the search via the provided `client.search()` method.
3.  Guards the update cycle: if `activeTaskRef.current.interrupt` is true, it skips result updates (`178|`, `184|`, `186|`).

Sources: [packages/core/src/search/client.ts:83-197](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client.ts#L83-L197)

## Search Provider Implementations

Each search client implements the `SearchClient` interface, which defines a mandatory `search` method returning `Awaitable<SortedResult[]>`.

| Client | Implementation Strategy | Dependencies |
| :--- | :--- | :--- |
| `fetch` | HTTP GET via `fetch()` | API URL, locale, tag |
| `orama-static` | Loads remote JSON blob into memory | URL (remote), locale, tag |
| `algolia` | `algoliasearch` SDK | indexName, client, tag |
| `orama-cloud` | `@orama/core` Cloud SDK | OramaCloud instance |
| `flexsearch-static` | Loads FlexSearch blob into memory | API URL, locale, tag |

Sources: [packages/core/src/search/client.ts:73-76](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client.ts#L73-L76), [packages/core/src/search/client/fetch.ts:27-52](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/fetch.ts#L27-L52), [packages/core/src/search/client/orama-static.ts:95-118](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/orama-static.ts#L95-L118), [packages/core/src/search/client/algolia.ts:54-89](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/algolia.ts#L54-L89), [packages/core/src/search/client/flexsearch-static.ts:23-41](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/flexsearch-static.ts#L23-L41)

## Static Index Lifecycle: Orama & FlexSearch

Static clients download search indexes once and cache them in memory. This improves search speed by eliminating round-trips for subsequent queries.

For `orama-static`, the mechanism is:
1.  `getDBCached` checks a module-level `cache` Map keyed by the index URL (`86|`).
2.  If missing, `loadDB` fetches the index, initializes an Orama instance using `create`, and populates it using `load` (`74|`).
3.  The search handler then retrieves the DB from the cache and delegates to the appropriate search utility (`101|`, `112|`).

> [!WARNING]
> The search index database is cached in a module-level Map variable `cache`. If the application dynamically changes the `from` URL without full page reloads, the client will fail to update its local index until a full refresh occurs.

Sources: [packages/core/src/search/client/orama-static.ts:34-93](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/orama-static.ts#L34-L93)

## Search Dialog Integration

The UI components (`SearchDialog`) interact with the search clients via common Context providers. For example, `OramaSearchDialog` wraps the core dialog and injects a client generated by `oramaCloudClient`.

The interaction flow is:
1.  The user types into `SearchDialogInput`.
2.  `onSearchChange` updates the state in the hook provided by the parent `SearchProvider`.
3.  `useDocsSearch` reacts to the state change, triggers the `SearchClient.search` method, and updates the `data` result.
4.  `SearchDialogList` renders the result array provided by the `useSearchList` hook.

Sources: [packages/base-ui/src/components/dialog/search-orama.tsx:68-76](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dialog/search-orama.tsx#L68-L76), [packages/radix-ui/src/components/dialog/search.tsx:299-403](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dialog/search.tsx#L299-L403)

## Result Aggregation & Grouping

When multiple hits correspond to a single documentation page, clients must perform grouping to avoid redundant list items. In the `algoliaClient`, this is handled by `groupResults`:

1.  A `Set<string>` named `scannedUrls` tracks unique URLs (`28|`).
2.  If a URL is not yet in the set, the hit is added as a 'page' type.
3.  All hits (including fragments/sections) are pushed to the list to allow deep linking to sections.
4.  This selection logic ensures that every page has a header entry, followed by its child sections.

Sources: [packages/core/src/search/client/algolia.ts:26-52](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/algolia.ts#L26-L52)

## Usage Example

Developers can integrate the search subsystem by creating a dialog component and wrapping it in a provider. Here is a minimal implementation using the default `fetchClient`:

```typescript
// Example: Using the Search Dialog with the Fetch client
import { fetchClient } from 'fumadocs-core/search/client/fetch';
import { useDocsSearch } from 'fumadocs-core/search/client';

function MySearch() {
  const { search, setSearch, query } = useDocsSearch({
    client: fetchClient({ api: '/api/search' }),
  });

  return (
    <div>
      <input value={search} onChange={(e) => setSearch(e.target.value)} />
      {query.isLoading && <span>Searching...</span>}
      <ul>
        {Array.isArray(query.data) && query.data.map(item => (
          <li key={item.id}>{item.content}</li>
        ))}
      </ul>
    </div>
  );
}
```

Sources: [packages/core/src/search/client/fetch.ts:27-52](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client/fetch.ts#L27-L52), [packages/core/src/search/client.ts:83-197](https://github.com/blade47/fumadocs/blob/main/packages/core/src/search/client.ts#L83-L197)

## Related

- [Search Indexing](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/search-subsystem/search-indexing)
- [Search Dialogs](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/search-subsystem/search-dialogs)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/llms.txt) for all pages in this wiki.
