---
title: Algolia Search
description: Integrate Algolia Search with Fumadocs
---

<Callout title="Notice">
  If you're using Algolia's free tier, you have to [display their logo on your
  search dialog](https://algolia.com/policies/free-services-terms).
</Callout>

## Introduction

The Algolia Integration automatically configures Algolia Search for document search.

It creates a record for **each paragraph** in your document, it is also recommended by Algolia.

Each record contains searchable attributes:

| Attribute | Description           |
| --------- | --------------------- |
| `title`   | Page Title            |
| `section` | Heading ID (nullable) |
| `content` | Paragraph content     |

The `section` field only exists in paragraphs under a heading. Headings and
paragraphs are indexed as an individual record, grouped by their page ID.

Notice that it expects the `url` property of a page to be unique, you shouldn't have two pages with the same
url.

## Setup

### Install Dependencies

```package-install
algoliasearch
```

### Sign up on Algolia

Sign up and obtain the app id and API keys for your search. Store these
credentials in environment variables.

### Sync Search Indexes

Export the search indexes from Next.js using a route handler, this way we can access the search indexes after production build:

```json doc-gen:file
{
  "file": "../../examples/next-mdx/app/static.json/algolia.ts",
  "codeblock": {
    "meta": "title=\"app/static.json/route.ts\""
  }
}
```

Make a script to sync search indexes:

```js title="update-index.mjs"
import algosearch from 'algoliasearch';
import { sync } from 'fumadocs-core/search/algolia';
import * as fs from 'node:fs';

const content = fs.readFileSync('.next/server/app/static.json.body');

/** @type {import('fumadocs-core/search/algolia').DocumentRecord[]} **/
const indexes = JSON.parse(content.toString());

const client = algosearch('id', 'key');

sync(client, {
  documents: indexes, // search indexes, can be provided by your content source too [!code highlight]
});
```

The `sync` function will update the index settings and sync search indexes.

Now run the script after build:

```json title="package.json"
{
  "scripts": {
    "build": "next build && node ./update-index.mjs"
  }
}
```

### Workflow

You may make it a script and manually sync with `node ./update-index.mjs`, or
integrate it with your CI/CD pipeline.

<Callout type="warn" title="Typescript Usage">
  If you are running the script with [TSX](https://github.com/privatenumber/tsx)
  or other similar Typescript executors, ensure to name it `.mts` for best ESM
  compatibility.
</Callout>

### Search UI

You can consider different options for implementing the UI:

- [Fumadocs UI Usage](/docs/ui/search#algolia)
- Build your own using the built-in search client hook:

  ```ts
  import algosearch from 'algoliasearch';
  import { useDocsSearch } from 'fumadocs-core/search/client';

  const index = algosearch('id', 'key').initIndex('document');

  const { search, setSearch, query } = useDocsSearch({
    type: 'algolia',
    index,
    distinct: 5,
    hitsPerPage: 10,
  });
  ```

## Options

### Tag Filter

To configure tag filtering, add a `tag` value to indexes.

```js
import algosearch from 'algoliasearch';
import { sync } from 'fumadocs-core/search/algolia';

const client = algosearch('id', 'key');

sync(client, {
  documents: indexes.map((index) => ({
    ...index,
    tag: 'value', // [!code highlight]
  })),
});
```

And update your search client:

- **Fumadocs UI**: Enable [Tag Filter](/docs/ui/search#tag-filter-1) on Search Dialog.
- **Search Client**: You can add the tag filter like:

  ```ts
  import algosearch from 'algoliasearch';
  import { useDocsSearch } from 'fumadocs-core/search/client';

  const index = algosearch('id', 'key').initIndex('document');

  const { search, setSearch, query } = useDocsSearch(
    {
      type: 'algolia',
      index,
    },
    undefined,
    '<your tag value>',
  );
  ```

The `tag` field is an attribute for faceting. You can also use the filter `tag:value` on Algolia search clients.

### Customise Attributes & Settings

While the default attributes might not suit your case, you can pass `extra_data`
to index options for adding extra fields to each record.

```js
import { sync } from 'fumadocs-core/search/algolia';

sync(client, {
  documents: indexes.map((docs) => ({
    ...docs,
    extra_data: {
      value: 'hello world',
    },
  })),
});
```

To customize the default index settings, set index settings, and update
documents with `updateDocuments(...)` separately.
