Fumadocs

Algolia Search

Integrate Algolia Search with Fumadocs

Notice

If you're using Algolia's free tier, you have to display their logo on your search dialog.

Introduction

The Algolia Integration automatically configures Algolia Search for document search.

By default, it creates a record for each paragraph in your document, it is officially recommended by Algolia.

Each record contains searchable attributes:

AttributeDescription
titlePage Title
sectionHeading ID (nullable)
contentParagraph 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.

Setup

Install Dependencies

npm install algoliasearch

Sign up on Algolia

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

Sync Search Indexes

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

update-index.mjs
import algosearch from 'algoliasearch';
import { sync } from 'fumadocs-core/search/algolia';
 
const client = algosearch('id', 'key');
 
sync(client, {
  documents: indexes, // search indexes, may be provided by your content source
});

You can export the search indexes from Next.js using a route handler:

app/static.json/route.ts
import { NextResponse } from 'next/server';
import { type DocumentRecord } from 'fumadocs-core/search/algolia';
import { source } from '@/lib/source';
 
export const revalidate = false;
 
export function GET() {
  const results: DocumentRecord[] = [];
 
  for (const page of source.getPages()) {
    results.push({
      _id: page.url,
      structured: page.data.structuredData,
      url: page.url,
      title: page.data.title,
      description: page.data.description,
    });
  }
 
  return NextResponse.json(results);
}
update-index.mjs
import * as fs from 'node:fs';
 
const content = fs.readFileSync('.next/server/app/static.json.body');
 
// now you can pass it to `sync`
/** @type {import('fumadocs-core/search/algolia').DocumentRecord[]} **/
const indexes = JSON.parse(content.toString());

Make sure to run the script after build:

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.

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

Typescript Usage

If you are running the script with TSX or other similar Typescript executors, ensure to name it .mts for best ESM compatibility.

Search Client

To search documents on the client side, use Fumadocs UI Search Dialog, or make your own implementation.

In addition, the headless search client of Fumadocs can handle state management for React.

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.

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',
  })),
});

Search UI (Fumadocs UI)

Enable Tag Filter on Search Dialog.

Search Client

The tag field is an attribute for faceting. To filter indexes by tag, use the filter tag:value on Algolia search clients. On Fumadocs search client, you can add the tag filter like:

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>',
);

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.

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.

Edit on GitHub

Last updated on

On this page