Migrating this site from Github+Jekyll to Netlify+Hugo (with the amazing blogdown package)

When updating my blog last week, for the first time this year, I was reminded that while I have really liked being able to use Github pages combined with jekyll to build a free static blog/website, maintaining the jekyll dependencies and ensuring that I can locally build my site on a number of different computers/OSes has turned out to be a bit of a pain. Lately it has seemed that every time I go to make an update, something was broken and I would have to spend an hour or so Googling how to fix it, only to have to go through it all again when I updated from a different computer.

So, after reading through Yihui Xie’s amazing book about the equally amazing-looking blogdown package for R, I decided to take the plunge and experiment with a new site backend based on the hugo framework (since that is the default supported by the blogdown package).

This post outlines the various steps that I took to migrate the source from my old jekyll-based site hosted with Github pages to a this new version hosted with Netlify.


The great thing about switching to Hugo, is that I was able to create, modify, build, and preview the site all within R, using the blogdown package. Switching themes is a breeze, however if you want to customize the theme you choose with your own changes it isn’t necessarily as easy to just switch back and forth.

Most importantly, blogdown allows you to write your source using Rmarkdown (or plain markdown), and the build_site()/serve_site() functions automagically re-build and locally serve the site for preview while you are working. If you’re an avid RStudio user, there are also some addins and shortcuts to make new posts quickly and easily. I wasn’t as interested in this since I am primarily an Emacs/ESS user, but it’s good to know about.

Basically, I just followed the instructions in the blogdown book, and within 2 minutes I had a functioning Hugo site (not yet hosted on the internet).

Jekyll vs Hugo: themes

Hugo, like jekyll, is built on a theme. For my jekyll blog, I had been using a variant of the hyde theme that I found already modified to work with building from Rmarkdown source files (instead of the default markdown). After some searching, I discovered an equivalent hugo-version of the Hyde theme, and in particular a nice hyde variant (called, originally hyde-hyde) that retained my previous aesthetic but prettied it up quite a bit.

hyde-hyde preview

Hyde-hyde customizations

Static content on the homepage:

One thing I like about my old theme was that the homepage had both static content (i.e. an index.html as well as a preview listing of the most recent blog posts. In order to add that to my theme, I followed the instructions from Matt Mayes:

How to add a static index to the homepage

It’s worth noting that to make tweaks to a theme, you don’t have to actually modify the theme source files directly. Similarly to LaTeX, you can create a mirrored folder structure under layouts/ that will get picked up by hugo before it goes searching through the themes/hyde-hyde/layouts/ folder. This does make it harder to switch between themes, however.

Getting Mathjax to work:

The default hyde-hyde theme doesn’t work out of the box with Mathjax (used for displaying nice-looking equations based on LaTeX syntax), so I had to add it to the theme, following the instructions on Xiaolin Zeng’s site blog:

Turn on Mathjax

Making a “posts” or “Blog archive” pages:

I also wanted to have a “Blog Archive” item in the sidebar that would summarize all the blog posts. I had this for my jekyll site, and it was created by making a page and then adding a little jekyll-snippet that would find/sort/display the listing of all posts.

After a long time of searching around to see how to implement the same kind of snippet for hugo, I finally discovered that all I had to do was point the link for the page (defined in the config.toml file) at the /post/ directory, and it would automagically create the listing without anything else being defined:

Blog archive

Score one for Hugo!

Making the main column wider:

This is something that I want to do, but haven’t tried yet. When I do I’ll follow the instructions here.

Converting old Rmd source files

Thankfully, the hugo version of the site was able to build almost perfectly simply by migrating all my old Rmd source files from the jekyll site into the /content/post/ folder of the hugo site. I also had to migrate any static content (e.g. images) by making a /static/images/ folder and updating the image links in the Rmd source.

There were a few things that took a bit of updating, and in the end, because I only have a few dozen posts, I did them manually.

Changing the latex tags

For some reason the old jekyll system needed all LaTeX text to be wrapped in $$ ... $$ (i.e. double dollar signs). This was always weird to me, since regular latex uses $ ... $ for “inline” equations and $$ ... $$ for an equation environment (i.e. on its own line). Fixing this was simple (but a bit tedious).

$$ g(x) = \int_{-\infty}^{+\infty} f(x) dx $$

Cleaning up categories and tags

Something about the old jekyll site I had never quite figured out (and which had definitely gotten broken with a jekyll update at some point) was the “categories” and “tags” metadata for posts. For some reason, the two seemed to be interchangeable, but at the very least I was never able to get them to show up in the post header to make finding similar posts quick and easy. This worked out of the box with hugo/hyde-hyde, however it prompted me to go through every post and clean up/update the “categories” and “tags” for each one.

The upshot, was that I was then able to add a simple sidebar link, without anything other than a short entry in the config.toml, that provided a list of all the categories and tags:

Categories and Tags in the sidebar

One thing that I hadn’t liked about the old jekyll site (which admittedly was probably because of my own misunderstandings with jekyll) was that the permalink URL for each post included the categories field from the post yaml metadata. This was annoying because it meant if I changed (or added) categories after publishing, the URL for the post would change.

In hugo, it’s possible to configure the permalink structure explicitly, via the config.toml file. Based on the recommendation from blogdown, I am using:

permalink configuration

which constructs the post permalink as baseurl/YYYY/mm/dd/slug, where the slug is like a “short title” you can add to the post yaml. If a slug is not provided, the title field is used instead. The advantage of using a slug is that you can change the title after posting, without changing the permalink to the post.

Because of the previous issues of the categories getting mixed up into the jekyll urls, I knew that I would have a lot of broken links with the new site. An elegant solution for this (with Netlify at least) is to use a _redirects file to specify rules for redirecting old links to new ones. To start, I created only one entry (for the last post I had done, because I had just posted it to Twitter amidst a lively discussion about colormaps and accessibility, and I didn’t want the link to be immediately broken).

I’m not sure if I’ll redirect all the old posts … maybe there is a clever way of using regexes to strip the category parts of the old URLs out and forward them all at once?

Hosting on Netlify

The final piece to the blog migration was that on the advice of Yihui in the blogdown book, I switch from hosting with Github pages (using the richardsc.github.io root hosting repository) to hosting with Netlify. Netlify is free, provides the facilities to use a custom domain (e.g. “clarkrichards.org”), and will actually re-build automatically if the hugo source files are located in a Github repository. So, deploying with Netlify turned out to be very easy (I had to figure out the options to get my domain name, managed through Hover, pointed at the right place, and the right things to get https working, but it was fairly straightforward honestly).

I expect to continue to use Github pages for other things, particularly for the pkgdown websites (another great R package!) to accompany R packages.


Hugo and blogdown are great! One thing that I love is how quickly the site is rebuilt – basically, after every “save” while editing an Rmd/md, the site is already rebuilt and re-displayed (locally) by the time I switch to the browser to have a look.

Another nice thing about hugo is that the static site it builds is hostable on any web server – just drop/copy/paste the /public/ folder to a web-viewable location and you’re done.

Onward and upward with hugo!

Related Articles