I recently switched blog software from Bludit which is an flat-file CMS that is super user-friendly. I found it to be much more lightweight than WordPress and the variety of themes to be pretty good. However, I have this habit of changing my mind about how I want my blog hosted every few years and with my IT background being much stronger now than it was 3-4 years ago when I chose Bludit, I decided to give Hugo another go.
Hugo is a static website generator rather than a CMS. You feed it markdown files and a theme and it’ll create a website for you. You can infinitely customise the themes and even create your own and the result will be a static site with no database behind it putting your web server at risk. That said, it’s a commitment and not a small one at that. I think to be truly comfortable with Hugo, you need to have an understanding of what it’s actually doing, be comfortable with mark-up/down languages, and be able to read technical documentation (and fill in the gaps). Personally, I found the Hugo documentation to be… obtuse at best and downright unhelpful at worst. Once I figured out what it was trying to do, things got a bit easier.
This guide is going to be predicated on installing the extended version of Hugo and the Stack theme - adapt as necessary to your use case.
You’ll want to install Hugo on your platform of choice. In my case, I installed it on my Debian Buster development box. I did this using the fetch from GitHub instructions on this instruction page. You will also need to have Go installed - version 1.11 or newer (at time of writing). You will also require a correctly configured web server, which I won’t go over here, but Apache and nginx tutorials are a dime a dozen. In my opinion, installing Hugo is probably the easiest and best documented part of this entire process.
Creating a New Site
One of the core concepts of Hugo is the creation of a “site”. It’s about what you’d expect, however you will need to create a directory for it to live in, so make sure you do that first!
I create the new site using
hugo new site [path] below. This initialises a whole bunch of files and folders that make up the structure of the raw Hugo site. Raw? You’ll see what I mean when we start cooking.
Installing a Theme
Hop into your new site’s /theme directory and bring your new theme in. The quickstart guide recommends doing this using a
git init and
git submodule add command however I had no issues with just using
git clone to pull my theme of choice down from the maintainer’s repo.
At this stage, if your theme includes it, you may want to copy the contents of the exampleSite up and over the main site’s root directory. e.g.
cp -r /opt/hugo/themes/hugo-theme-stack/exampleSite /opt/hugo. This will give you with a bunch of pre-made posts, a few pages, a working config file, and a lot of good clues about how the site should be structured.
Configuring the Theme
You should notice a config.toml file in the directory that your
hugo new site command created. Depending on your theme, you may have overwritten this in the last step with a working copy from an exampleSite subfolder, you may need to configure your own in line with your theme’s docs, or, if it’s like the Stack theme, you may need to rename/move/delete the config.toml file so that Hugo will pick up and use the config.yaml file provided by the theme creator.
Hugo supports TOML and YAML markup languages for its configuration files - these are essentially just configuration formats of key-value pairs and is pretty similar in concept to JSON. YAML is whitespace-centric and uses tabs/spaces to format things in a human readable way whereas TOML uses more of an INI-style format, similar to what you might see in Windows configuration files.
In the case of my theme, I only had to make a few changes to the configuration file provided - primarily related to the title and description of the blog but I also edited the custom emoji, the URL for my website icon, and the baseURL.
The baseURL is an important one to get right as incorrectly setting this may break certain features of your website - for example, I spent a long time troubleshooting an issue with my search functionality, only to find the baseURL had been set incorrectly. Basically, when you build your website, make sure you double check for broken links in the console - if you see them and the files are in the correct folders, then your baseURL is incorrect. This is one of the things that annoyed me about figuring out how to use Hugo - some errors are not evident until build time despite best efforts with the test web server command.
Creating New Content
This will vary a lot depending on your theme! In my case, the theme separates things out into post/page/tag categories (called Sections by Hugo).
To create a new post in my Hugo blog, I run
hugo new post/how-to-hugo/index.md which will create the appropriate folder and a markdown file for me to create my new blog post in. Similar can be run for pages and custom tag pages (which I don’t really use nor understand). Here’s a quick guide on how to use markdown - it’s really quite intuitive once you get the hang of it and it’s used in lots of places like Reddit and GitHub.
The only downside to this approach is that it only puts very basic metadata at the top of the file as shown below.
I use this approach to create the folder structure if the post I’m creating isn’t already very similar to another I’ve already created. Otherwise I’ll just copy a previous folder structure, rename things, and do very minor edits to the metadata. It’s also worth noting that this will create a draft post, which won’t build as part of your site by default and won’t be visible on either the tested or built versions of your website.
The following is what the metadata for a typical post looks like and which should give a little context for why I don’t like using the new post command:
Testing the Website
This is the fun bit, where you get to see your site (hopefully) come to life. This command has a lot of options so I’d definitely recommend you check some of them out using
hugo help server.
The first step here is to make sure you’re running the
hugo server command from within your Hugo site directory. I believe there are ways using the command line options to force it to know where the website directory is but honestly it’s not worth it and it’s quicker to just change directories to the correct site.
Next you’ll run the below command. Essentially what this does is creates a web server and builds your site on the fly. You’ll be able to see the website update in real time at
<yourIP/hostname>:1313 as you make changes, which is pretty cool. We’re binding the webserver to all IPs just for testing purposes - if you’re configuring your actual web server, best practice says not to do this.
Assuming all looks good in your testing web server, you’re ready to cook your raw Hugo site.
Building the Website
So up until now you’ve just been running your Hugo instance in its testing web server which is designed to be ephemeral. I googled for ways to daemonise it before realising that’s just not how it was designed to be used. When I figured that out, it actually freed me up quite a bit because I already had a web server up and running on the internet that I could just go ahead and drop this onto.
The command I use for my build is a bit longer than you would need if you were just building in the same directory as you’re testing in but I like to keep things separate because I’m not about that testing in production life.
- The –config option specifies where the configuration file is located - this isn’t necessary if you’re running everything out of the same directory.
- The –destination option specifies where the website should be outputted to.
- The -v option is verbose mode.
- The -b option is the setting for baseURL and is not required if it’s set correctly in your config file. I use it here however because my testing and production environments aren’t the same.
This will take the configuration files and content you’ve created and generate (cook) the static files required for your website. If you outputted directly to your web server’s public folder, your new website should be immediately visible at http[s]://<yourIP/hostname>/.
And that’s it! That’s how you configure and deploy a basic Hugo site. I’m sure there’s a whole bunch of errors and things that are a bit more verbose than they need to be in here, but I personally found the documentation really confusing. Even though the quickstart guide covers a lot of what I’ve just explained, I found that not enough of the core concepts were explained there.