There’s a neat little tool called pagefind which allows your fully static site to have full-text search. I thought the process of integrating it here was surprisingly easy.
For context: I have an ersatz static site generator. I am writing in a markdown file right now, use pandoc
to process them into HTML, and orchestrate the whole thing with a Makefile. But none of the Pagefind integration process required touching markdown or pandoc, since it indexes the HTML output I already produce as part of my static site generator.
The quick start guide is very helpful. I just run npx -y pagefind
, passing --site out
since my website’s html files are built in the ./out
directory.
This populates ./out/pagefind
with two kinds of file:
pagefind/index/<stuff>.pf_index
and pagefind/fragment/<stuff>.pf_fragment
pagefind/pagefind-ui.js
and pagefind/pagefind-ui.css
Then, all you need to do is include the stylesheet and the Javascript file on your webpage. This code:
<link href="/pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-ui.js"></script>
<div id="loading">Loading...</div>
<div id="search"></div>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
new PagefindUI({ element: "#search", showSubResults: true });
document.getElementById("loading").remove();
;
})</script>
produces this widget:
The sample HTML on pagefind’s quick start page does not include the Loading...
element. I added it so that if the page is loading slowly or if JS is turned off, people will know something is up.
I was worried that pagefind would index the footer, so searching Back to garden entrance
would hit every page on the site. But it turns out pagefind automatically skips elements like <nav>
and <footer>
. Cool. It looks like this is the full list of automatically-skipped elements.
There are config options; you can pass a CSS selector of elements to skip, or to index exclusively. You can also pepper data-pagefind-
attributes directly into the HTML, which of course gums up the HTML a bit, but it’s easier.
This site is built with a makefile. I am very much a makefile beginner.
I added the directory $(out)/pagefind
to the all
phony rule, so that running make all
attempts to build $(out)/pagefind
. Then I added a makefile rule to create this directory by running npx -y pagefind
.
$(out)/pagefind: $(garden-outs) $(static-outs)
npx -y pagefind --site $(out)
Here garden-outs
and static-outs
are variables expanding to every HTML page generated using other rules. Pagefind needs to index these HTML files, so it can only run after they are generated.
Finally I noticed that pagefind can be a little slow. So I created another phony rule no-search
which doesn’t run pagefind. This way when I run make
locally, it will skip pagefind, but in CI (or if I just want the Pagefind JS and CSS files locally) I can run make all
.
no-search: $(garden-outs) $(static-outs)
all: no-search $(out)/pagefind
Despite the npx
, pagefind is not actually written in JS, they’re just misusing npm as a convenient distribution mechanism. You can install the binary if you want.
The pagefind quick start guide mentions a --serve
parameter. I think if you are dealing with a static site generator, you probably already have some way to serve the results locally (i have a make serve
which runs miniserve
).
As far as I know, the pagefind --serve
option is not any different from any other serving option… but it looks like some kind of “pagefind playground” is in the works. Ooh.