Algolia Search in VuePress Without Joining DocSearch

Last Updated

VuePress supports Algolia-based search, but expects you to use the DocSearch service. This guide shows how to use VuePress’s DocSearch UI with standard Algolia.
A dog searching in the undergrowth for a dead fowl hidden by large leaves. Etching by W.S. Howitt
A dog searching in the undergrowth for a dead fowl hidden by large leaves. Etching by W.S. Howitt. Howitt, Samuel, 1765?-1822. Public Domain Mark. Source: Wellcome Collection.

VuePress 2 has first-party support for Algolia-driven search with integration for DocSearch UI. If you’ve read technical documentation for web tools, you’ve probably interacted with the DocSearch UI. For example, the VuePress docs use it; so do the React docs, TypeScript docs, Tailwind CSS docs, and on and on. See it on the DocSearch homepage.

VuePress’s integration expects you to use Algolia’s DocSearch service. The DocSearch service is for open-source projects only, in particular publicly available documentation or technical blogs. [ref] That’s a dealbreaker for some sites. And though powered by Algolia, DocSearch has its own distinct dashboard. [docs] It’s good, but it’s different, a new thing to learn, and not in your Algolia dashboard with your other applications. If you already use Algolia, you might prefer to not learn a new app, and to have your VuePress site listed in your Algolia dashboard.

There is another option: the VuePress docs [ref] state, “Alternatively, you can run your own crawler to generate the index, and then use your own appId, apiKey and indexName to configure this plugin.”

But the VuePress documentation and Algolia documentation don’t explain how. That’s where this guide comes in. It describes how I add the DocSearch search box to the VuePress 2 navbar without joining the DocSearch program. You can see the result in action at the zsh-abbr docs.

Adding Algolia-powered DocSearch UI to your VuePress site

  1. Sign up for a free Algolia account.

  2. In Algolia, create a new “application” (note the free tier option), and in it create a new “index”.

  3. VuePress needs access to your Algolia credentials. But we want to keep those secret, not in plain text in your repo. So we’ll put them in a dedicated file which is not tracked by Git, and use dot-env (more on that below) to read that file. Create a file .env in your project root

    This file should not be tracked in Git. Add a new line to your project’s .gitignore file (create it if necessary, in the project root) with the content

    .gitignore
    text
    .env
    text
    .env

    Give .env the following contents, replacing REPLACEME with the appropriate values.

    Yes, really, use xyz for the TYPESENSE_API_KEY.

    The Algolia application ID, admin API key, and search-only API key are found in your Algolia dashboard: sign into Algolia, go to Settings > API Keys, and select the application you created in the previous step.

    The Algolia index name is the name of the index you created in the previous step.

    .env
    yaml
    yaml
    TYPESENSE_API_KEY=xyz
    TYPESENSE_HOST=host.docker.internal
    TYPESENSE_PORT=8108
    TYPESENSE_PROTOCOL=http
    # Algolia admin API key
    API_KEY=REPLACEME
    # Algolia application ID
    APPLICATION_ID=REPLACEME
    # Algolia index name
    INDEX_NAME=REPLACEME
    # Algolia search-only API key
    SEARCH_KEY=REPLACEME
    yaml
    TYPESENSE_API_KEY=xyz
    TYPESENSE_HOST=host.docker.internal
    TYPESENSE_PORT=8108
    TYPESENSE_PROTOCOL=http
    # Algolia admin API key
    API_KEY=REPLACEME
    # Algolia application ID
    APPLICATION_ID=REPLACEME
    # Algolia index name
    INDEX_NAME=REPLACEME
    # Algolia search-only API key
    SEARCH_KEY=REPLACEME

    Warning

    You may be tempted to rename these. ALGOLIA_SEARCH_ONLY_API_KEY is clearer than SEARCH_KEY. Don’t do it. The DocSearch crawler expects certain names.

    Tip

    A common practice is to keep a skeletal .env.example or .env.sample tracked in the repo, with all sensitive content removed. For example, you might create .env.example with the content

    .env.example
    yaml
    yaml
    TYPESENSE_API_KEY=xyz
    TYPESENSE_HOST=host.docker.internal
    TYPESENSE_PORT=8108
    TYPESENSE_PROTOCOL=http
    # Algolia admin API key
    API_KEY=
    # Algolia application ID
    APPLICATION_ID=
    # Algolia index name
    INDEX_NAME=
    # Algolia search-only API key
    SEARCH_KEY=
    yaml
    TYPESENSE_API_KEY=xyz
    TYPESENSE_HOST=host.docker.internal
    TYPESENSE_PORT=8108
    TYPESENSE_PROTOCOL=http
    # Algolia admin API key
    API_KEY=
    # Algolia application ID
    APPLICATION_ID=
    # Algolia index name
    INDEX_NAME=
    # Algolia search-only API key
    SEARCH_KEY=
  4. Configure DocSearch

    1. Add dot-env as a dependency, following the installation instructions at https://github.com/motdotla/dotenv.

    2. Create a file docsearch.config.js with the following contents.

      • In start_urls replace "REPLACEME" with the URL(s) you want to crawl for this index. Typical use a single production URL, for example "https://my-vuepress-2-site.com".
      • selectors determines what is indexed. This example assumes that you are using the default theme; adjust it as necessary; learn more in the Algolia record extractor docs
      docsearch.config.js
      js
      js
      require('dotenv').config();
      const config = {
      index_name: process.env.INDEX_NAME,
      start_urls: [
         "REPLACEME",
      ],
      stop_urls: [],
      selectors: {
      lvl0: {
      selector: ".sidebar-heading.active",
      global: true,
      default_value: "Documentation"
      },
      lvl1: ".theme-default-content h1",
      lvl2: ".theme-default-content h2",
      lvl3: ".theme-default-content h3",
      lvl4: ".theme-default-content h4",
      lvl5: ".theme-default-content h5",
      text: ".theme-default-content p, .theme-default-content li, .theme-default-content table",
      lang: {
      selector: "/html/@lang",
      type: "xpath",
      global: true
      }
      },
      custom_settings: {
      attributesForFaceting: ["lang"]
      }
      }
      js
      require('dotenv').config();
      const config = {
      index_name: process.env.INDEX_NAME,
      start_urls: [
         "REPLACEME",
      ],
      stop_urls: [],
      selectors: {
      lvl0: {
      selector: ".sidebar-heading.active",
      global: true,
      default_value: "Documentation"
      },
      lvl1: ".theme-default-content h1",
      lvl2: ".theme-default-content h2",
      lvl3: ".theme-default-content h3",
      lvl4: ".theme-default-content h4",
      lvl5: ".theme-default-content h5",
      text: ".theme-default-content p, .theme-default-content li, .theme-default-content table",
      lang: {
      selector: "/html/@lang",
      type: "xpath",
      global: true
      }
      },
      custom_settings: {
      attributesForFaceting: ["lang"]
      }
      }
  5. Add the DocSearch search UI to your VuePress site, and configure it to use your personal Algolia index.

    1. Add the @vuepress/plugin-docsearch@next dependency as described in the VuePress documentation

    2. Import and use the plugin in your VuePress config file. ⚠️ At this point you might think “API_KEY isn’t used, I might as well remove it from .env.” Don’t remove it, it’s used by the crawler.

      docs/.vuepress/config.(js|ts)
      js
      js
      // could have other imports here
      import { docsearchPlugin } from '@vuepress/plugin-docsearch';
      export default { // `export default defineUserConfig({` if using TypeScript
      // could have other configuration here
      plugins: [
      // could have other plugins here
      docsearchPlugin({
      apiKey: process.env.SEARCH_KEY,
      appId: process.env.APPLICATION_ID,
      indexName: process.env.INDEX_NAME,
      }),
      // could have other plugins here
      ],
      // could have other configuration here
      };
      js
      // could have other imports here
      import { docsearchPlugin } from '@vuepress/plugin-docsearch';
      export default { // `export default defineUserConfig({` if using TypeScript
      // could have other configuration here
      plugins: [
      // could have other plugins here
      docsearchPlugin({
      apiKey: process.env.SEARCH_KEY,
      appId: process.env.APPLICATION_ID,
      indexName: process.env.INDEX_NAME,
      }),
      // could have other plugins here
      ],
      // could have other configuration here
      };

    Start up the VuePress dev server, and you should see the DocSearch search box in the navbar. But the site hasn’t been crawled yet, so the search box will be useless.

    Heads up

    If the DocSearch UI doesn’t show up, make sure your vuepress, @vuepress/client, and @vuepress/plugin-docsearch are all on the same version.

Crawling your site

Algolia’s legacy DocSearch scraper can scrape arbitrary content.

  1. The scraper uses Docker. If you have Docker Desktop installed, start it now. If you don’t, download it, install it, and start it.

  2. Add a Node package script to trigger a new crawl, by adding the following to your package.json’s scripts:

    package.json
    json
    json
    "docs:crawl": "docker run --platform=linux/amd64 -it --env-file=./.env -e \"CONFIG=$(node docsearch.config.js)\" algolia/docsearch-scraper",
    json
    "docs:crawl": "docker run --platform=linux/amd64 -it --env-file=./.env -e \"CONFIG=$(node docsearch.config.js)\" algolia/docsearch-scraper",
  3. The docs:crawl script crawls the docsearch.config.js start_urls. Use the live production URL for the start_urls. Deploy the latest version of your site before crawling, to assure that the latest content is crawled.

  4. In a terminal run

    command line
    shell
    # NPM
    npm run docs:crawl
    # Yarn
    yarn docs:crawl
    # pnpm
    pnpm docs:crawl
    shell
    # NPM
    npm run docs:crawl
    # Yarn
    yarn docs:crawl
    # pnpm
    pnpm docs:crawl

Reload your local dev site. The search box should work!

Reload your production site. The search box is not working yet, because the DocSearch UI on the production site isn’t connected to your Algolia app. Fix that by adding the SEARCH_KEY, APPLICATION_ID, and INDEX_NAME variables to your production environment. For example, Netlify users can use the Netlify UI or netlify.toml; Vercel users use the Vercel UI. Reload. The search box should work!

Updating content

We’ve configured the crawler to crawl the production site. If you make a text change locally, that change will not show up in the local search even after running the crawler. The workflow for updating content is

  1. Update content
  2. Push the update to production
  3. Run the crawler command (locally)

Search results will be up-to-date locally and on production.


Updates

May 1, 2024: Add Markdown table content to docsearch.config.js’s selectors.content.

Articles You Might Enjoy

Or Go To All Articles