Well, it’s not a good blog website if you can’t search on it, right? So I decided to implement a search bar.

Search on a static website

Indexing your static site is probably the hardest part of doing search. You can either use some JS script where the client will index the site or you can index it on the server after you generate the site.

Well Pagefind is the second one. It makes our job easy, because you only need to setup a site where your search will be and then you only need to run one command to create the index.

So to deploy site with search index you can just run hugo && npx pagefind --source "public"

Here’s my source code for my search page, if you’d like to take a look:


<link href="/_pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/_pagefind/pagefind-ui.js" type="text/javascript"></script>
<div id="search"></div>

<script>
    window.addEventListener('DOMContentLoaded', (event) => {
        new PagefindUI({ element: "#search" });
    });
</script>

<style>
body {
  --pagefind-ui-primary: #eeeeee;
  --pagefind-ui-text: #eeeeee;
  --pagefind-ui-background: #152028;
  --pagefind-ui-border: #FFA86A;
  --pagefind-ui-tag: #152028;
  --pagefind-ui-font:'Fira Code'
}
</style>

raw_html shortcode

You need to encapsulate the code above into a <raw_html> shortcode or allow unsafe rendering in Hugo.

The <raw_html> shorcode is just a simple file in layouts/shortcodes. It works as if I allowed unsafe rendering in Hugo, but I can do this on demand only at the places I need it to be. Look here for more.

Pagefind

It just works great. The search is instat so it feels just as fast as the rest of the website.

The only issue I have so far is that it does not support ignoring classes or IDs. You have to specify what to ignore in your theme, which can mean that you’ll need to fork the theme and modify it that way. As I already modified the theme, it’s not that big of a burden for me, but still, it’s annoying than just specifying what classes or IDs to ignore in a config file.

But I’ve modified the theme so that it should ignore everything I need and it looks perfect.