Fast, keyboard-optimized search for Hugo

Hi All —

I forked some of the work of Eddie Webb and Matthew Daly’s search explorations to build a fuse.js-based, keyboard-first, super-quick, light-as-possible client-side search for Hugo.

To see it in action, go to craigmod.com and press CMD-/ and start typing.


Fast Search


I believe Fast Software is the Best Software and built this with that in mind. This method was highly inspired by Sublime Text’s CMD-P/CMD-shift-P method of opening files / using functions.

The core precepts of this exploration were:

  • Minimal / zero external dependencies (no jQuery)
  • Smallest possible size added to each page
  • json index only delivered when needed (further minimizing overall impact on page speed / user experience)
  • Keyboard friendly, instant navigation (ala Alfred / macOS Spotlight)

As Eddie Webb points out, this method has the additional benefits of:

  • No NPM, grunt, etc
  • No additional build time steps, just hugo as you would normally
  • Easy to swap out choice of client side search tools, anything that can use a json index

I put up a gist with all the bits and pieces. I an by no means a javascript expert, so please, clean up as you see fit:


Hope you find this as useful as I do.

Thanks to everyone for the great software and community.

C

Very nice, but I had problems to use it. Firefox on Windows does not support the event.metaKey and if you are not on a US keyboard the slash is not on event.which 191. It’s better to use event.key or event.code. This would make your code and website more universal.

Wonderful, please fork the gist and make any changes you think would increase compatibility.

What’s the license?

Just added an MIT license, which I think is the most permissive? I.e., use at will in whatever way desired.

Love your design philosophy. How do I make your website search work on my ipad?

I tried fuse.js for search, but it bogs down once you have thousands of pages and a 1.7MB compressed index file. I ended up switching to FlexSearch.js. Search page is here, you can see the glue code uncompressed here.

I haven’t tested it but assume (?!) Safari on iPad triggers keyboard similarly to desktop? As for touch-only, you could add a “search button” to the top menu triggering this loop when focus is activated by touch:

if (event.metaKey && event.which === 191) {
      // Load json search index if first time invoking search
      // Means we don't load json unless searches are going to happen; keep user payload small unless needed
      if(firstRun) {
        loadSearch(); // loads our json data and builds fuse.js search index
        firstRun = false; // let's never do this again
      }

      // Toggle visibility of search box
      if (!searchVisible) {
        document.getElementById("fastSearch").style.visibility = "visible"; // show search box
        document.getElementById("searchInput").focus(); // put focus in input box so you can just start typing
        searchVisible = true; // search visible
      }
      else {
        document.getElementById("fastSearch").style.visibility = "hidden"; // hide search box
        document.activeElement.blur(); // remove focus from search box 
        searchVisible = false; // search not visible
      }
  }

Very cool.

If I add fulltext to my index it also balloons up to a couple MB. More than Fuse performance, I was concerned about speed of payload delivery. In the end, Titles + meta-desc + first-paragraph seems to get me 99% of the way towards extracting full-utility but at 1/10 the payload size.

FlexSearch looks brilliant though.