Using Hugo


I’m using Hugo to run this site. It has some documentation, but I found it a bit hit and miss, so here’s a quick how I did it, rather than a how to. Partly for my records, and partly because it might be useful to others.

I have traditionally used big blog platforms like WordPress to run any blogging I’ve done,but, I wanted to use a static site generator this time round and stick to a super-minimal and performant site.

I run a Windows machine with WSL2, so this should work for you if you’re on WSL2 or Linux. Getting set up is mostly just following the Quick Start guide from Hugo, but here there’s more of a “I’m making an actual site” feel to it and a bit of missing context.


Install Brew

Hugo is installed easiest with Brew it seems. Brew is yet another standard way of installing things. Yay. Instructions are on the Brew home page, I just stuck this into a WSL prompt like they said to do:

/bin/bash -c "$(curl -fsSL"

That will tell you what it’s going to do, then do it. It’ll prompt you for your password when it runs a sudo command, after checking you have sudo rights. At the final step it will output some commands you need to execute yourself to finish off setting it up in your profile. Awesome. You now have Brew installed as well as apt and all the other ways you already had to install things…

Install Hugo

Installing hugo with brew is super simple. But seemed to take an age for me:

brew install hugo

Once installed, check it’s working:

michael@DESKTOP-0V8O7JR:~ $ hugo version
hugo v0.88.1+extended linux/amd64 BuildDate=unknown

Init Site

I wanted to manage my site with standard cloud based git version control, because I’m a developer at heart. So I set up a new blank repository on BitBucket, as that’s what we use at work, and cloned that locally.

Next, I just used Hugo to create a new blank site in the local repository:

hugo new site personal-site
cd personal-site
git commit -a -m "Hugo new site init"
git push

Following that, we need tp add a theme, I decided to use the Goa theme as it looked a lot like the base, simple, minimalist site I’d hand cranked before.

I forked the repository first, because I want to control where my changes are, for me, Goa was a base I intended to change, rather than a theme I was sticking with. Then I added the fork into my Hugo install as a git submodule and added it to the site configuration. I went with a sub-module so I can master the theme seperately, in it’s own version history, and gut it out again for something else later if I want.

git submodule add themes/goa
echo theme = \"goa\" >> config.toml

At this point, I still haven’t started Hugo!

Basic Site Configuration

Next up was to re-configure my site, the base configuration doesn’t include the stuff that the Goa Theme needs to render correctly, and is all out of the box.

So I just cribbed all the details from the demo version of the Goa theme, then tweaked to suit my site. I also had a read to see what those settings were doing. Quite nice the way you can define in custom settings for your site, then use them in the templates transparently.

Mark-up Lanaguages

By default, Hugo uses TOML. Tom’s Obvious Minimal Language. Yes, because with XML, JSON, YAML, INI files etc, what we really needed as techies was another “obvious” and “minimal” mark-up language to deal with. With it’s own set of quirks. Yay.

After doing all the config, I got annoyed with TOML. Hugo supports TOML, JSON or YAML. I didn’t want to learn TOML for this site, I’m super comfortable with JSON and YAML, but I decided to switch to JSON as I probably use that a bit more than YAML at work.

I used a TOML to JSON online convertor to convert my config.toml file contents to JSON and replaced config.toml with config.json.

Now my config file is in JSON, the structure makes much more sense to me, with the various parts it controls all separated out in a nice way! YAML would also be nicely structured, and perhaps a bit more “on brand” for devops, but it’s arbitrary. So long as it’s not TOML!

Development vs Production

I want drafts in my dev environment and not in production. Hugo has a nice system of configuration files that are environment specific, you can create a config folder in your Hugo site, with a sub-folder per environment that sets overrides. Defaults are production when you do a compile to generate a static site and development when you spin up the local Hugo server, so I created a basic config\development\config.json file with my development environment overrides:

    "baseURL": "http://localhost:1313/",
    "builddrafts": true,
    "canonifyurls": false

I’ve tweaked the base URL for the site and told it not to generate absolute links. Simple I think. Might get richer over time. BaseURL in my main config.json file is set to my domain, builddrafts and canonifyurls are both true.

Working on Your Site

So then, to run your development site, so you can draft your content and work on your theme or whatever, it’s a case of running the Hugo server:

michael@DESKTOP-0V8O7JR:~/personal-site [main ↑1 +2 ~1 -1]$ hugo server -D
Start building sites … 
hugo v0.88.1+extended linux/amd64 BuildDate=unknown
WARN 2021/10/10 06:43:17 Page.RSSLink is deprecated and will be removed in a future release. Use the Output Format's link, e.g. something like:
    {{ with .OutputFormats.Get "RSS" }}{{ .RelPermalink }}{{ end }}

                   | EN  
  Pages            | 19  
  Paginator pages  |  0  
  Non-page files   |  0  
  Static files     | 13  
  Processed images |  0  
  Aliases          |  0  
  Sitemaps         |  1  
  Cleaned          |  0  

Built in 8 ms
Watching for changes in /home/michael/personal-site/{content,data,layouts,static,themes}
Watching for config changes in /home/michael/personal-site/config.json, /home/michael/personal-site/config/development
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
Press Ctrl+C to stop

Great, now in my browser I have a site running, which I can see and make changes to. There’s a problem with the older code in the theme I based on using a legacy way of outputting RSS links, so I’ll go and fix that and then get on with writing content.

I’m wondering what my 19 pages are though. I’ve not written anything yet.

Git Submodules

Now, any changes I make to the theme, configuration or content are all fully tracked and mastered with standard git commands. Remember when you make changes/commits in the sub-module to commit the change in the main repository to ensure your site is tied to your specific revision of your theme! Excellent! I can always go back!

Releasing Your Site

A release build is made by running the hugo command, this will generate the static site in the public folder. So I’ve tweaked .gitignore to ignore public/*, as I don’t want to version the releases in my repo.

michael@DESKTOP-0V8O7JR:~/personal-site [main ≡]$ hugo
Start building sites …
hugo v0.88.1+extended linux/amd64 BuildDate=unknown
WARN 2021/10/10 07:01:24 Page.RSSLink is deprecated and will be removed in a future release. Use the Output Format's link, e.g. something like:
    {{ with .OutputFormats.Get "RSS" }}{{ .RelPermalink }}{{ end }}

                   | EN
  Pages            | 19
  Paginator pages  |  0
  Non-page files   |  0
  Static files     | 13
  Processed images |  0
  Aliases          |  0
  Sitemaps         |  1
  Cleaned          |  0

Total in 29 ms

Super fast! Later, I’m going to set up a BitBucket Pipeline to auto-build and release to my server when I push changes to main. But not yet. Manual release to start.

cd public
scp -rp *

And there we have it, a quick blank site on a basic theme. I still have bundling and minification to look at for the assets, that’s not working. But that’s all you need to get started.