Migrating From Wordpress to Hugo

Published by Christian Mohn · Read in about 4 min (754 words)

Migrating From Wordpress to Hugo
aka The Long and Winding Road

When I decided to move away from Wordpress and over to Hugo, I really had no concept of the amount of work it would be. Simply put; I just decided to do it — without really knowing what I set out to do.

Once I had decided on a foundation theme, I chose the Hugo Bootstrap Premium as my starting point, the real work started.

The first challenge I had, was to get all the existing content moved over to Hugo. Hugo is entirely Markdown based, which ment I would have to find a way to export all the Wordpress posts in a format that Hugo could work with. After trying several Wordpress based plugins, that really didn’t get the job done, either because the plugin itself had issues or that my hosting providers setup didn’t match the requirements (or timed out while trying).

In the end, I decided to give Exitwp a try. In essence, Exitwp works with a “normal” Wordpress XML export, which meant that I could do an export, and then work with the exported data locally (for details, check the documentation). Exitwp is designed for use with Jekyll, it works perfectly fine with Hugo as well.

Basically what Exitwp does is to convert the existing Wordpress posts into Markdown files, with the publish date and post title as the filename (example: 2018-01-29-bootbank-cannot-be-found-at-path.md)

This created a great foundation, as all the existing posts where now converted to Markdown, with existing metadata in the Front Matter.

After conversion, my posts Front Matter looked like this example:

author: cmohn
comments: true
date: 2018-01-29 22:49:53+00:00
layout: post
slug: bootbank-cannot-be-found-at-path
title: Alerting on "Bootbank cannot be found at path ‘/bootbank’" in vRealize Operations
url: /vmware-2/bootbank-cannot-be-found-at-path/
wordpress_id: 4963
- VMware
- Alerting

Great! The url: parameter there is fantastic, as it means that old URLs would still work as before, even Hugo generates a new URL for them, with my preferred /:year/:month/:day/:filename/ format (because I believe easiliy accessible date information is pretty crucial). Win! Also, note how easy it is to have multiple URLs pointing to one post in Hugo! Also, if you want more, there is always the Alias: parameter.

I then did a quick Search and Replace in all the files, replacing cmohn with Christian Mohn. I don’t really need the comments or wordpress_id metadata there anymore, but there’s really no harm in it being there, so I left them.

Once that was done, I copied all my posts from the Exitwp conversion directory, to my Hugo /content/posts directory and all my posts showed up in Hugo locally! Awesome!

Everything looked OK, until I realized that all the image references were pointing to the existing absolute URL, which worked fine locally (as they pointed to the still running Wordpress site when I ran the local Hugo server) but that would break spectacularly once once I pointed the domain to the new location. I’m glad I caught that one before cutting over the domain! Sadly this was a real pain to fix, due to the following issues:

  • My general non-proficiency in regexp.

  • Wordpress is kind of stupid when it comes to uploads as it places uploaded files into wp-content/uploads/{year}/{month}/{filename}.

This made it hard to do a general search and replace for all the image references, so I pretty much went through each end every post fixing and cleaning up the image URLs.

Once that was done, I also noticed that there was quite a lot of other Wordpress specific things I needed to clean up. All posts I had with code snippets in them needed to be fixed, as they were littered with Wordpress Plugin specific code tags. All posts that had images with captions also needed deletion cleanup, any Wordpress galleries as well as all embeds that I had (Twitter, Youtube etc.)

The next thing I did was to go parse through the image files in my /img/ folder, and optimize them. I used jpegoptim and optipng to accomplish that:

jpegoptim #

find . -name "*.jpg" -exec jpegoptim -m80 -o -p --strip-all {} \;

optipng #

find . -name "*.png" -exec optipng -o7 {} \;

By running this on my new img directory, which took quite a while on a total of >2.5k files, I got a reduction of ~47 % or 187 MB, from 393,9 MB to 206,6 MB, without any noticeable quality degradation.

And that just about covers it, my Wordpress to Hugo migration, a short story long.

Post last updated on January 2, 2024: Add author


vNinja.net is the digital home of Christian Mohn and Stine Elise Larsen.

The primary focus is on IT architecture and data center technologies like virtualization and related topics, but other content also pops up from time to time.