A few days ago Soft Skills: The software developer's life manual reminded me that blogging is a Good Thing ™, so I cloned the old repository. First things first, let's upgrade Octopress! Since I last looked, Octopress received a major version upgrade from version 2 to 3. That's good, the post detailing the release is really promising. It didn't, on the other hand, receive a migration guide. That's less good. After looking around the interwebz and finding several articles about moving from Octopress to Jekyll, I also decided to take the leap. Here are some learnings not covered or not detailed in those articles.

Side-note: if you ever wonder whether you should switch from tech X to tech Y, searching for "X to Y" is a good first place to look. Make sure to also search for "Y to X", you want to keep bias out of your data. These hits usually provide stories and reasonings for the switch. Similarly, hits for "X vs Y" (and "Y vs X") usually provide good pro-con comparisons. Google Trends is another good input; just don't forget to look at trends as well as the current state.

The source of this blog is available at https://github.com/abesto/blog, so if you want to see more context, feel free to go there and look around.

Code highlighting vs excerpts

Just for the record: if you want to use GitHub-style code highlighting in Markdown, you need to add this line to _config.yml:

markdown: redcarpet

The first thing I encountered after copying over the _posts directory was that jekyll serve blew up with this unfriendly error message:

  Liquid Exception: highlight tag was never closed in _posts/2015-06-11-octopress-2-to-jekyll.md/#excerpt
  jekyll 2.5.3 | Error:  highlight tag was never closed

Around an hour of frantic searching turned up Jekyll issue #1401, which basically says that if you don't have an excerpt_separator configured, then Jekyll will use the first paragraph as the excerpt. Unfortunately whatever code extracts the first paragraph doesn't consider that there may be unclosed tags, so from the post

---
---
{% highlight c %}

{%endhighlight %}

the extracted excerpt is:

{% highlight c %}

Which of course fails with the error message we saw above. Two ways to work around this, which are nice to do anyway:

  • add excerpt_separator: '<!-- more -->' to _config.yml. You can now add the string <!-- more --> to the source of your post to fine-tune where the excerpt should end.
  • use the GitHub way (```) of marking up code listings

Embedding Disqus

Adding the embed code is as simple as it gets; you can just open up _layouts/post.html, and add the snippet provided by Disqus. See also the instructions provided by Disqus themselves. If you want to get a bit more fancy to keep the layout cleaner, you can create _includes/disqus.html, use a config variable for the Disqus shortname, and just include the snippet in _layouts/post.html.

_includes/disqus.html

{% if site.disqus_shortname %}
  <div id="disqus_thread"></div>
  <script type="text/javascript">
          var disqus_shortname = '{{ site.disqus_shortname }}';
          (function() {
                  var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
                  dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
                  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
          })();
  </script>
  <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
{% endif %}

Note that to display the above code listing, I had to wrap it with {% raw %} to keep Liquid from interpolating values like {{ page.title }}.

_config.yml

# ...
disqus_shortname: abestoswoes
# ...

_layouts/post.html

<!-- ... -->
<h1>Comments</h1>
{% include "disqus.html" %}
<!-- ... -->

Migrating Disqus (trailing /)

In my setup the migration changed the URL scheme in one tiny detail: there is now a trailing slash. Unfortunately this caused the Disqus conversations to be effectively lost. Luckily Disqus provides documentation for how to migrate when URLs or even domains change. In my case it turned out that the old (/-less) URLs redirect to the new URLs, so I could just run the Redirect Crawler. One click, and all the discussions are back in place. Great experience.

Embedding Google Analytics

I used the very same approach as for Disqus:

_includes/google_analytics.html

{% if site.google_analytics_tracking_id %}
  <script type="text/javascript">
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', '{{ site.google_analytics_tracking_id }}']);
    _gaq.push(['_trackPageview']);

    (function() {
      var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
      ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();
  </script>
{% endif %}

_config.yml

# ...
google_analytics_tracking_id: UA-17390698-2
# ...

_includes/head.html

<!-- ... -->
  {% include google_analytics.html %}
<!-- ... -->

Sitemap and RSS feed

For sitemap generation, the sitemap_generator plugin provides a great and simple solution; just drop the .rb file into your _plugins directory. Of course there's the question of automating the sitemap submission when it changes, which ties into automating deployment of a Jekyll blog; that's a story for another time.

For the RSS feed, I wanted to keep the URL I had previously, namely /atom.xml. Jekyll initializes the project with the RSS feed at /feed.xml. The solution is deceptively simple; I looked for configuration variables to tweak for several minutes before realizing that there's an actual feed.xml file in the root of the project that I can just rename to atom.xml. The filename is referenced in three places, they need to be updated: in the .xml file itself, in index.html and _includes/head.html. (I actually forgot to do that until I wrote about it in this post)

In conclusion

I like how much cleaner the repository is with Jekyll compared to Octopress 2. To be fair, that's one of the main concerns Octopress 3 addresses. I also prefer the default Jekyll template to the Octopress one; not that that's a huge argument. All that's left now is to write some more content that's not about the blog itself.

Happy blogging!