Algolia
This article guides you through adding Algolia Search to Docusaurus v3, assuming you already have an active  Algolia account.
Default
Add the following Algolia search configuration:
https://mkeithx.pages.dev
docusaurus.config.js
module.exports = {
  ...
  algolia: {
    apiKey: 'YOUR_API_KEY',
    indexName: 'YOUR_INDEX_NAME',
    appId: 'YOUR_APP_ID',
  },
  ...
};
Custom
In this method, we will extend Algolia search React component by utilizing the Swizzle method:
Add the following on your site configuration:
https://mkeithx.pages.dev
docusaurus.config.ts
import type { Config } from "@docusaurus/types";
import type * as Preset from "@docusaurus/preset-classic";
const config: Config = {
  title: "My Site",
  favicon: "img/favicon.ico",
  scripts: [
    {
      src: "https://YOUR_APP_ID-dsn.algolia.net",
      rel: "preconnect",
      crossorigin: true,
    },
  ],
  /* Your site config here */
};
export default config;
JavaScript
- npm
 - Yarn
 - pnpm
 
npm run swizzle @docusaurus/theme-classic SearchBar
yarn swizzle @docusaurus/theme-classic SearchBar
pnpm run swizzle @docusaurus/theme-classic SearchBar
Typescript
- npm
 - Yarn
 - pnpm
 
npm run swizzle @docusaurus/theme-classic SearchBar --typescript
yarn swizzle @docusaurus/theme-classic SearchBar --typescript
pnpm run swizzle @docusaurus/theme-classic SearchBar --typescript
Choose the --wrap option and add the following configuration in your src/theme/SearchBar:
https://mkeithx.pages.dev
- JavaScript
 - TypeScript
 
src/theme/SearchBar.js
import React from "react";
import SearchBar from "@theme-original/SearchBar";
import type SearchBarType from "@theme/SearchBar";
import type { WrapperProps } from "@docusaurus/types";
import { DocSearch } from "@docsearch/react";
export default function SearchBarWrapper(props) {
  return (
    <div>
      <DocSearch
        appId="YOUR_APP_ID"
        indexName="YOUR_INDEX_NAME"
        apiKey="YOUR_API_KEY"
      />
    </div>
  );
}
src/theme/SearchBar.tsx
import React from "react";
import SearchBar from "@theme-original/SearchBar";
import type SearchBarType from "@theme/SearchBar";
import type { WrapperProps } from "@docusaurus/types";
import { DocSearch } from "@docsearch/react";
type Props = WrapperProps<typeof SearchBarType>;
export default function SearchBarWrapper(props: Props): JSX.Element {
return (
  <>
    <DocSearch
      appId="YOUR_APP_ID"
      indexName="YOUR_INDEX_NAME"
      apiKey="YOUR_API_KEY"
  />
    <SearchBar {...props} />
  </>
);
}
tip
Visit documentation to learn more.
Crawlers
Docusaurus highly recommends to use the official v3 crawler configuration.
Crawlers template
- Default
 - Custom
 
new Crawler({
  appId: 'YOUR_APP_ID',
  apiKey: 'YOUR_API_KEY',
  rateLimit: 8,
  maxDepth: 10,
  startUrls: ['https://YOUR_WEBSITE_URL/'],
  sitemaps: ['https://YOUR_WEBSITE_URL/sitemap.xml'],
  ignoreCanonicalTo: true,
  discoveryPatterns: ['https://YOUR_WEBSITE_URL/**'],
  actions: [
    {
      indexName: 'YOUR_INDEX_NAME',
      pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
      recordExtractor: ({ $, helpers }) => {
        // priority order: deepest active sub list header -> navbar active item -> 'Documentation'
        const lvl0 =
          $(
            '.menu__link.menu__link--sublist.menu__link--active, .navbar__item.navbar__link--active'
          )
            .last()
            .text() || 'Documentation';
        return helpers.docsearch({
          recordProps: {
            lvl0: {
              selectors: '',
              defaultValue: lvl0,
            },
            lvl1: ['header h1', 'article h1'],
            lvl2: 'article h2',
            lvl3: 'article h3',
            lvl4: 'article h4',
            lvl5: 'article h5, article td:first-child',
            lvl6: 'article h6',
            content: 'article p, article li, article td:last-child',
          },
          indexHeadings: true,
          aggregateContent: true,
          recordVersion: 'v3',
        });
      },
    },
  ],
  initialIndexSettings: {
    YOUR_INDEX_NAME: {
      attributesForFaceting: [
        'type',
        'lang',
        'language',
        'version',
        'docusaurus_tag',
      ],
      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',
      separatorsToIndex: '_',
    },
  },
});
new Crawler({
  appId: "<YOUR-APP-ID>",
  apiKey: "<YOU-API-KEY>",
  rateLimit: 8,
  maxDepth: 10,
  maxUrls: 5000,
  renderJavaScript: false,
  startUrls: ["https://YOUR_WEBSITE_URL"],
  sitemaps: ["https://YOUR_WEBSITE_URL/sitemap.xml"],
  ignoreCanonicalTo: true,
  discoveryPatterns: ["https://YOUR_WEBSITE_URL/**"],
# Optional
      // highlight-start
  exclusionPatterns: [
    "https://YOUR_WEBSITE_URL/FOO",
    "https://YOUR_WEBSITE_URL/BAR",
  ],
      // highlight-end
  schedule: "every 2 day at 6:00 am",
  actions: [
    {
      indexName: "<YOUR_INDEX_NAME>",
      pathsToMatch: ["https://YOUR_WEBSITE_URL/**"],
      recordExtractor: ({ $, helpers }) => {
        // priority order: deepest active sub list header -> navbar active item -> 'Documentation'
        const lvl0 =
          $(
            ".menu__link.menu__link--sublist.menu__link--active, .navbar__item.navbar__link--active",
          )
            .last()
            .text() || "Documentation";
        return helpers.docsearch({
          recordProps: {
            lvl0: {
              selectors: "",
              defaultValue: lvl0,
            },
            lvl1: ["header h1", "article h1"],
            lvl2: "article h2",
            lvl3: "article h3",
            lvl4: "article h4",
            lvl5: "article h5, article td:first-child",
            lvl6: "article h6",
            content: "article p, article li, article td:last-child",
          },
          indexHeadings: true,
          aggregateContent: true,
          recordVersion: "v3",
        });
      },
    },
  ],
  safetyChecks: { beforeIndexPublishing: { maxLostRecordsPercentage: 30 } },
  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",
      separatorsToIndex: "_",
    },
  },
});