Jekyll to Jigsaw

Main Thread • 5 min read

All these year in review and New Year's resolutions got me motivated. I decided use it to complete one of my own goals for the year - redesign blog. This was more or less an impromptu hackathon, which I time boxed to 4 hours to ensure I didn't go down the rabbit hole of intricately redesigning everything.

This would be a simple facelift to modernize the template with a focus on copy, as well as a conversion of the static site generator. I decided to refactor my blog to Jigsaw. So this serves as not only my first article to christen the conversion, but also a review of the process.

Why JigSaw

My blog has been around for over a decade. I can't tell you how many times it's been converted. It originally started as static HTML, then WordPress, then Jekyll, then GitHub Pages, then Ghost, then back to Jekyll. And now, of course, Jigsaw.

Historically I used this as an opportunity to try new tech stacks. Nowadays, this is rather impractical for a few reasons.

  1. A blog doesn't really push technical boundaries. So while it may serve as an introduction, it's not going to substantiate its use for other things.
  2. My time is better spent elsewhere. If it's not a good learning opportunity, just go with something familiar. Jigsaw has a PHP core and leverages Laravel Blade templates engine. It also included a starter template developed with TailwindCSS and a little Vue.js.
  3. Both of these combined bring me to my final reason of convenience. Writing blog post is hard enough already, I don't want anything to make it harder. While Jigsaw allows me to use Blade, I can continue to use Markdown.

In the end, for me, Jigsaw balanced my time by being convenient to work with (PHP + Blade + Markdown) while still giving me some light learning opportunities (TailwindCSS + Vue.js).

Converting front matter

Although front matter is pretty straightforward, I created a lot custom keys over the years while transitioning between all the static generators. So I wrote a quick script to condense these down (and reformat) to the minimal amount of: title, description, date, categories, and a few SEO keys.

Here's a Gist of the conversion script I wrote.

Rewriting URLs

Another motivation for this redesign was to finally switch to jasonmccreary.me. I purchased this domain a while back, but had not made it primary. Since I was going to change the link structure for each of my posts anyway, I took the opportunity to do both.

The key thing was ensuring my URLs redirected so I didn't lose my search engine rankings. I made sure to switch the proper settings in Google Search Console and Google Analytics, as well as generating 301 redirects for each post. There was also some tweaks to the Jigsaw config and template to ensure generated URLs consistently included the trailing slash.

Here's a gist of these scripts to convert the Jekyll posts dated filenames to the dasherized Jigsaw post filenames and generate the 301 redirects.

Tweaking categories

For the most part Jigsaw was a straight conversion. The only thing that took a minute was configuring the categories. The documentation was a bit light on how these are set up (possible open source contribution…). Again since I was familiar with PHP and Blade, it wasn't too hard to dig around the code and figure it out.

Initially, it wasn't automatically generating the category pages (or collections). Ultimately, there is an source/_categories folder within the start template where I needed to create markdown files for each of my categories.

That wasn't quite it though. The categories closure in config.php also needed some tweaks. Especially since my category names were titles and contained spaces. I had two options, I could add code to generate the lowercase, dasherized URLs in the template or I could do so at build time.

Inline with my goal to keep the writing experience easy, I preferred to generate these properly at build time. So I changed the config to lowercase and dasherize the categories names from the front matter and properly group the posts. Here's the specific code as well as a Gist of the complete config.php.

1'posts' => function ($page, $allPosts) {
2 return $allPosts->filter(function ($post) use ($page) {
3 $category = str_replace('-', ' ', title_case($page->getFilename()));
4 return $post->categories ? in_array($category, $post->categories, true) : false;
5 });
6}

Adding Read Time

Jigsaw also has fancy helper methods. This is pretty nice as it was a pain to customize such things and Jekyll - often requiring overriding or monkey patching in Ruby. With Jigsaw I simply add a closure in config.php and can reference it through the $page object just like I do the front matter.

This made it super easy to create something I wanted to add to my articles for a while - Read Time. It's a nice little UX hack to see an estimate of the time it will take you to read an article. I derived the formula from some of these calculations. Here's the specific code and also in the Gist of the complete config.php. I simply call $post->readTime() within my templates.

1'readTime' => function($page) {
2 return intval(round(str_word_count(strip_tags($page->getContent())) / 200));
3}

All in all it took about 4 hours for the conversion. 2 hours were massaging the front matter, and another hour was battling the category configuration. So, in fairness, it really only took about an hour to set up Jigsaw using the starter template and begin customizing.

I plan to revisit the design, especially after reading Refactoring UI and incorporate pages for my various products and services. I like doing a little bit each time I write an article. I'll write a post and spend 15 minutes making other tweaks. So well I wouldn't call it done, I will check the box for my first 2019 goal of 2019 two redesign my blog.

Have more questions about Jigsaw? Ask me on Twitter. I'm glad to answer and considering packaging up some of my customizations or contributing them to the starter template.