Algolia

Integrate Algolia DocSearch into your Flame documentation site.

Algolia DocSearch provides a fast, relevant search experience for documentation sites. Flame does not include Algolia by default — add it via a plugin registered in the plugins array of docu.json:

:::info title="Example configuration — adapt to your plugin" The entry below is an example. @docubook/plugin-search-algolia is a placeholder — replace it with whatever Algolia search plugin you install. :::

json
{
  "plugins": [
    ["your-algolia-plugin-package", {
      "appId": "YOUR_APP_ID",
      "apiKey": "YOUR_SEARCH_ONLY_API_KEY",
      "indexName": "YOUR_INDEX_NAME",
      "assistantId": "optional_assistant_id"
    }]
  ]
}

The plugin format is [packageName, factoryOptions]. At build time, Flame loads the package, calls its default export as a factory with your options, and registers the returned plugin instance.

Register for DocSearch

Algolia provides DocSearch for open-source projects for free.

  1. Visit the DocSearch application

    Go to docsearch.algolia.com/apply and submit your documentation URL.

  2. Wait for approval

    Algolia reviews your application and sends your credentials:

    • Application ID
    • Search-Only API Key
    • Index Name
    • (optional) Assistant ID
  3. Add credentials to docu.json

    Add the plugin entry to plugins as shown above. No .env file needed.

Crawler Setup

After your site is live, configure the Algolia crawler to index your pages. The crawler runs externally on Algolia's infrastructure — no build-time impact on Flame.

Dashboard Setup

  1. Open Algolia Dashboard
  2. Navigate to Crawler

    Go to Data SourcesCrawler → click your crawler name.

  3. Add your domain

    In the Domains tab, add your production URL.

  4. Open the Editor

    Open the Setup dropdown → select Editor.

Crawler Configuration

Paste the configuration below into the editor. The values you need to change are highlighted.

index.js
new Crawler({
  appId: "YOUR_APP_ID",           // ← your App ID
  apiKey: "YOUR_CRAWLER_API_KEY",  // ← your crawler API key
  indexPrefix: "",
  rateLimit: 8,
  startUrls: ["https://your-domain.com"], // ← your domain
  renderJavaScript: true,
  maxDepth: 10,
  maxUrls: 8000,
  schedule: "every 1 day at 02:00 am",
  sitemaps: [],
  ignoreCanonicalTo: true,
  discoveryPatterns: ["https://your-domain.com/**"], // ← your domain
  actions: [
    {
      indexName: "YOUR_INDEX_NAME", // ← your index name
      pathsToMatch: ["https://your-domain.com/**"], // ← your domain
      recordExtractor: ({ $, helpers }) => {
        const lvl0 =
          // lvl0 = section name from breadcrumb (second item: Docs > Section > Page)
          $(".breadcrumbs li:nth-child(2)").text().trim() ||
          "Docs";

        const layoutAnchors = ["scroll-container", "main-navbar"];

        return helpers
          .docsearch({
            recordProps: {
              lvl0: {
                selectors: "",
                defaultValue: lvl0,
              },
              lvl1: [".prose h1"],
              content: [".prose p, .prose li"],
              lvl2: [".prose h2"],
              lvl3: [".prose h3"],
              lvl4: [".prose h4"],
              lvl5: [".prose h5"],
              lvl6: [".prose h6"],
            },
            aggregateContent: true,
            recordVersion: "v3",
          })
          .map((record) => {
            if (!layoutAnchors.includes(record.anchor)) return record;
            return {
              ...record,
              anchor: undefined,
              url: record.url
                ? record.url.replace(/#(scroll-container|main-navbar)$/, "")
                : record.url,
              url_without_anchor:
                record.url_without_anchor ||
                (record.url ? record.url.split("#")[0] : record.url),
            };
          });
      },
    },
  ],
  safetyChecks: { beforeIndexPublishing: { maxLostRecordsPercentage: 10 } },
  initialIndexSettings: {
    "YOUR_INDEX_NAME": {
      attributesForFaceting: ["type", "lang"],
      attributesToRetrieve: [
        "hierarchy", "content", "anchor", "url",
        "url_without_anchor", "type",
      ],
      attributesToHighlight: ["hierarchy", "content"],
      attributesToSnippet: ["content:10"],
      camelCaseAttributes: ["hierarchy", "content"],
      searchableAttributes: [
        "unordered(hierarchy.lvl0)",
        "unordered(hierarchy.lvl1)",
        "unordered(hierarchy.lvl2)",
        "unordered(hierarchy.lvl3)",
        "unordered(hierarchy.lvl4)",
        "unordered(hierarchy.lvl5)",
        "unordered(hierarchy.lvl6)",
        "content",
      ],
      distinct: true,
      attributeForDistinct: "url",
      customRanking: [
        "desc(weight.pageRank)",
        "desc(weight.level)",
        "asc(weight.position)",
      ],
      ranking: [
        "words", "filters", "typo", "attribute",
        "proximity", "exact", "custom",
      ],
      highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
      highlightPostTag: "</span>",
      minWordSizefor1Typo: 3,
      minWordSizefor2Typos: 7,
      allowTyposOnNumericTokens: false,
      minProximity: 1,
      ignorePlurals: true,
      advancedSyntax: true,
      attributeCriteriaComputedByMinProximity: true,
      removeWordsIfNoResults: "allOptional",
    },
  },
});

Index Settings

Key settings worth noting:

SettingValueWhy
distincttrueDeduplicate records by URL — one result per page
attributeForDistinct"url"Group all sections of a page under one result
renderJavaScripttrueFlame uses JS-rendered content — must be enabled
scheduleevery 1 dayKeeps search results fresh without over-scraping

Deploy

Credentials are in docu.json, so no .env or platform secrets needed. Deploy .docu/dist/ to any static host — the Algolia plugin handles everything at build time.

Last updated Aug 13, 2026