Why Hugo?

On of the many benefits of working in tech is that you’re surrounded by smart people searching for alternatives — I got inspired by a company project that required a landing page to be easily editable, quickly hosted and lightweight. That’s when I found Hugo — a general purpose website framework written in Go. As a static site generator, Hugo is extremely fast to deploy.

Let’s Get To It

Hugo has a well-documented guide here to set things up, with the assumption that you are comfortable with Git and the command line. The example I’ll use is on MacOS and the theme Hugo Minimo.

1. Install Hugo

Install Hugo on your machine using Homebrew

brew install hugo

2. Create a New Site

Navigate to the folder where you want your new site to live. For example, I would like to have mine in the repos folder

cd ~/repos/

Use the command line below to create a new site.

hugo new site your-new-site

3. Select a Theme

Select a theme from themes.gohugo.io, I used Hugo Minimo. You could also download it directly https://github.com/MunifTanjim/minimo/archive/master.zip and move it to themes/

cd your-new-site
git init
git submodule add https://github.com/MunifTanjim/minimo.git themes/minimo

Then, add the theme to the site configuration:

echo 'theme = "minimo"' >> config.toml

4. Site Structure

Alright, now that you’re all set, it’s time to create a new post and understand how Hugo structures the website.

  • Folders and files under content/ will be rendered as web pages organised as follows:
content/
     post/
          post-01.md
          post-02.md
     _index.md
     about.md
  • Images are stored in static/images and can be added to your posts using Markdown

  • The theme is normally organized as default layouts containing “partials” that enrich the content and layout options. Learn more about Hugo particals.

layouts/
     _default/
          baseof.html
          list.html
          single.html
     partials/
     article/
     author/
     head/
     page/
  • To generate a new post, you can either create a new .md file in post/ or use hugo new post/my-first-post.md

  • The newly generated post normally contains the following, and you can customise this by tweaking archetypes/default.md

---
title: "My First Post"
date: 2020-10-17T22:02:43+11:00
hero: /images/hero-my-first-post.jpg
excerpt:
tags:
draft: true
---
This is my first post!

5. Start the Hugo server

With Hugo, changes such as adding new posts, CSS styling and etc. can be instantly viewed locally at http://localhost:1313/ with the following:

-- with draft enabled
hugo server -D
-- without draft
hugo server

6. Customization

Before making the site public, you probably want to make it more personal. config.toml is the good starting point, where you can change the URL, site title, pagination, add additional pages and more.

baseURL = "http://www.example.com"
title = "Your New Site "
theme = "minimo"
Paginate = 5

[menu]
     [[menu.main]]
          identifier = "about"
          Name = "About"
          url = "/about/"
          weight = 0

7. Firebase

You can host your Hugo site virtually anywhere. I chose to use Firebase. You can find a list of more hosting options at the end. Before we begin, you’ll need a Firebase account. If you don’t, you can sign up for free with your Google account.

  • Go to the Firebase console and create a new project (unless you already have a project). You will need to globally install firebase-tools (node.js):
npm install -g firebase-tools
  • Log in to Firebase (setup on your local machine) using firebase login, which opens a browser where you can select your account.
firebase login:ci
  • Visit the URL provided, then log in using a Google account. You’ll need to save this token to a private variable later.

  • In the root of your Hugo project, initialize the Firebase project with the firebase init command:

firebase init

From here:

  • Choose Hosting in the feature question
  • Choose the project you just set up
  • Accept the default for your database rules file
  • Accept the default for the publish directory, which is public
  • Choose “No” in the question if you are deploying a single-page app

By this point you will have some new firebase files within your projecct directory.

Your .firebaserc file should look something like this:

{
  "projects": {
    "default": "your-project-name"
  }
}

Your firebase.json file should look something like this:

{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

8. GitHub Actions

Now that we have Firebase installed and ready to go. We need to add one last step, GitHub Actions. Just to summerize, we will create a workflow that will make github do all the work to compile and push our static html files to Firebase.

  • If you don’t already, push your codebase to your repo. Navigate to GitHub, select your repo and go to “Actions”. Click on the “New Workflow” button and then “set up a workflow yourself”.

  • Name your new workflow, I chose “Deploy”.

  • In the text area below copy and past the following:

name: Deploy to Firebase

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  deploy_to_firebase_hosting:

    runs-on: ubuntu-latest

    steps:
      - name: Checkout the repository
        uses: actions/checkout@master
      - name: Build Hugo
        uses: lowply/[email protected]
      - name: Deploy to Firebase
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only hosting
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_CI_TOKEN }}
  • Press the green “Start Commit” button to commit our new deploy.yml file to our repo.

  • Next, we’ll need to add a secrete to the repo. To do so, navigate to “Settings” and then “Secrets”. Select “New Secret” and give it a name. I chose, FIREBASE_CI_TOKEN. Note, this will need to match the Firebase Token variable in our deploy.yml file (line 26).

  • Remember that Firebase CI token I told you to keep safe? Well, pull that up and paste that code in the “Value” text area. Save your new secret.

  • And now, whenever you commit and push any changes to the repo, your workflow will activate and push your site to firebase.