Hugo, for your site

This site is running on Hugo. I’ve followed Scott Hanselman’s advice before: make your blog content your own. This means that Facebook is not your platform, since you’re the commodity and your content could literally be taken away. Wordpress is better, but make sure you publish from a source you control and manage, and can back up. Wordpress has a habit of losing your content. Whatever platform you choose, make sure that your posts are yours and not somehow owned by the platform because you forgot to mention that they are yours.

Using Hugo is actually simple, although please know that you need to know how to work in the terminal or command line. If you don’t, then stop reading this and figure that out first. If you can’t, then check out other solutions that may work for you.

Introduction

Hugo does have a lot of documentation, but I wouldn’t call it newbie friendly. It took me a while to figure out how to get my site up and running in Hugo initially. The issue for me was terminology; I did not understand what an archetype was, or a taxonomy. The defaults don’t provide a lot of guidance, so when you create a site it’s not clear what should go where.

The themes are vague on what’s supported or how (and they are opinionated on how your content is set up; this is both a blessing and a curse). The theme is actually what controls most of your content structure so always start with the theme’s sample site to understand how your site will need to be set up.

This post is about clearing up some of these rough edges I experienced, and hopefully it will help someone else (or future-me when I forget).

A brief introduction to Hugo

I won’t go in to too much detail here, but Hugo is an incredibly fast static site generator. A static site generator creates a static website of HTML files, with no server side processing needed (such as PHP). It is based on some source structure which, in Hugo’s case, is Markdown files in specific folders. Hugo gathers all these files and generates a website structure that browsers will understand. It even generates valid links to other posts, or images, that you have.

To give a basic example; let’s say you want to set up a blog site. Here, you’d create a new Hugo site (I’ll give the steps later), get a theme, and create blog post content under a content folder called “blog”. Inside this folder will be all your blog posts in Markdown files. You create all your posts this way, then generate your site from them using Hugo. You copy this output to a web server, a share, or something like an Amazon S3 bucket, and you have a fully functioning blog site. There are no runtime requirements on your hosting site as it serves the files as-is from the web server. This is close to how mine is set up.

Installing Hugo

The first step is to get Hugo set up. All of this is available in their Getting Started documentation. The quick start is the best place to get the detail, but essentially you:

  1. Install Hugo.
  2. Create your Hugo site.
  3. Get a Theme of your choosing (or create one)
  4. Add/Update content (be aware of your chosen theme’s opinion on where this content should be located; or change the theme to look at your content location)
  5. Build the site
  6. Publish your site to your hosting location

This first three steps are a once off; the final 3 are the typical routine each time you update content.

Install Hugo

Hugo is a command line application. You install it via Homebrew, Chocolately, or direct download. The specific details are here. Once it’s installed, you should make sure it’s in your path.

Create your site

Run this in a command line or terminal:

hugo new site awesome-blog

It’s that simple. This will create a bare site, ready for Hugo to work with. However, since there is no default theme, nothing will render if you create your site off of this basic setup. The minimum requirement is a theme.

Here’s the tree structure of a newly created site:

.
├── archetypes
├── content
├── data
├── layouts
├── static
├── themes
└── config.toml

Note how there is just one file: config.toml. This file is not that interesting at the moment but it is important for the configuration of your site later. It contains the site base URL and site name as a base. More goes here as you configure your site.

Get a theme of your choosing

There are a lot of themes on the Hugo Themes site. Since each theme is specific about how it works, I will select a simple one for now; Hugo Dusk. It’s a minimalist design, but I don’t want to go in to too much detail here.

Clone the theme from git, in to the themes folder:

$ cd themes
$ git clone https://github.com/gyorb/hugo-dusk

Your directory tree now looks like:

.
├── archetypes
├── content
├── data
├── layouts
├── static
├── themes
│   └── hugo-dusk
│       ├── archetypes
│       │   └── default.md
│       ├── exampleSite
│       │   ├── content
│       │   │   ├── post
│       │   │   │   ├── creating-a-new-theme.md
│       │   │   │   ├── goisforlovers.md
│       │   │   │   ├── hugoisforlovers.md
│       │   │   │   └── migrate-from-jekyll.md
│       │   │   └── about.md
│       │   ├── static
│       │   │   └── .gitkeep
│       │   ├── .gitignore
│       │   └── config.toml
│       ├── images
│       │   ├── screenshot.png
│       │   └── tn.png
│       ├── layouts
│       │   ├── _default
│       │   │   ├── li.html
│       │   │   ├── list.html
│       │   │   ├── single.html
│       │   │   ├── summary.html
│       │   │   └── terms.html
│       │   ├── partials
│       │   │   ├── disqus.html
│       │   │   ├── footer.html
│       │   │   ├── head.html
│       │   │   ├── header.html
│       │   │   ├── paginator-menu.html
│       │   │   ├── postfooter.html
│       │   │   ├── social-links-footer.html
│       │   │   ├── social-links.html
│       │   │   └── tags.html
│       │   ├── 404.html
│       │   └── index.html
│       ├── static
│       │   ├── css
│       │   │   ├── color-dark.css
│       │   │   ├── layout.css
│       │   │   └── tomorrow-night.min.css
│       │   └── js
│       │       └── highlight.min.js
│       ├── LICENSE.md
│       ├── README.md
│       └── theme.toml
└── config.toml

Note the exampleSite under the theme’s folder; it’s a useful starting point for all the themes. They help to understand how the theme works. Also note the config.toml in this folder, as this is also useful for your site; it provides the basis for your own site’s configuration.

The next step is to set up your site’s theme. Open the config.toml, and set the theme like this:

theme = "hugo-dusk"

Also grab the other content from the exampleSite config:

SectionPagesMenu = "main"

[[menu.main]]
  name = "Posts"
  weight = -120
  identifier = "post"
  url = "/post/"

[[menu.main]]
  name = "Tags"
  weight = -110
  identifier = "tag"
  url = "/tags/"

Add content

In the case of the theme above, you will note the sub-folder post under content in the exampleSite. You will follow the same structure. You can deviate, but this will mean tweaking your site set up.

hugo new post/first-post.md

That’s how you create all content in future. Your structure now looks like this (I’ve excluded the theme’s folder for brevity):

.
├── archetypes
├── content
│   └── post
│       └── first-post.md
├── data
├── layouts
├── static
├── themes
│   └── ...
└── config.toml

At this point, you have a single post for your site. You can add content to this markdown file using standard markdown. Titles, lists, content, all of it. However, notice right at the top is the front matter. This looks like:

+++
date = "2017-04-27T13:50:11+02:00"
draft = true
title = "first post"
+++

This is where you place all the meta-data about your post. Don’t delete it. Add to it though. You’ll first want some tags:

tags = ["blog", "first-post"]

And there we go! Your site is pretty much ready. To preview your site, use Hugo:

hugo serve --buildDrafts

The output will give you your localhost URL to use to preview your site. Leave hugo serve running in the background; it picks up your changes and live feeds it to your browser. This is an awesome way to watch your site’s layout while you write your posts.

Note that I included --buildDrafts above? This is because your post is currently still a draft. What this allows you to do is have content ready, but not have it included in your published site. This is great for drafting posts, keeping them in source control (or backed up), but not have them accidentally become public before you intended. There are other front matter elements you can use, such as expiryDate, which will remove your content if you build your site after this date. It is not automatically removed from your live site for you though, this is a static site. You have to build and publish to update relevant changes.

Have fun and happy blogging!