Add high-performance search to static sites with PageFind
Pagefind is a fantastic addition to static site search tools. With very little configuration, it quickly indexes a static build and gives you instant-updating, filterable search. Use the default UI on a search page or, as on this site, build it into a modal. It’s small (as of this writing, just over 2KB minified and gzipped). It has many configuration options, and the maintainer is responsive and open to new ideas. And it has a nice dev mode, running on localhost
.
Read Next
I first used Pagefind in Starlight. Check out Comparing docs site builders: VuePress vs Starlight
Here’s everything needed to get going.
Contents
Installation
Install the pagefind
package.
Note
The examples here use pnpm
. npm run
and yarn
should work, but I have not tested them.
and add the Pagefind CSS and JS to your site.
Indexing and serving
Add scripts to package.json
. Many ways to factor these. I do as below, where build:site
is the framework’s build script. Note that Pagefind indexes a local build, so you’ll need to generate one first, and when changing the site source you may need to stop and rerun the dev script. (Replace the ALL CAPS text with your real content.)
Add a search box
Tell Pagefind how to scrape your content
Pagefind works well out of the box. If search hits aren’t showing the correct heading, summary, or image, fine tune things with data-pagefind-*
attributes.
-
Heading
Usedata-pagefind-meta="heading"
to manually specify the heading. Here I assume the heading is visible on the indexed page, but it doesn’t have to be — see the Pagefind docs for alternative approaches. -
Thumbnail
Usedata-pagefind-meta="image[some-attribute], image_alt[some-other-attribute]"
to manually specify the image used by search hits. Here I assume the image you want to show in in the search UI is visible on the indexed page, but it doesn’t have to be — see the Pagefind docs for alternative approaches. -
Excerpt
Usedata-pagefind-body
to manually set a container for Pagefind to index inside of. (Pagefind will still respectdata-pagefind-*
attributes outside of this container.) Usedata-pagefind-ignore
to specify content Pagefind should not index.
Putting those together, you might get a page structure similar to this. The highlighted lines are indexed.
Add filters to the default Pagefind UI
If your markup has a data-pagefind-filter
attribute, the default Pagefind adds a filter pane to the default search UI, with filters grouped into collapsible groups.
With the following markup, Pagefind’s default search UI will have a filter pane with two collapsible filter groups, “Author” and “Tags”.
Filters do not have to be visible on the page. One way of indexing filters which do not show on the indexed page’s front end is to use the data-pagefind-filter="name[attribute]"
pattern:
Another is to use hidden
:
See the Pagefind docs for more.
You can see Pagefind in action on this site by clicking “search” in the desktop sidebar or mobile header.
Articles You Might Enjoy
-
-
Accessible CSS-Only Light/Dark Toggles (with JS persistence as progressive enhancement)
CSS’s
:has()
can obviate JS -
Watch for specific added nodes with MutationObserver
MutationObserver makes it easy to watch for the addition of specific nodes, if you know where to drill.