Migration from Wordpress to Hugo

Nanoblogger – Wordpress – Hugo

History repeats itself. This blog started 2004 using a static site generator (NanoBlogger, not maintained anymore since 2013).

Then in 2005 I was tired of always uploading the statically generated site with lftp and migrated to WordPress, where the pages are served dynamically from a database.

Now, more than 17 years later, I’m switching back to a static site generator (Hugo). Times have changed, no need for cumbersome manual ftp upload anymore (GitLab or GitHub CI/CD scripts take care of that).

The new cumbersome is filling out web forms to write your content, when all you want is:

  • to write your text in your text editor on your local workstation, using Markdown or Asciidoctor to render it into web format.
  • have your articles in a Git repository, where you have a copy of everything in your local workspace

(Almost) Transparent Migration

My goal was to make the migration as non-breaking as possible, i.e. keeping all permalinks identical (that’s why they are called permanent 😉). Of course the graphical appearance changed (the old one was a bit dated); now I’m using a slightly patched Tranquilpeak theme.

One thing that has changed though is the RSS URL, from /feed/ to /feed.xml, and there is no Atom feed anymore. I could probably bring it back, but if there is no need, I’ll save the time it takes to configure it. So if you’d like me to add it, drop me a message. You’ll find my coordinates on the sidebar or via the hamburger menu in the top left corner.

The Migration in Detail

There are several approaches documented for a migration from Wordpress to Hugo. I tried blog2md which takes the Wordpress Backup XML as input and converts every article into a separate Markdown file. That’s already a good start, but it still needed quite a bit of manual migration work:

  • all non-text files (uploads, favicon etc) had to be downloaded manually from the Wordpress Site and copied into the /static folder of the Hugo workspace (as I was self-hosting the Wordpress site, I had FTP access, so this was quite easy).

  • the generated Markdown files needed some manual post-processing (there were about 65 articles, so this was a bit tedious, but still manageable):

    • paragraphs were not detected, so I had to insert line feeds at the correct places
    • backticks were sometimes not set for monospaced text; some triple backspaces for code blocks were there, but usually lacked the line feeds before or after. And inside the backticks there were many unnecessary escapes.
    • tables from the Wordpress site were not detected, every table cell ended up in a separate Markdown paragraph (I’ll admit that tables are not a standard Markdown feature, but almost all renderers support tables)
    • footnotes were converted into intra-article links, but ignoring the quasi-standard Markdown extension for footnotes, see e.g. Github Markdown Footnote Syntax
  • The Wordpress site was configured to build the permalinks using date and title; so my first try with Hugo was to use the same configuration ('/:year/:month/:day/:title/'). But this works only for most of the articles; for some titles (e.g. containing umlauts) the permalink would have been different to the Wordpress one. So I changed the configuration to

      posts = '/:year/:month/:day/:slug/'

    This allows to override the default permalink using a slug front matter variable (without explicit slug the title is used)

What’s next?

Although I’m happy with the new look and manageability of my blog, the migration is not completed. The old comments are not visible yet and currently no new comments can be added, but I’m working on it; there are a couple of solutions to have comments with a Hugo site. I’ll tell you more about in a future article.

If you’d like to comment on this or other articles as long as the comment system is not in place yet, please drop me a message on Mastodon and I’ll add it when I migrate the old comments.

Peter Steiner

Software Developer and Opinionated Citizen