Using Pagefind in Micro.blog to Only Return Posts in Search Results
When I tried out Pagefind for the first time on this site, I was finding that the results were including more than just the posts, such as the post lists, the stats page, the archive page, and a bunch of other indexed pages. These were crowding out the posts themselves, and I expressed my wish for a way to control the indexing in some way.
Turns out there’s no need to modify the indexing, you can do this using Pagefind filters. This enables faceted search in that the end user can configure which pages to show in the results, based on arbitrary key-value pairs you as the site author specify in the HTML (I’m not doing a great job explaining this, please click through to the documentation to see how it works).
The way I used this to filter the results down to only post entries is by defining a “pagetype” filter. This is done by including a HTML element in the Hugo template used for posts. For those using the Card theme, this involves adding a span[data-pagefind-filter] element to the “post/single.html” template:
<!-- layouts/post/single.html -->
{{ define "main" }}
<span data-pagefind-filter="pagetype">post</span>
<main>
<!-- ... -->
</main>
{{ end }}
Doing this will enable a filter sidebar in the default search UI, which I didn’t want. So I hid that, along with the filter span itself, with a bit of CSS:
[data-pagefind-filter],
.pagefind-ui__filter-panel {
display: none !important;
}
But there still needed to be a way to enable to filter to apply it to the results. Fortunately, Pagefind has a way to control the default search UI to some degree. And the way to enable this new pagetype filter is by calling the triggerFilters methods in the bit of JavaScript initialising the UI:
<!-- /search page -->
<div id="search"></div>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
let search = new PagefindUI({
element: "#search",
showSubResults: true,
pageSize: 10,
excerptLength: 50,
autofocus: true
});
search.triggerFilters({ "pagetype": [ "post" ] });
});
</script>
After that, rebuild the site. Pagefind should run and index all the posts with the new filter, and the new filter should be applied by default, resulting in a search that only return the posts itself.
I hid the filter sidebar for now as I didn’t want it cluttering up the UI, but in time, I may bring it back. The filtering mechanism looks pretty powerful, and could be useful for things like category filtering down the line. It would also be nice to find out how to use the filter within the query string itself: I still like the idea of using the hash to filter based on category. But as it stands now, I’m very happy with the result.
EDIT: Turns out there may be an even easier way to choose what is indexed. Perusing through the documents, you can use an annotation to tell Pagefind what to index. It looks like if you make use of this annotation on a page, anything outside of it won’t be indexed (the filters and metadata still will). So the use of filters like this may not be necessary at all.