I’ve been writing blogs since March of 1999. Yes, I’m old.
When I started, my friend Ben suggested Moveable Type, and it worked well until around 2003 when they decided to switch their license from an open source one to proprietary. We decided to move to this new open source publishing application called WordPress.
WordPress would go on to become one of the most dominant content creation systems in the world, mainly due to its open source nature. It was monetized through the creation of a hosted version as well as proprietary themes and plug-ins, but you didn’t need those to get value out of it.
As with most software, as it grew so did the bloat, and while the application itself has been pretty secure for awhile now, attack vectors were introduced through vulnerable plug-ins. Since my sites are pretty simple, I had been considering switching to a static site generator (SSG) but it wasn’t really a priority for me.
That was until WordPress started to implode. It is left as an exercise for my three readers to check out the drama, but it includes things such as disabling community member accounts if they talk about things such as a fork.
I started researching SSG options and decided on Hugo. Other leading SSGs are Jekyll, Eleventy and Publii, but I had issues getting Jekyll installed on my Mac and Publii, while fun, was too much like WordPress (which can make it a good option for people not used to the command line). I have over 2000 blog posts and I do not want to go through another migration.
Since I use Homebrew installation of Hugo was as simple as:
$ brew install hugo
The first site I decided to upgrade was tarus.io. Now unlike WordPress, Hugo is a command line tool. You install it on your development machine, create your content, run a command and Hugo will generate static HTML in a folder that you can copy to your web root, and then you are done.
All you really need to get a Hugo site up and running in minutes is to choose a theme. I ended up going with Hyde, as it closely matched the Wordpress Hum theme I was using on tarus.io.
Once I had that choice made, I created a hugo
subdirectory, and from there I simply followed these steps:
hugo new site quickstart
cd quickstart/themes
git clone https://github.com/spf13/hyde.git
cd ..
echo "theme = 'hyde'" >> hugo.toml
hugo server
The final command will output a URL on localhost
that you can use to see the Hugo output in your browser.
In your working site directory there will be a subdirectory called content
and that is where all of your posts, etc. will go. Instead of a visual editor or raw html, you use Markdown, which I find easier, and I use an open source tool called MacDown (along with vim) to edit.
I didn’t want to manually recreate 2000 posts so luckily there is a plug-in to export a WordPress site to Hugo. Note that do to the new direction WordPress is headed, you do not have to install the plug-in through the WordPress marketplace. Simply follow that link to GitHub, click on <> Code
and save the .zip
file. You can then just install that file into your WordPress instance, which will create a Tool option “Export to Hugo”. You get no visual indication that it is working (except the browser tab should indicate it is loading) and out should pop a zip
file with all of your content, including images, with most of your posts and pages converted to Markdown.
Simply unzip the contents of that file into your /content
directory and you should be go to go.
Not so fast.
The plug-in does a lot of heavy lifting but chances are you will need to hand edit some of your files. If you have been posting a lot since, say, 2022, WordPress added a lot of kruft to the raw HTML and the exporter has problems parsing it. I ended up using GenAI (specifically Anthropic Claude on Amazon Bedrock) to write some scripts and some commands to help me clean it up, but there was still a lot of manual work involved. Once I got back into mid-2022 most of the output was clean and useable, with the exception that it tended to crop the last link in the post.
The exporter uses a Markdown option where links are referenced by a number and are included at the bottom of the document. They are numbered 1, 2, 3, etc. and they do save a little space if the same URL is referenced two times or more (as the exporter will reference it only once). But for some reason it clips my last one and I have to put it back.
The easiest way for me to do that is to export the WordPress site using the default exporter, which dumps the text into a big XML file. I can then search through it, looking for the end of each post, and then paste the missing URL back in.
By default Hugo will strip out HTML and not render it. If you do want to embed raw HTML in your document you can add a “shortcode”.
One was called “rawhtml”.
Basically, you create a directory under your site directory called layouts/shortcodes
and in that directory create a file called rawhtml.html
with the content:
<!-- raw html -->
{{.Inner}}
Then you can use the shortcode {{< rawhtml >}}
at the line before we want to use html and {{< /rawhtml >}}
at the end of the block.
When it is time to publish your site, I found out that I had to run the “server” command with some options:
hugo server -D --baseURL=https://YOUR-URL --appendPort=false
and then I could just:
rsync -av -P ./public/ example.com:/path/to/your/webroot
Note that if you do a WordPress export your /wp-content
directory will be included, and if your browser allows for indexing people can browse through your content. I added a .htaccess
file with the line:
Options -Indexes
which will prevent that from happening.
I then started working on Forgotten Cocktails. There are a large number of free themes for Hugo and I tried many of them, finally settling on Bilberry. Some I had trouble getting to work until I learned that while most themes will try to publish all of the Markdown files in your /content
directory, some features look for specific directories, such as post
instead of posts
. Renaming it will sometimes get stuff to start working.
I was very happy with Bilberry as it had many more features than Hyde, so over the weekend I went back to work on tarus.io. That’s when I found Stack.
I like Bilberry. I love Stack.
Note that it can be pretty easy to try out different themes. Simply download a new one and update your hugo.toml
file, but I’ve pretty much decided to base my sites on those two.
The third site I converted was for my car, the Banana SL. It doesn’t have much content so that one was easy. I ended up going with Bilberry for that one.
Finally I decided to attack this site. Sheesh. There is a lot here - almost 1200 posts. There are also a lot of dead links and other problems, so I’m going to go through each post one by one, but I want off WordPress so badly that I am launching this site with a fraction of the content, and I plan to add the rest back over the next few weeks.
This my professional blog, so I decided to start with Act III of my professional life, which happened when I left the company I founded back in 2021. I will add back almost all the posts back to 2002 but it will just take some time. For example, I was very proud of creating The Order of the Green Polo but it doesn’t exist anymore, so I need to update the links to point to archive.org.
As of this morning I am no longer using Wordpress for myself. I manage a couple of sites for friends that I’ll need to migrate in the future, but they are no longer being updated and are there just for the history. That should make it easier to migrate since they haven’t been updated in awhile, and the exporter handles the conversion better if the posts are old.
Note that if your Wordpress site is heavy on comments, Hugo doesn’t have a built in comment feature (it’s the “static” in SSG). You can integrate with other discussion sites but I tend to talk about these posts via social media so it didn’t matter to me to migrate them over. If that concerns you know that there are options but it isn’t out of the box.
I was surprised at how simple it was to get started on Hugo, and I like having a site that is statically generated. If you are happy with WordPress and don’t care about the drama, that’s great, you may want to consider an SSG just for security but I have no judgement if you continue to use WordPress. However for me Hugo is just the thing to migrate away.
Here is a screenshot of my old site just for posterity.