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.

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.

Advanced

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.

Under the Hood

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.

How is this guide?

Last updated on

On this page