migrating Wordpress to Hugo

Mon, May 18, 2020 5-minute read

I’ve decided that I’d like my blog to be hosted on a simple webserver - no database, no scripts running server side - plain old HTML.

As I am already using Markdown on a daily basis, for my development journals, note taking and even drafting of posts for other websites of my “old” blog, a static-site generator which takes Markdown files as input and produces pretty HTML was what I started looking for.

There is a amazing website, called StaticGen which gives a nice comparison of the features of a vast selection of existing static website generators, a valuable resource which helped me to finally settle on Hugo. (Also, I’ve been using Hugo previously for the Grazer Computer Club website and blog 😄)

Naturally, when you’ve already got a couple of sites, posts and galleries you’ll want to convert these from your wordpress-based website on the new one, here’s how I managed to get 90% of that work done automagically and only had to fiddle with the remaining 10%.

1: export / backup your existing website data

There’s an amazing project “wordpress-to-hugo-exporter” which I used to convert all my posts and pages into ready-to-use markdown files. Unfortunately there is one pitfall that can easily be made when working with this wordpress plughin: The generated .zip-Export of your website will probably be to large to download via web-UI/Dashboard. If you’ve got a webhost that allowes you to SSH into your webserver that’s no issue, just call hugo-export-cli.php directly and scp that file to your local machine.

php hugo-export-cli.php

2: install hugo and verify it works

If you’re on a Arch-based distro (such as Manjaro Linux), just use pacman to install “hugo” and create a new, empty website.

pacman -Sy hugo
hugo new mwallner.net

After that you should be able to cd into your website root and start a local demo webserver:

cd mwallner.net
git submodule add https://github.com/lxndrblz/anatole.git themes/anatole
hugo server -D

NOTE: see that I already added a hugo theme “anatole” - it’s one of the ready-to-use themes presented on gohugo.io.

The following output should display a hint for an URL you should be able to open in a web browser.

...
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop

3: copy the exported website data into the new hugo website

I’ve just extracted that contents of the .zip file generated by “wordpress-to-hugo-exporter” directly in my new website folder:

unzip -X mwallner.net-exported.zip

If you’re still using hugo server in interactive debug mode, your site should refresh and all your old posts and sites should be ready.

4: tweak the theme to fit your needs

This will probably be the most time-consimung activity of this procedure. If you find a theme that you’re happy with - good for you!

I liked the initial layout and overall appearance of anatole, yet there were a couple I wanted to get changed.

If you like to get your hands dirty with changing the look of a predefined hugo theme, check out style.css first - it’ll be somewhere in /themes/<your theme>/static/css/style.css. When you want to change central layout elements, add post-previews and such, take a look at the layouts folder - it contains the templates for the generated HTML files. If you want to have dedicated shortcodes that can be used in your markdown files to create richer content, check out layouts/shortcodes.

Up to now, I have changed the anatole theme to

  • include a thumbnail of the posts on the main page
  • include date and approximate reading-time on the main page
  • add a category-cloud below the social indicators on the left pane
  • added shortcodes
    • {{ < tagcloud /> }} - insert a tagcloud
    • {{ < categorycloud /> }} - insert a ‘category cloud’
    • {{ < aimg src="..." width="..." /> }} - insert a image thumnail with a link to the image file itself
    • {{ < gallery dir="..." /> }} - insert a image gallery with all images of a given folder

“categorycloud” is just a spinn-of of the awesome “tagcloud” by sidorenko.io.

for refernce, here’s two examples:

categorycloud.html

{{ if not (eq (len $.Site.Taxonomies.categories) 0) }}
{{ $fontUnit := "rem" }}
{{ $largestFontSize := 1.6 }}
{{ $smallestFontSize := 0.8 }}
{{ $fontSpread := sub $largestFontSize $smallestFontSize }}
{{ $max := add (len (index $.Site.Taxonomies.categories.ByCount 0).Pages) 1 }}
{{ $min := len (index $.Site.Taxonomies.categories.ByCount.Reverse 0).Pages }}
{{ $spread := sub $max $min }}
{{ $fontStep := div $fontSpread $spread }}

<div id="tag-cloud" style="padding: 5px 15px">
    {{ range $name, $taxonomy := $.Site.Taxonomies.categories }}
    {{ $currentTagCount := len $taxonomy.Pages }}
    {{ $currentFontSize := (add $smallestFontSize (mul (sub $currentTagCount $min) $fontStep) ) }}
    {{ $count := len $taxonomy.Pages }}
    {{ $weigth := div (sub (math.Log $count) (math.Log $min)) (sub (math.Log $max) (math.Log $min)) }}
    {{ $currentFontSize := (add $smallestFontSize (mul (sub $largestFontSize $smallestFontSize) $weigth) ) }}
    <!--Current font size: {{$currentFontSize}}-->
    <a href="{{ "/categories/" | relLangURL }}{{ $name | urlize }}"
        style="font-size:{{$currentFontSize}}{{$fontUnit}}">{{ $name }}</a>
    {{ end }}
</div>
{{ end }}

aimg.html

<a href="{{ .Get "src" }}">
<img 
  src="{{ .Get "src" }}" 
  {{ if or (.Get "alt") (.Get "tion") }}
    alt="{{ with .Get "alt"}}{{.}}cap
        {{else}}
          {{ .Get "caption" }}
        {{ end }}"
  {{ end }}
  {{ if .Get "width"}}
    width="{{ .Get "width" }}"
  {{ end }}
/>
</a>

And so forth, there are many good examples what can be done with hugo out there 😄.

5: create your static website and deploy!

When you’re done, hugo makes it incredibly easy to generate real static .html files that are ready to be deployed to the webhoster of your choice. If you’re looking for a great and free option, make sure to take a look at GitHub pages.

hugo -D

The static website will be deployed to the public subfolder.