Adding Tipue Search to a Piecrust Blog

Background

One thing I’ve missed since my migration away from Wordpress is the lack of search. My workaround for quickly finding a particular post was to load up my archive page and do a command + f which would pull up any hits on titles and tags. This worked well enough for me, on this still growing site. However, I have other sites where an integrated search option would be very handy, especially if I concern myself with my visitors’ expectations.

Enter onethingwell.org’s fantastic curation of apps. It was OTW that first turned me on to Piecrust and it again came to the rescue with its post on Tipue Search. Tipue Search “is a site search engine jQuery plugin” that “only needs a browser that supports jQuery”. It doesn’t need a database on the backend or a large PHP, Python, Ruby, Java app powering it. Those kind of solutions are fine for much larger and dynamic sites. However, for sites like this one, they are overkill and add unnecessary overhead with no appreciable return; they’re not the right tool for the job.

Start Cooking

Tipue Search has three modes:

  • static
  • live
  • JSON

My first attempt at integrating Tipue Search with my site was by way of the “live” mode. Afterall, if I can just sit back and let it take care of all the intelligence, then all the better. As it turned out, though, live mode is not dynamic; you can’t point it at a directory and let it crawl the pages on demand. This makes sense as such a method would take longer and longer to process as a site grew. It’s fine for the type of site that has a few pages. When using it on a blog site like this one, the best I could do was to get it to search my Archive page. It would always return a hit, but that hit was the entire archive page. It wouldn’t point me to the specific post that it found. It was as good as having no search.

After I ran into that wall, I decided to just have Piecrust build a JSON file that I could point Tipue Search to with its JSON mode. This is exactly what static site generators are built to do after all.

The Solution

  1. Add the requisite Tipue Search scripts, stylesheets, and form to your default template.
  2. Create a new template, searchdata.json:

    {"title": "{{ post.title }}", "text": "{{ post.content|replace({'\n': " ", '\\': " "}) }}", "tags": "{% if post.tags %}{% for tag in post.tags %}{{ tag }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}", "loc": "{{ post.url }}"},
    
  3. Create a new page, searchdata.html, that loops through each blog post using the above template for the output.

    ---
    content_type: json
    layout: none
    posts_per_page: 9999
    single_page: true
    format: none
    posts_filters:
        not:
            has_tags: draft
    ---
    {"pages": [
        {% for post in pagination.posts %}
        {% include 'searchdata.json' %}
        {% endfor %}
        {"title": "", "text": "", "tags": "", "loc": ""}
    ]}
    
    • The null value line just after the for loop is needed to create a valid JSON file that doesn’t have a comma for the final definition line.
  4. Finally, create your search.html page which will be the landing page for your search results. Be sure to point it at the generated searchdata.json file.

    <div id="tipue_search_content">
      <div id="tipue_search_loading">
      </div>
    </div>
    
    <script>
    $(document).ready(function() {
        $('#tipue_search_input').tipuesearch({
          'mode': 'json',
          'show': 9999,
          'showURL': false,
          'contentLocation': '{{ site.root }}searchdata.json'
        });
    });
    </script>
    

Caveats

  • This process only searches blog posts. It does not search other pages you may have created, like an “about” page, etc.
  • The search will only return results matching a post’s title and tag i.e. not full text search of a post’s content. It would take a little extra work to get the {{ post.content }} formatted such that Tipue Search would accept the JSON file

This is a personal website. Unless otherwise stated, the content and opinions expressed here are my own and not those of my employer.