Static Blog Search with Awesomplete

This is a post about developing my blog on my blog - take a second to appreciate how meta that is.

I recently transitioned my personal site from Wordpress to a static site on Github pages built using Middleman. Overall it was an awesome change and I feel much better having my personal site and assets etc in plain text and source control. The transition was pretty smooth however there were a few things that I had with Wordpress that took a bit of finesse to achieve with Middleman. Blog search was one of those things and I eventually came up with a pretty elegant solution that I would like to share.

The reason search is interesting is because Middleman generates static sites which means any search solution needs to be entirely client side. If you google for Middleman search you’ll find some other projects and gems but I think my solution is simpler.

I built my blog search using this nice little autocomplete library called Awesomplete. To start I added the following markup to the sidebar partial which is rendered on all the blog sections of my website:

<input id="search" class="form-control" list="articleList" placeholder="Search...">
<datalist id="articleList">
  <% blog.articles.each do |article| %>
    <option><%= article.title %></option>
  <% end %>
</datalist>

This creates the base list of all my blog articles. Now we need to bring it to life with Awesomplete:

  var input = $("#search")[0];
  var awesomplete = new Awesomplete(input, {
    minChars: 1,
    maxItems: 5,
    autoFirst: true
  });

  var searchIdx = {
    <% blog.articles.each do |article| %>
      <%= article.title.to_json %>: "<%= article.url %>",
    <% end %>
  }

  window.addEventListener("awesomplete-selectcomplete", function(e) {
    var articleTitle = $(e.target).val();
    var articleUrl = searchIdx[articleTitle];
    Turbolinks.visit(articleUrl);
  });

This code does a couple of things - first it initializes the Awesomplete widget. Next it defines a searchIdx variable which just maps article title to url and stores it in javascript land so we can access it later. The last bit of code listens to the awesomplete-selectcomplete event then looks up the url for the selected article and then loads the page with Turbolinks (if you’re not familiar this is just a slicker way of doing window.location = ).

I was really happy with how this turned out, super fast, simple and the code is nicely contained in my sidebar partial. Give it a try in the search box to the right!