<pagefind-search> Web Component
I’m a huge fan of Pagefind, the fully static search engine.
The super cool thing about Pagefind is that it does not require an application server—you can host it on GitHub pages (which I’ve done in the demo below)! I currently use Pagefind on this very web site and on 11ty.dev.
I wanted a way to control the asset loading of the component using <is-land>
so I built a small web component wrapper called <pagefind-search>
. Read more about <is-land>
usage below.
Usage
<script type="module" src="pagefind-search.js"></script>
<pagefind-search>
<!-- Fallback to DuckDuckGo search -->
<form action="https://duckduckgo.com/" method="get" style="min-height: 3.2em;"><!-- min-height to reduce CLS -->
<label>
Search for:
<input type="search" name="q" autocomplete="off" autofocus>
</label>
<!-- Put your searchable domain here -->
<input type="hidden" name="sites" value="www.zachleat.com">
<button type="submit">Search</button>
</form>
</pagefind-search>
<is-land>
Use Cases
I don’t think it makes sense to always wrap this one in <is-land>
(I don’t on my dedicated search page) but I do think that it unlocks a wider variety of user-preference user controlled lazily loaded use cases.
For example, putting the component in a dialog would lazily load the 20 kB (compressed) JavaScript bundle only when the search dialog is opened by the user.
<dialog>
<is-land on:visible>
<pagefind-search></pagefind-search>
</is-land>
</dialog>
You could do the same with <details>
too.
You could put the <pagefind-search>
instance at the bottom of your page and only load it when the user scrolls down.
Lots of possibilities here!
Dev Notes
This one has some interesting declarative/programmatic boundaries that needed to be managed.
I wanted to make it easy to alias Pagefind options as HTML attributes, so I went with the convention that any attribute that started with an _
would be passed to the Pagefind constructor:
<pagefind-search _show_images="false"></pagefind-search>
The above calls new PagefindUI({ showImages: false })
. If more options are added to Pagefind later, they’ll work with this approach without me having to make future changes.
And then for more advanced usage, there is a full escape hatch to JS with manual
initialization:
<pagefind-search manual id="my-search"></pagefind-search>
<!-- type="module" is important here -->
<script type="module">
let el = document.querySelector("#my-search");
await el.pagefind({ showImages: false });
// `el.pagefindUI` to access the PagefindUI instance.
</script>
I also added a little pagefind-autofocus
attribute to autofocus to the form element after it has initialized. As the native autofocus
can be applied to any HTML element (think contenteditable
), I went with the safer pagefind-
prefixed attribute name.
<pagefind-search pagefind-autofocus></pagefind-search>
8 Comments
Hawk Ticehurst
@zachleat Woah TIL about Pagefind ????
Zach Leatherman
@hawkticehurst yeah!! It’s awesome! I forgot to plug maybe the most impressive use of pagefind that I have: https://www.zachleat.com/twitter/static search of 46,000 pages ???? zachleat’s Twitter Archive
Hawk Ticehurst
@zachleat Wildddddd. This is so cool! Like, *of course*.. why *wouldn’t* you index your statically built files to create a low bandwidth search engine for your websites??
Zach Leatherman
@hawkticehurst (as always I’m gonna cc the brainchild of pagefind @bglw)
Nicolas Hoizey
@zachleat “I currently use Pagefind on this very web site and on 11ty.dev.” -> also in your Tweetback! ????
Zach Leatherman
@nhoizey haha yes, I forgot to include that one ???? https://fediverse.zachleat.com/@zachleat/111505839545250260
Christian Engel
A web component wrapper for Pagefind, the fully static search engine. I definitely have to try this one out! ????
Zach Leatherman :verify:
@mstrkapowski great!