This content originally appeared on dbushell.com and was authored by dbushell.com
My website has been static since — checks new search index — at least July 2014!
I’ve gone through so many static site generators and custom build scripts I’ve lost track. In that time I’ve amassed quite a big blog. Finding old articles has become harder than it should be. I need search.
Finding Pagefind
Because my website is “serverless”† I have to implement client-side search. That means JavaScript. That means probably not a database and certainly not a multi-megabyte index of any kind. I could easily roll my own fuzzy JavaScript search but I can’t ship all the content required to the front-end.
† “Serverless” is such a dumb word.
First I found Tinysearch which is a Rust app that compiles WASM. I tested it on my blog content and it generated an impressively small payload. The downside is that Tinysearch is limited to entire words. A search for “rasp” will not match “Raspberry”.
I asked around on social media and Dan Burzo was the first to suggest Pagefind. Pagefind also involves Rust & WASM and works with any static build output. For my website I’m restricting it to my blog with --glob
config.
npx pagefind --site "build" --glob "<[0-9]:4>/**/*.html" --root-selector "main"
I also configured the root selector to only index content inside a <main>
element.
Fallback
Paul Robert Lloyd suggested the clever fallback of directing the form action
to a privacy respecting search engine. This is done by coding the search form something like:
<form role="search" action="https://duckduckgo.com" method="GET">
<label for="search-for">Search for</label>
<input id="search-for" type="search" name="q">
<input type="hidden" name="sites" value="dbushell.com">
<button type="submit">Search</button>
</form>
If progressive enhancement fails — there are many reasons why — the form is still functional. The trick is the hidden input named sites
which allows us to restrict the DuckDuckGo query to a specific domain. I’m not aware of other search engines that support such a query parameter.
In my final code I’ve opted to wrap my <form>
and results in <search>
which negates the need for role="search"
. I also wrapped the <search>
in a <search-form>
custom element.
Web Component
At this stage I found Zach Leatherman had already built a Pagefind Search Web Component. Pagefind comes with a default UI and Zach’s component uses this for a drop-in search feature. It doesn’t get much easier!
I’m using Pagefind’s search API to generate custom UI. In my custom element callback I defer the Pagefind setup until after the search input is first focused:
connectedCallback() {
const input = this.querySelector("input[type='search']");
input.addEventListener("focus", () => {
/* Setup Pagefind... */
}, { once: true });
}
This prevents around 100 KBs from the initial page load that may never be downloaded.
I’ve merged my new search feature into my existing latest blog posts in the sidebar (footer on mobile). It’s not a prominent feature. If I ever redesign my website I’ll make more effort. Search results replace the latest posts or vice versa if the search is empty.
This is how it looks in action:

That’s if it’s working. I’m still messing around. It will be a little unstable for a while! I haven’t tweaked any Pagefind options yet. The default sorting algorithm seems good enough.
Anyway, thanks to everyone who recommended Pagefind. It only takes a second to generate a new static index so I can append that to my build script. I’ve yet to tidy up the technical debt from my build script addition last week 😬. I’ve been working on some pre-deployment tests but those are run manually for now.
Immediate update: as prophesied my progressive enhancement failed! It should be fixed now. My content security policy header required the wasm-unsafe-eval
directive. Without this “WebAssembly is blocked from loading and executing on the page”.
This content originally appeared on dbushell.com and was authored by dbushell.com

dbushell.com | Sciencx (2024-11-21T10:00:00+00:00) Static Search with Pagefind. Retrieved from https://www.scien.cx/2024/11/21/static-search-with-pagefind/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.