Gavin Wray

Migrating 'The Perfect Twang' from WordPress to Hugo

Learning a blog platform other than WordPress has been on my mind for a while. I’ve worked with WordPress sites as an author, editor or general maintenance man for ten years now. It’s time to try something new.

I researched static site generators and chose to learn Hugo. Aside from learning a new technology, another reason for moving the blog to a static site generator is that my WordPress sites are so slow.

After a steep learning curve, I migrated my music blog The Perfect Twang from WordPress to Hugo. [Edited 6 October 2019: this blog is now on]

This post summarises what I’ve learned so far. For more detailed guides, try reading:

Installation and set-up

Installing Hugo on my Mac was the most difficult part of the migration. This is mainly due to my lack of skills with a command line and Mac permissions! While the Hugo installation instructions are short and clear, I hit permissions problems in Terminal, which took some research to figure out.

Once I resolved these niggles, I found it straightforward to get a vanilla site up and running. Win!

Content review

I used Ben Balter’s WordPress to Jekyll plugin to export my blog posts as Markdown files, which contained tags, categories and other metadata. The export includes a copy of the /wp-content folder, which contains images or other uploads related to posts and pages.

Reviewing the content is where I spent the bulk of my time. This involved:

  • fixing instances in Markdown files where symbols had changed to HTML entities, such as apostrophes or quotation marks
  • replacing absolute image paths containing WordPress’ /wp-content/uploads/etc to be relative to Hugo’s /static directory
  • understanding where to store images and other media files referenced by posts. (There’s extensive discussion on GitHub.) I settled on recreating WordPress’ uploads structure of /year/month/myimage.jpg under my Hugo site’s /static/media directory
  • understanding how to recreate WordPress’ permalink structure via Hugo’s config settings to avoid having to implement any URL redirection or risk losing PageRank

Theme and design

There are plenty of themes available for Hugo sites. I chose the Icarus theme by Zhang Ruipeng and Digitalcraftsman for two reasons:

  • you can include featured images with posts (known as ‘banners’ in Icarus)
  • there’s a consistent-looking archives page that includes featured images

I customised the theme with an override stylesheet to improve the following aspects:

  • contrast in the typography to meet WCAG level AA.
  • navigation on small screens, particularly at 400px wide
  • post titles in archive pages on small screens

There’s still work to do to be fully compliant with WCAG level AA but the major elements now pass.


When the site is ready on your local computer, you type hugo in the command line to generate all the site files in the /public directory. You then upload the /public directory to the web server.

When you write a new post, you need to regenerate the site and upload the entire directory of site files to your web server. My Perfect Twang blog of 20-something posts is 11 MB when compiled in Hugo. Via my Virgin Media broadband connection, this takes about 20 minutes to upload via FTP to DreamHost. Already, uploading by FTP has become a timesink, particularly when making small changes such as fixing a typo or publishing a new post.

Next on my Hugo to-do list is to find a more efficient way to track and deploy changes to the live web server.


I’m happy with Hugo in this area. With no queries or round trip to a database like WordPress requires (Hugo sites are simple, static html pages) there’s a significant improvement.

The following table compares performance of the home page before and after the move to Hugo:

Measurement Before (WordPress) After (Hugo)
Load time 1.33s 703ms
Requests 65 28
Pingdom performance grade 69/100 86/100
Page size 1.2mb 727kb
YSlow grade C B
YSlow performance score 78 82

Content © 2021 Gavin Wray
Athena Jekyll theme by Diana Mounter

Twitter · LinkedIn · SoundCloud · GitHub