Gian Saß

How to convert your WordPress blog to Hugo

· Gian Sass

I have recently converted this blog to Hugo. Reasons include not wanting to maintain a grossly outdated WordPress instance which could potentially harbour attackers trying to install Crypto miners on my server.

Here are the steps I had to take to export my posts to Hugo, and to fix my posts so they actually display correctly.

Step 1: Export WordPress content

Install the wordpress-to-hugo-exporter plugin onto your WordPress instance. You will then be able to export a ZIP file of your entire blog. The ZIP will look something like this:

# ls -ll hugo-export 
total 36
drwxrwxr-x 2 nuke nuke  4096 Okt 24 16:58 about-me
-rwxrwxrwx 1 nuke nuke   150 Okt 24 17:01 config.yaml
drwxrwxr-x 2 nuke nuke 12288 Okt 24 16:58 posts
drwxr-xr-x 6 nuke nuke  4096 Okt 24 17:03 public
drwxrwxr-x 3 nuke nuke  4096 Okt 24 17:00 resources
drwxrwxr-x 3 nuke nuke  4096 Okt 24 17:01 themes
drwxrwxr-x 3 nuke nuke  4096 Okt 24 16:58 wp-content

Step 2: Install a theme

Your blog will not be able to function without a theme. In my case I installed the Ghostwriter theme.

mkdir themes
cd themes
git clone https://github.com/jbub/ghostwriter 

To use the theme you have to set up some variables in your config.yml file. For reference copy the entire contents as specified in the Ghostwriter README.md Adjust the variables so they match the configuration of your blog.

Additionally, you will have to move the posts directory so the theme can find it:

mkdir content
mv posts content/post

If all worked, you should be able to run hugo server and see a lists of your posts and be able to view them!

Step 3: Fix images

Create a static folder and move your wp-content folder there, so it can be served by Hugo.

make static
mv wp-content static

To make the theme display the featured image of your posts, the theme expects a image key for each post. But the export plugin exports the variable as featured_image. So to fix that, change featured_image to image for each post.

cd content/post
for f in *.md; do sed -i 's/featured_image/image/g' $f; done

Also in my case, the actual image URLs in my posts were being proxied through WordPress, which means the image URLs were not relative. To fix that run:

cd content/post
for f in *.md; do sed -i 's/https:\/\/i0.wp.com\/blog.gian-sass.com\/blog//g' $f; done
for f in *.md; do sed -i 's/https:\/\/i1.wp.com\/blog.gian-sass.com\/blog//g' $f; done
for f in *.md; do sed -i 's/https:\/\/i2.wp.com\/blog.gian-sass.com\/blog//g' $f; done
for f in *.md; do sed -i 's/https:\/\/i3.wp.com\/blog.gian-sass.com\/blog//g' $f; done
for f in *.md; do sed -i 's/https:\/\/i4.wp.com\/blog.gian-sass.com\/blog//g' $f; done

Additionally you will have to allow unsafe HTML in your posts, because the plugin just happens to export images as native HTML and not as Markdown.

markup:
  goldmark:
    renderer:
      unsafe: true

And voila, images should work now!