Web Dev Diaries

A blog and resource for modern web development

Migrating from WordPress to Hugo

The Lost Gardens of Heligan in Cornwall, UK, A postbox for posting letters to Santa
The Lost Gardens of Heligan in Cornwall, UK, A postbox for posting letters to Santa

It’s exactly one year ago to the day that I rebuilt my blog in WordPress, simultaneously letting go of my old alcooper.me domain and registering under my current domain webdevdiaries.com.

I’ve just moved my entire tech & data stack over to Hugo, a static site generator. It’s built with Go and is purportedly very fast.

You might have even read my first blog post wherein I explained why I moved away from my slapped-together Angular, MongoDB and React setup.

It was tempting to carry on the trend and title this post Why I ditched WordPress for Hugo. However, rather than dive too deeply into the why, I’d prefer to show you the how, because I’ve been so impressed with how easy the entire migration process was.

Why I ditc… moved away from WordPress

I didn’t publish a lot of posts last year, but it was twice as much as the year before, so I consider WordPress a success and helped me make a solid step in the right direction. It boosted my writing confidence and lifted the technical blockers that maintaining my own tech stack introduced. I also liked having access to the diverse WordPress plugin ecosystem for easily adding blogging helpers, such as Yoast for SEO tips.

What I didn’t like about WordPress though was the “lock in” to that particular means of publishing and the storage of my content (in a database). I also disliked how difficult it was to work locally on theme changes and push those changes to my shared hosting server.

In hindsight, these issues could have been lightened if I’d version-controlled my site from the start and set up database migration scripts to synchronise my production DB with a local one. And with that, a fresh set of technical hurdles to surpass!

Time for a simpler alternative

In summary, my needs/wants for my blog are now:

  • Easy writing of posts, ideally in Markdown format
  • Well-formatted & nicely styled code examples
  • Painless theme editing (my time should be spent writing, not developing)
  • Preferably, no database or scripting/infrastructure to deal with

Luckily, a solution does exist that fulfils all of these points. It comes in the form of static site generation.

Static site generators are built to take in a bunch of static files containing text (usually markdown files) and process them to output HTML and CSS. Most generator tools are also clever enough to parse data placed at the top of the files into metadata.

You can think of these static files as rows in a database. Cool, huh?

There’s a bunch of static site generation tools available now, here’s a list of the most popular ones from last year. This was the list that lead me to find Hugo.

My reason for choosing it over the rest of the options was simply because it looked the easiest to start working with. Hugo’s getting started guide made the initial installation impressively simple.

Starting the migration

The one problem anyone moving away from WordPress will face is figuring out the best way to save their posts, pages and any other custom content. I had automated DB backups running already, but going from a DB dump to markdown files was going to be a tedious process. And that didn’t include other content stored in files like images.

Thankfully, I’m not first to have made such a migration from WordPress to Hugo. Someone has in fact built a tool that automates the conversion of all important content (posts, pages, related media files like images) into a folder structure of markdown and media files that will be immediately understandable by Hugo.

Here’s the migration tool: WordPress to Hugo Exporter.

It’s a WordPress plugin, so assuming your WordPress setup is self-hosted, you just need to install it by placing the plugin contents into your wp-content/plugins folder inside its own directory, e.g. wp-content/plugins/hugo-export. You can do this using whatever means is convenient, be that via SSH/SCP or by using a tool like FileZilla to transfer the files over.

You might also need to make a small change to your php.ini file as mentioned in the plugin’s readme, but I didn’t need to (I was on a Namecheap shared hosting server).

Now it’s actually really easy to start the export. Just log in to your WordPress admin area, look under the Tools menu and click on the newly added Export to Hugo link. The first time I tried this it showed me a 500 error page, but the second time I tried it was successful and it triggered a zip file download that contained the goods.

I then extracted the zip file into my Hugo project content directory, started the blog server with the hugo server command and I was instantly able to see all my old posts and pages being served with their images in tact. Better yet, the URL paths (slugs) were all exactly as they were in WordPress.

Moving to Netlify cloud service

I also wanted to take this opportunity not only to migrate my blogging platform but my server setup, too. I’ve grown a bit tired of dealing directly with a server and would much prefer to abstract that away. Tighter integration with my blog’s version-controlled source files would also be awesome.

Remember that link to the list of static sites I mentioned earlier? That’s also what gave me the inspiration to move to a cloud service. That list was published by Netlify and after I researched what they themselves offer, I was sold.

Not only is the basic Netlify web app publishing & hosting free for personal projects that don’t need lots of bells and whistles, it can also be connected to Github. I was able to version control my Hugo site with a private Github repository, link it to Netlify and get it online way faster than any other hosting or cloud service I’ve used before. Newly pushed commits to my Git repository also trigger re-deployments in Netlify. A fantastic first-time user experience all round.

It’s also free to link a custom domain name to a Netlify app, so I did that to retain my webdevdiaries.com domain.

If you consider using Netlify I’d also recommend following their steps to create a DNS zone and add their DNS nameservers to whichever service you used to register your domain name with (Namecheap, in my case). Once Netlify sees that you’ve updated your domain service nameservers correctly, adding SSL is a matter of clicking a button. No joke, that’s all you have to do. It handles the signing & attaching of an SSL certificate to your domain.

Netlify-Hugo configuration

There’s a page in Hugo’s documentation that details getting it setting up on Netlify. They don’t give a lot of information about the required netlify.toml file you’ll need other than showing one example, but I’ve tried this out and this seems to be all that’s required for a single-environment setup:

publish = "public"
command = "hugo"

HUGO_VERSION = "0.38.1"
HUGO_ENV = "production"

All good to go!

That’s about all there is to it. I’ve glazed over a few of the more minor setup details, although those should all be fairly intuitive to work out. You don’t have to go the route of hosting on a cloud service either, but I’ve been really impressed by Netlify’s service so far and I see no reason to look elsewhere right now.

There’s obviously other stuff I haven’t mentioned, like how to build Hugo themes or configure your blog’s settings, but these are really very straightforward to do. I’d recommend finding a pre-existing Hugo theme that you like the look of and use that as a starting point. I started with the Minimo theme for its simple design and I’m looking forward to making incremental changes to it over time. The Hugo docs are also a great source of knowledge and I’ve consulted it a few times so far to look up the available “front matter” options and shortcodes for dynamic links (i.e., stuff you can add into your markdown files).

Not only am I really happy overall with how the migration went and the new static site setup I now have, but it’s also given me even more motivation to keep on writing and publishing content.

comments powered by Disqus