Suprisingly, I’ve managed to keep writing here on and off, and when I saw Pagefind I thought it looked like a great way to add search to my static site. It was refreshing easily!

I use Jekyll to build this blog - it outputs all the html for the site into a folder called _site and to deploy it, I rsync up the changes to my host.

Pagefind works by indexing all your html content and creating some additional files in the root of your static site. It creates a _pagefind directory and in there are the js files needed for the search UI to work on your site, plus the search indices and meta files it creates.

Put a UI placeholder somewhere in the navigation section of your Jekyll template:

<div id="search"></div>

Hook up the JS near the bottom of your html:

  <script src="/_pagefind/pagefind-ui.js" type="text/javascript"></script>
  <script>
    window.addEventListener('DOMContentLoaded', (event) => {
      new PagefindUI({ element: "#search" });
    });
  </script>
</body>
</html>

Add the pagefind css too if you want (I’ve omitted it, because I’ll style it differently at some point):

<head>
  <link href="/_pagefind/pagefind-ui.css" rel="stylesheet">

and then once you’ve built the latest version of your site with jekyll build, call pagefind, pointing it at your built root:

pagefind --source _site

The Pagefind CLI page shows you the various options you can use.

If you save the options you want in a pagefind.yml file, you can call pagefind with no options.

Here’s my pagefind.yml

force_language: en
source: _site
glob: "*[!s]/**/*.{html}"
bundle_dir: _pagefind
exclude_selectors:
  - "#links"
  - "#recent-posts"
  - "footer"

I set English as the only language and point to the Jekyll _site folder.

The glob setting is telling pagefind to index any .html file in any folder, except those that are in a folder ending with s. This is because Jekyll generates a tags directory which pagefind was indexing and causing duplicate results to appear; one from the page with the blog post on, and the duplicate entry from the tags directory.

I wrote about this in an open Pagefind issue about the glob option. It works for me because I only have the one folder tags that ends in s. If you have e.g. a cats folder that you do want pagefind to index, then this won’t work for you.

bundle_dir tells pagefind where to save its assets and search index files. exclude_selectors is a set of css selectors that I don’t want pagefind to index the content from, largely to avoid duplicate or unecessary results.

Pagefind can serve your built site if you call pagefind --serve - you can’t get Jekyll to do it, because it will overwrite your _pagefind folder. Once you’re happy with everything, publish your site to your host.