Migrating to Hugo

Feb 6, 2019 | 4 minutes read

Tags: blog, hugo, wordpress

Not much has happened here lately. Today I was thinking about getting more active, but then I couldn’t sign in to Wordpress due to some breaking changes in any of the updates. Eventually I found out that there was a plugin that broke it, and produced some ugly php errors on the site.

I have been playing around with Hugo for a while and now I decided it was time to migrate.

Below is how I did, and my findings from that process.

Hugo setup

Hugo installation

I already had Hugo installed, but the installation process is simple. You can find how to do it here

Create Hugo site

Creating a site in Hugo is simple. Just move to the directory where you want to have the sources and execute create the site with the CLI:

$ hugo new site <SITE_NAME>

Install a theme

To view anything, you need to have a theme. A theme consists of output templates, styling and scripts. I went for Introduction, but you can choose any theme you like. There is quite a few available on Hugo themes site. You can even build your own theme if you like.

Once you have chosen a theme, you can install it by downloading and dropping it into the themes folder on your site, or do it with git:

$ cd <SITE_NAME>
$ git init
$ git submodule add <THEME_URL> themes/<THEME_NAME>
$ echo 'theme = "<THEME_NAME>"' >> config.toml

Check out your site

To check out your new site, start Hugo:

$ hugo server 

and browse to http://localhost:1313

There are some additional configurations you might want, or have, to do in your config.toml file. Have a look at the themes/<THEME_NAME>/exampleSite/config.toml to find the options for your theme.

Export Wordpress content

To export the content from Wordpress, I used a Wordpress plugin called wordpress-to-hugo-exporter

Installing wordpress plugin

The process of installing the plugin can be a bit different depending on your hosting options. I downloaded the plugin from github and installed it by uploading it in wp-admin GUI. Installation instructions for other options can be found on the plugins github page.

Export content

Once the plugin was installed, it was a simple one-click export by selecting the option Export to Hugo from the Tools menu.

This gave me a zip-file in my Downloads folder, containing all my posts, pages and wp-content uploads.

Add content to Hugo

To get my posts into Hugo, I added them from hugo-exports/posts in the zip-file to my <HUGO_SITE>/content/blog directory.

If you start the Hugo server with the -w flag your posts should be visible by now.

$ hugo server -w

Go live with your new site

When you are happy with how things looks and it’s time to go live with your new and shiny Hugo site, you need to generate it:

$ hugo

Then you simply upload everything under public/ to your hosting provider. The actual upload can be different on different providers, but I used simple FTP for now.


I did find it very easy to migrate my site. However, there was some caveats.


  • Posts containing images had absolute URL:s pointing to the old site. I.e. <DOMAIN>/wp-content/uploads/<IMG_NAME>. I had to go through all posts and change those urls.
  • Images existed in several formats, probably due to some plugin I used on WP. I had to manually copy only the “original” images and put them in /static/img since I didn’t want unused assets laying around.


  • Posts are exported in a format of YEAR-MONTH-DAY-TITLE, which in itself isn’t so bad, but since Hugo has support for Page bundles it would have been nice if the export would have exported posts as bundles. I didn’t do anything about it, but it would have given a better structure in the content tree.
  • Some plugins adds preformatted html to posts that you necessarily don’t want to have on your new shiny site.


All in all, it was not too much effort to migrate from Wordpress to Hugo. I am happy with the result and the new site has a lot less overhead, is much faster and much more secure.

Next steps:

  • Automating publishing of new posts
  • Add comments
  • Be more active in my writing :)