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.

It creates a record for each paragraph in your document, it is also 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.

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:

npm 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

Pre-render a static route /static.json to export search indexes into production build:

lib/export-search-indexes.ts
import { source } from '@/lib/source';
import type { DocumentRecord } from 'fumadocs-core/search/algolia';

export async function exportSearchIndexes() {
  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 results;
}
app/static.json/route.ts
import { exportSearchIndexes } from '@/lib/export-search-indexes';

export const revalidate = false;

export async function GET() {
  return Response.json(await exportSearchIndexes());
}

Make a script to sync search indexes:

scripts/sync-content.ts
import {  } from 'algoliasearch';
import { , DocumentRecord } from 'fumadocs-core/search/algolia';
import * as  from 'node:fs';

// the path of pre-rendered `static.json`, choose one according to your React framework
const  = {
  : '.next/server/app/static.json.body',
  'tanstack-start': '.output/public/static.json',
  'react-router': 'build/client/static.json',
  : 'dist/public/static.json',
}['next'];

const  = .();

const  = .(.()) as DocumentRecord[];

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

// update the index settings and sync search indexes
void (, {
  : 'document',
  : ,
});

Now run the script after build:

package.json
{
  "scripts": {
    "build": "... && bun ./scripts/sync-content.ts"
  }
}

Workflow

You may manually upload search indexes with the script, or integrate it with your CI/CD pipeline.

Search UI

You can consider different options for implementing the UI:

  • Using Fumadocs UI search dialog.

  • Build your own using the built-in search client hook:

    import {  } from 'algoliasearch/lite';
    import {  } from 'fumadocs-core/search/client';
    
    const  = ('id', 'key');
    
    const { , ,  } = ({
      : 'algolia',
      : 'document',
      ,
    });
  • Use their official clients directly.

Options

Tag Filter

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

lib/export-search-indexes.ts
import { source } from '@/lib/source';
import type { DocumentRecord } from 'fumadocs-core/search/algolia';

export async function exportSearchIndexes() {
  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,
      tag: '<your value>',
    });
  }

  return results;
}

And update your search client:

  • Fumadocs UI: Enable Tag Filter on Search UI.

  • Search Client: You can add the tag filter like:

    import { useDocsSearch } from 'fumadocs-core/search/client';
    
    const { search, setSearch, query } = useDocsSearch({
      tag: '<your tag value>',
      // ...
    });

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

How is this guide?

Last updated on