A step-by-step guide on migrating from WordPress to Hugo

Image of Mattias Geniar

Mattias Geniar, November 12, 2019

Follow me on Twitter as @mattiasgeniar

I just finished the last bits of migration for this site. It involved moving my podcasts from the podcast.sysca.st domain to a dedicated overview on this site.

In this post, I’ve documented all the steps I took to migrate from that WordPress system to this installation of Hugo.

Installation of Hugo

You’ll need to install Hugo first. Their docs cover that pretty well.

The hugo binary is what will generate the static HTML from the markdown & template files we will use later on.

Export your WordPress data to a Hugo format

Hugo uses markdown files to store its content. Everything is in flat files.

First, install the SchumacherFM/wordpress-to-hugo-exporter plugin. It isn’t available in the search in WordPress itself, you’ll have to download & install it.

  1. In their git repo, download the plugin as a ZIP file
  2. Go to your WordPress, Plugins > Add New
  3. Pick Upload Plugin and choose the ZIP file you just downloaded
  4. Activate the plugin after installation

Once the plugin is installed, you can try to go to Tools > Export to Hugo. That page might take a while to load.

If that works, you’ll be presented with a ZIP file that contains:

  • All your posts & pages
  • All your uploaded files (/wp-content/*)

However, it might fail. If your site is too large, the creation of that ZIP fails and you’ll have to try via CLI. SSH into your server to get started.

Note: if you can’t SSH, ask your host to do this for you.

$ cd wp-content/plugins/wordpress-to-hugo-exporter-master/
$ php hugo-export-cli.php
This is your file!
/tmp/wp-hugo.zip

This’ll take a while, too.

Now you have a ZIP file with all your site content (which serves as a pretty good backup).

$ ls -alh /tmp/wp-hugo.zip
294M Nov  9 07:25 /tmp/wp-hugo.zip

Now download and extract that to your local machine.

Exporting custom data types in WordPress

By default, the plugin above will export posts & pages. If you have custom post types, you’ll have to modify the export ever so slightly.

To do so, open and edit the file hugo-export.php. Around line 100 you’ll find a query like this one:

<?php

return $wpdb->get_col("
  SELECT ID FROM $wpdb->posts
  WHERE post_status in (
    'publish',
    'draft',
    'private'
  )
  AND post_type IN (
    'post',
    'page'
  )
");

In my case, I had a custom post type for the podcasts. I changed the query to this:

<?php

return $wpdb->get_col("
  SELECT ID FROM $wpdb->posts
  WHERE post_status in (
    'publish',
    'draft',
    'private'
  )
  AND post_type IN (
    'post',
    'page',
    'podcast'
  )
");

Run the export again and you’ll find all custom posts exported in the posts/ directory. More on that below.

Exploring the exported data

Once unzipped, you’ll find a directory structure like this.

config.yaml
posts/
 \_ 2016-08-01-episode-1.md
 \_ 2016-08-02-episode-2.md
 \_ 2016-08-03-episode-3.md
preparing-guest-syscast/
 \_ index.md
wp-content/
 \_ uploads/
   \_ 2017/
   \_ 2018/

There’s a general config.yaml with the meta data of your site (like title, description etc.) and an export of all the posts and pages you had.

Now that you have all data exported, you can begin using this in hugo.

Using your WordPress data in Hugo

Start by creating a new Hugo project.

$ hugo new site mysite
$ cd mysite

This’ll create a new hugo site with all the required directories. Now, copy your exported data into it.

$ cp -r /path/to/hugo-export/ content/

In other words: copy all the directories from the export into your content directory in Hugo. The end result should look something like this.

$ ls -alh
archetypes/
content/
 \_ posts/
   \_ 2016-08-01-episode-1.md
   \_ 2016-08-02-episode-2.md
   \_ 2016-08-03-episode-3.md
 \_ preparing-guest-syscast/
   \_ index.md
 \_ wp-content/
   \_ uploads/
     \_ 2017/
     \_ 2018/
data/
layouts/
[...]

Now, for testing, apply a default theme to Hugo and watch it go.

$ git init
$ git submodule add https://github.com/budparr/gohugo-theme-ananke.git themes/ananke
$ echo 'theme = "ananke"' >> config.toml
$ hugo server -D

That last command will start a local Hugo server and you can browse to http://localhost:1313/ to view your site.

You’ve moved all data from WordPress to a local Hugo install. It’s up to you now to find or create a good theme. 😉



Want to subscribe to the cron.weekly newsletter?

I write a weekly-ish newsletter on Linux, open source & webdevelopment called cron.weekly.

It features the latest news, guides & tutorials and new open source projects. You can sign up via email below.

No spam. Just some good, practical Linux & open source content.