Standup, Hugo! Creating a Blog with Hugo


Let’s quickly review what you’ll need to build a Hugo blog, and what it will mean to have a Hugo blog at the end of the process.

What You’ll Need

Before we begin, you’ll need a few things. I’ll list the essentials below (as well as my recommendations where relevant)

  • Git, the ubiquitous VCS of the era
  • GitHub account, for storing your blog content (and hosting for free!)
  • Text Editor, for writing content and editing configuration files (I recommend either Sublime Text for simple uses or GoLand for those who also need to edit GO code for plugins)

What You’ll Have

By the end of this post, the hope is that you will have:

  • A fully-functional, clean, and simple blog
  • Hosted for free on GitHub Pages
  • A workflow for adding new content and automatically building your website

Let’s (hu)go!

Getting Started with Hugo

The good news: Hugo has excellent getting started documentation. My goal is to guide you through the process quickly, filling in any gaps.

Installing Hugo

A convenient detail about using Hugo is that is comes as a single binary, there is no complex environment to maintain! Nonetheless, we must install Hugo. On Macos, this is done by

brew install hugo

See the installation docs for other operating systems.

Creating the Repository

The blog needs a place to live - create a GitHub Repo to store the code. Note: if you intend to host with GitHub Pages as is done here, the name of your repository must be <username> for users or <organization> for organizations. Clone your repo! We use ssh below, see GitHub SSH Key Guide for more detail if you need to setup SSH keys first.

git clone<username>/<username>

Once the repo is cloned locally, change directory to it

cd /path/to/my/repo

Now run the Hugo command for creating a new site, with a specific name <sitename> for the output folder to be created in the repo

hugo new site <sitename>

This is a good place to commit and push all changes!

Preliminary Content

We need to add a post before rendering the site! We’ll create a post called my-first-post using the Hugo command new. First make sure you’re in the site directory

cd /path/to/my/repo/<sitename>

Now create the post markdown file

hugo new posts/

Or, equivalently, create a markdown file at /path/to/my/repo/<sitename>/content/posts/ that looks like:

title: "Hello, World!"
date: 2021-10-23
draft: false

Sample post content


Before we can build the site, we’ll need to choose a theme. This choice is important since not all themes have the same set of configuration options. Choose your theme from the vast selection and then add it as a git submodule. For this demo we’ll use the Coder Theme, on which this site’s theme is based.

cd /path/to/my/repo/<sitename>
git submodule add themes/coder

Now we need to specify the theme in the Hugo config file, which is usually located /path/to/my/repo/<sitename>/config.toml. Use your text editor of choice to add the following:

theme = "coder"

Where you can replace "coder" with the name of the theme you chose, if you chose differently. Now the theme should be ready for build! Note that you will need to commit the submodule just like other changes to the repo.


Let’s build the site and serve it:

hugo server -D

The output will tell you where it is being served, likely localhost:1313. Now you’ve built the basics!

Adding a Non-post Page

The documentation is a little thin on this, but many of us would like to have an “About” page or some other page that has non-post content. The process for creating these is very easy! Let’s use the “About” page as an example. Create a file for it at location /path/to/my/repo/<sitename>/content/ with header and content:

title: "About"
date: 2021-10-23
draft: false

I am a Hugo-powered blogger!

Once you save the file, you should notice that Hugo has detected a change, and automatically rebuilt the site! We should add the page to the menu to make it easy to find, which is done in the config file. Note: menu items should be standard across themes; however, check with the documentation of your specific theme if you encounter any rendering oddities. In the config file we’ll add (or modify if exists):

    identifier = "about"
    name = "About"
    url = "/about/"

If you want to add other pages to the menu, this is accomplished by adding another [[menu.main]] item. Once Hugo detects this change and reruns, you should be able to see the “About” menu item and the corresponding page by clicking it.

Workflow and Deployment

Now you have a functioning Hugo project, let’s setup some bells and whistles to get this content online. We will first setup GitHub actions that will build and deploy the site for you, then we will configure GitHub pages. See the Hugo docs for more details.

GitHub Action

GitHub Actions offer a wide array of automation and workflow benefits. Today, we’ll setup a workflow that checks for new commits on main and from pull requests, sets up a Hugo environment, and builds your site. The configuration below is also set such that only after you merge the pull request will the site be deployed. A full example is included at the end of this post.

Next we need to create a YAML file for this workflow at the following location /path/to/my/repo/.github/workflows/gh-pages.yml, and configure it to match the below:

name: GitHub Pages

      - main  # Set a branch to deploy

    runs-on: ubuntu-latest
      group: ${{ github.workflow }}-${{ github.ref }}
      - uses: actions/checkout@v2
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
          hugo-version: '0.88.1'
          extended: true
      - name: Build
        run: hugo --minify --source=locallytrivial
      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        if: ${{ github.ref == 'refs/heads/main' }}
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./locallytrivial/public

The above workflow uses the actions/checkout action to clone your repo content, the peaceiris/actions-hugo action to setup the necessary Hugo dependencies, and the peaceiris/actions-gh-pages action to deploy the site (only on the main branch, which is where commits go after Pull Request is merged).

GitHub Pages

To setup GitHub pages, you’ll go to the GitHub Pages section of your repo settings<username>/<username>, and make sure the “Source” branch is set to gh-pages. This will only be available after you have pushed to master (or merged your first pulln request). You can optionally set a custom domain name here as well! (That step might require editing DNS configurations from your domain host, e.g.

Example Usage: Making a Post

Now you should be all-ready to make a post and deploy the site. This example gives each workflow step to make a sample post titled, “Standup, Hugo!”.

Create a Feature Branch

The first step in a Pull Request workflow is to create a feature branch. See GitHub docs for more on git flow. Make sure you’re on latest main branch

git checkout main
git pull

Now create a branch, with a somewhat descriptive name

git checkout -b post-standup-hugo

Create the Post

Create a new Markdown document for the post /path/to/my/repo/<sitename>/content/posts/ with content:

title: "Standup, Hugo!"
date: 2021-10-23
draft: false
- Code
- Hugo
- Blog Stack

This is a post I created using the GitHub workflow!

Commit, Push, Create Pull Request

Commit and push these changes

git add /path/to/my/repo/<sitename>/content/posts/
git commit . -m "commiting new post"
git push

Now navigate to the GitHub page for your repo and find the branches page:<username>/<username> Find the post-standup-hugp branch and click “New Pull Request”. Enter a somewhat descriptive title and description, then click “Create Pull Request”.

Merge and Deploy (with a button!)

Wait for the build suite to pass, then click “Merge Pull Request”. Once it is merged, the build suite on the main branch will deploy your code to the gh-pages branch! If you do not see your website at https://<username> make sure to double check that the Source branch is set to gh-pages in the repository settings > Pages.

Sit back, and enjoy. You’ve stood up a Hugo blog!