You may or may not know that this site is built using Jekyll, a static site generator. That means there’s no database, so page load speed is much faster.

Without a database though, there’s nothing to query when needed, i.e. when wanting a search function, so I went about building a work around.

With the Liquid templating language, used by Jekyll, I built a JSON encoded feed for posts and pages on the site which I wanted to show up in search results.

[
    {
        "title": "{{ post.title }}",
        "content": "{{ post.content | markdownify | strip_html }}",
        "link": "{{ site.url }}{{ post.url }}",
        "date": "{{ post.date }}",
        "excerpt": "{{ post.snippet }}"
    }
    ...
]

I then wrote a Javascript plugin which receives a search term, either from a querystring or a form submission, and looks for the term within the JSON feed.

With this data, it’s pretty simple to output the results directly into the DOM using a template partial.

Jekyll search

That’s it explained in it’s simplest form anyway. Try it out for yourself over on the search page and let me know what you think.

If you’re interested in exactly how I’ve gone about this, you’re in luck. It’s definitely not perfect yet, but, regardless, I have released the code on GitHub so other Jekyll users can use it, alter it, even improve on it.

There are a few things things I’d like to fix/tidy up in the future, like:

  • The JSON feed isn’t very ‘pretty’ - I know this isn’t important, but I’m all for well-formed markup.
  • Date formatting would be nice. - I’ve done this on this site myself by tweaking the Javascript file, but it’s not ideal to force people to use my date formatting, so it’s not in the repo.
  • Make the script into a jQuery plugin - This would make it possible to customise your search function without having to change the plugin itself.

Update

Thanks to this pull request from Marcel van der Boom I now escape JSON using the ruby ‘json’ gem.

To do this, Marcel added a plugin which registers a filter:

require 'json'

module JsonFilter
  def json(input)
    input.to_json
  end

  Liquid::Template.register_filter self
end

After that, he uses that filter to escape the JSON, removing the need for quotes in the Liquid template and ensuring special characters don’t cause any errors.

[
    {
        "title": {{ post.title | json }},
        "content": {{ post.content | markdownify | strip_html | json }},
        "link": "{{ site.url }}{{ post.url }}",
        "date": {{ post.date | json }},
        "excerpt": {{ post.snippet | json }}
    }
    ...
]