TL;DR Moving from hosting the blog in Wordpress to generating it with Hugo.
I have pondered for a while on whether I wanted to move from Wordpress blog to a static one. Blog after blog converted to static pages, and they seemed to be faster than mine. Something had to be done. On top of that I have had some issues with the built in editor in Wordpress, and wanted a change of scenery.
For a while I have checked the different frameworks for hosting a generated static page. Options include Hugo, Gatsby, Jekyll, Pelican, Eleventy,and the list goes on.
After some consideration I chose Hugo. These are some of the reasons I chose Hugo:
There are many reasons for going from a server processes technology like Wordpress, to a statically generated site like Hugo.
When using a generated static page, you have only the https endpoint, and no login/plugins/frameworks/backdoors for attackers to inject code. No code is processed in a backend, and everything is served as html, css, or javascript. I have no direct logins to update, change passwords or manage MFA on. There is no login system with weaknesses and exploits for spoofing access. I am effectively moving authentication over to Azure (with Azure AD if I want, more on that later) and GitHub (repository and deployment).
Whenever I want to write a blog post, I just make a new markdown file in Visual Studio Code, and publish. There is no login to Wordpress, fighting with an editor, uploading images to Wordpress, auto-saving, process consuming editor, SEO-analytics, or bugs in the system. A simple markdown file with some images is all it takes, and tags/categories/images/twitter/opengraph is included in the pages correctly. Many times I fought with the social media meta tags in Wordpress, and they didn’t really work correctly for me. I could have invested more time in it, but I figured it shouldn’t be that difficult to configure.
For hosting Wordpress I have been using a web hotel at Domeneshop. This costs around 30NOK each month, so not really a big expense here. There is need of a PHP processing server, and a MySQL backend database for storing data. These services add up, and in time I would have to upgrade my web hotel plan because of storage issues. I would also need to upgrade if I wanted faster processing, or better bandwith/hosting options in general.
With a static site I only need a place to store my files (html, css, javascript, images, ++), and maybe a Content Delivery Network for speed and caching. This is not a lot of files, and you will get away with storing it just about anywhere that can publish your files.
Any dynamic solution requires a backend processing server that serve dynamically created pages. This can be ASP.Net, PHP, Java, or any other backend processing technology. Sometimes this can limit your hosting options, because not every hoster can deliver exactly what you need. Sometimes it can get expensive when you need an actual compute-unit behind your web page.
With a static site, as mentioned in the previous paragraph, you only need storage and CDN. This opens up a whole new array of hosting possibilities, and they can be cheaper, quicker, and generally just better.
Possibilities include:
I chose an Azure Static Web App.
With Wordpress I had to update almost every time I logged on. A theme had updates, plugin needed update, wordpress itself needed update, or just the need to update backend PHP version. This adds up, and I have more than once deferred an update because I did not have the time at the moment. This leads to insecure configurations, and maybe unpatched vulnerabilities. My guess is there are lots of unpatched and vulnerable wordpress blogs out there, because there are so many updates all the time. This is one of the main reasons I wanted to move to a static page.
Of course there are drawbacks to moving away from Wordpress. Not many, but they are there.
So how did I migrate my blog from Wordpress to Hugo hosted on Azure Static Web Apps? These are the steps I performed.
Exporting the old posts is very easy. You just export with Wordpress export to XML (of course depending on your conversion tool of choice). You can choose what you want to export. In my case I only exported the posts.
There are a bunch of community projects for this, but I ended up using this one in Windows Subsystem for Linux. I have a WSL2 with Ubuntu, where I can do these sort of things. Clone the repository. Install Node.js, and run it like described in the repository. Works like a charm, and it can also download pictures for you, which is nice!
Download and install Hugo like described here. I opted for doing this also in WSL, as this simplifies much in terms of tools needed. After you have downloaded Hugo, you need to create a new project. I chose to store the blog files in a subfolder of my repository ./blog and can point Hugo to create a new site there.
I installed Hugo in my WSL Ubuntu with snap. Snap should be better supported now because of systemd support, but I had a hard time enabling it correctly in the past. It is working for me now, but installed so long ago that I don’t have the installation link any more. Anyway, you can install Hugo whichever way you are comfortable with.
Create a repository for storing your blog. I recommend using a private type repository here, as you are the only one needing access to these raw files. All publicly available files will be built by a GitHub Workflow, and deployed to your Azure Static Web App. No one other than you needs access to the repository.
Clone the empty repository to your WSL or wherever you are configuring Hugo.
Hugo requires a config file to work correctly. You might want to spend some time figuring out the options here, as there are some important configs you need. I used config.toml as my method, because I think toml-structure looked the most user friendly. It looks like yaml.
This is the top of my config.toml:
############################ Default configuration #########################
baseURL = "https://your-url-here"
languageCode = "en-us"
title = "title of your blog"
theme = "your chosen theme" # must also be downloaded
summaryLength = "10" # number of words in post summary
paginate = 6 # number of posts per page
disqusShortname = "" # Disqus connection, if needed
pygmentsCodefences = true # might be necessary for getting syntax highlighting correct
[outputs]
home = ["HTML", "RSS", "JSON"]
There are also lots of other configs, but this would depend on your chosen theme.
Follow the quickstart, but substitute your own folder name. You can use “blog”, “site”, “public”, or whatever you want. I used “blog”. Hugo will build it’s structure inside that folder.
For my part I chose Liva Hugo, because it looks fresh and light. It is lightweight, and can be extended with javascript plugins. It is social media friendly, and looks good on large and small screens alike. You can find the theme that suits you for free here, or just google “free hugo themes” and get more results. Often there is a free lite-theme, and you pay for some pro features. I did not pay for my theme, as the free one covers my needs.
You should also consider creating a logo, and the best way I found was going here to generate a free one.
Remember that you need to check your social media tags! These help generate good previews for SoMe, and is crucial to get those nice looking “look at my post” tweets.
Added in this way:
YMMV as your theme can have a different config. You could also do this in many other different ways, and when you find the correct way, please inform me. It works for me now, and I am not planning on updating the theme anytime soon. After updating the theme these changes will be overwritten, I assume.
The front matter is also important for getting the SoMe tags right. Images must be added a certain way, and you get a summary_with_large_image Twitter card. For me the images: [] was key in getting a proper Twitter card with large image.
I chose to generate some stylesheets and use syntax highlighting that way. Hugo has a builtin highlighter called Chroma, and it seems to work good enough. You can either generate and add the extra stylesheets, or you can just use the builtin way of enabling highlighting. I ended up following along this post to troubleshoot and fix my highlighting.
Added “syntax light” to my header, which can be changed for a “syntax dark” if needed at a later stage (those generated by hugo gen chromastyles cmd):
Where to publish for me was a no brainer as I have already worked with Azure Static Web Apps. Create an Azure Static Web App in the portal, and connect it with GitHub. Everything else is done automatically for you, and it understands Hugo so it can build your pages for you automatically. It even has a Pull Request feature which creates a temporary page whenever there is a pull request to main branch. This feature needs some more attention from me, and I have not used it enough yet. Still fresh!
Create Static Web App
Choose a hosting plan (free for personal is great!)
Some deployment details like where code is stored, and which branch.
Set up Hugo build config for automatic deploy.
After export there are a lot of typos and missing code fences. This needs to be handled before publishing. I have manually combed through my posts and tried to update the more recent ones. Other than that I have left most of the old ones in a more or less non-updated state. Meaning they don’t look great, but the information is still there.
Azure Static Web Apps provide SSL for free. You need a domain for hosting, and you can purchase this in Azure if you want. I have my domains purchased from Domeneshop, and have been satisfied with their service thus far.
Add a custom domain to the Static Web App in Azure portal by configuring a CNAME or ANAME with your registrar. I had to use the ANAME type record because codewithme.cloud is the apex domain.
All in all this was a fairly good experience. I feel like the blog looks good right now, but I might change the look and feel at a later stage. On the plus side I won’t need to update Wordpress or any other software on my blog for a while!
Thank you for reading, and please comment if you see something wrong or strange!