Featured image of post Hugo + Stack + GitHub Pages Blog Setup Guide

Hugo + Stack + GitHub Pages Blog Setup Guide

Hugo + Stack + GitHub Pages Blog Setup Guide

A complete guide to building a personal blog with Hugo + Stack theme and deploying it to GitHub Pages.

This guide covers both new Stack (v4.x, split .toml config format) and legacy (v3.x, single hugo.yaml) configuration differences, with annotations where key differences exist.


Environment Setup

Install Git

  1. Go to the Git website to download and install: https://git-scm.com/downloads
  2. Use all default options during installation

Install Hugo (Extended Version)

  1. Go to Hugo GitHub Releases: https://github.com/gohugoio/hugo/releases
  2. Choose the extended version (marked with extended) โ€” the Stack theme requires extended SCSS compilation support
  3. Windows users: download hugo_extended_xxx_windows-amd64.zip and extract hugo.exe

This guide was written using Hugo v0.161.1 and Stack theme v4.0.2.

GitHub Account

  • Register a GitHub account: https://github.com
  • It’s recommended to enable two-factor authentication (2FA) โ€” you can install the Authenticator 2FA Client plugin in Edge

Create a Hugo Site

Initialize the Project

Open a terminal in the directory where hugo.exe is located (type cmd or powershell in the address bar) and run:

1
2
3
4
5
# Create a new site
hugo new site myblog

# Enter the site directory
cd myblog

Generated file structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
myblog/
โ”œโ”€โ”€ archetypes/    # Article templates
โ”œโ”€โ”€ assets/        # Static assets (images, CSS, JS)
โ”œโ”€โ”€ content/       # Blog content (articles)
โ”œโ”€โ”€ data/          # Data files
โ”œโ”€โ”€ i18n/          # Multilingual support
โ”œโ”€โ”€ layouts/       # Layout templates
โ”œโ”€โ”€ public/        # Build output (generated by hugo command)
โ”œโ”€โ”€ static/        # Static files (copied directly to public)
โ”œโ”€โ”€ themes/        # Themes
โ””โ”€โ”€ hugo.toml      # Site configuration

Test the Default Site

1
hugo server -D

Visit http://localhost:1313/ in your browser. The page will be basic (no theme). Press Ctrl + C to stop the server.


Configure the Stack Theme

Download the Theme

  1. Go to the Stack theme GitHub: https://github.com/CaiJimmy/hugo-theme-stack
  2. Download the latest Release archive (or click “Download ZIP”)
  3. Extract to the site’s themes/ directory
1
2
myblog/themes/
โ””โ”€โ”€ hugo-theme-stack-4.0.2/   # Folder with version number

Configure Theme Files โ€” Critical Step

This is the step where errors are most likely to occur. The new Stack (v4.x) and legacy (v3.x) have completely different file structures:

Comparison Legacy Stack (v3.x) New Stack (v4.x)
Example site folder name exampleSite/ demo/
Config files Single hugo.yaml Multiple .toml files in config/_default/
Theme reference theme: hugo-theme-stack [[module.imports]] (Hugo Modules)

New Version (v4.x) Steps:

Step 1: Copy Configuration Files

1
2
3
4
5
# Create config/_default directory
mkdir -p config/_default

# Copy all config files from demo
cp themes/hugo-theme-stack-4.0.2/demo/config/_default/*.toml config/_default/

After copying, config/_default/ contains 6 config files:

File Purpose
hugo.toml Base config (baseURL, title, pagination, permalinks, etc.)
languages.toml Multilingual configuration
markup.toml Markdown rendering config (code highlighting, TOC, etc.)
menu.toml Menu config (navigation bar, social links)
params.toml Theme parameters (sidebar, comments, widgets, etc.)
related.toml Related content recommendation config

Step 2: Change Theme Reference Method

Open config/_default/hugo.toml, find:

1
2
[[module.imports]]
    path = "github.com/CaiJimmy/hugo-theme-stack/v3"

Replace with:

1
theme = "hugo-theme-stack-4.0.2"

This traditional method doesn’t require Go environment or Hugo Modules, making it simpler and consistent with this guide.

Step 3: Handle Root hugo.toml Conflict

The root hugo.toml and config/_default/hugo.toml will conflict. Back up or delete the root file:

1
mv hugo.toml hugo.toml.bak

Step 4: Copy Example Content

1
2
3
4
5
# Back up existing content (if any)
mv content content_backup

# Copy demo content
cp -r themes/hugo-theme-stack-4.0.2/demo/content .

Step 5: Copy Avatar and Static Assets

1
2
mkdir -p assets/img
cp themes/hugo-theme-stack-4.0.2/demo/assets/img/avatar.png assets/img/

Legacy Version (v3.x) Steps:

  1. Enter the theme’s exampleSite/ folder
  2. Copy the content folder and hugo.yaml to the site root
  3. Delete the root hugo.toml (since you now have hugo.yaml)
  4. Confirm that the theme field in hugo.yaml matches the theme folder name (version number removal recommended)

Verify by Starting

1
hugo server -D

Visit http://localhost:1313/ in your browser. You should now see the complete Stack theme (with sidebar, search, example articles, etc.).

If the page is incomplete, check the terminal for WARN messages (e.g., “Search page not found”, “Archives page not found”). This is usually because example content wasn’t copied.


Custom Configuration

Basic Information

Edit config/_default/hugo.toml (new version) or hugo.yaml (legacy):

1
2
baseURL = "https://your-username.github.io/"
title   = "My Blog"

If your primary language is Chinese, it’s recommended to set:

1
2
defaultContentLanguage = "zh-cn"
hasCJKLanguage         = true   # Set to true for Chinese/Japanese/Korean

Edit config/_default/params.toml (new version) or the params.sidebar section in hugo.yaml:

1
2
3
4
[sidebar]
    emoji    = "โœ๏ธ"
    subtitle = "Your personal tagline"
    avatar   = "img/avatar.png"
  • Place the avatar image at assets/img/avatar.png
  • Choose emojis from emojiall.com

Edit config/_default/menu.toml (new version) or the menu.social section in hugo.yaml:

1
2
3
4
5
[[social]]
    identifier = "github"
    name       = "GitHub"
    url        = "https://github.com/your-username"
    params.icon = "brand-github"

Icon names reference: Tabler Icons (use brand-xxx format).

Comment System

Stack supports multiple comment systems. Here’s an example using utterances (based on GitHub Issues, no extra registration needed):

1
2
3
4
5
6
7
8
[comments]
    enabled  = true
    provider = "utterances"

    [comments.utterances]
        repo      = "your-username/your-username.github.io"
        issueTerm = "pathname"
        label     = ""

For more comment system configurations, see the theme documentation: https://stack.jimmycai.com/config/comments

1
2
[footer]
    since = 2026

Creating Articles

Article Structure

The Stack theme recommends each article in its own folder with index.md and image assets:

1
hugo new content post/my-first-article/index.md

Generated directory structure:

1
2
3
content/post/my-first-article/
โ”œโ”€โ”€ index.md      # Article content
โ””โ”€โ”€ image.jpg     # Article image (optional)

Article Front Matter Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
---
title: My First Article
date: 2026-05-12
description: Article summary description
tags:
  - Hugo
  - Blog
categories:
  - Tutorial
image: image.jpg   # Article cover image (optional)
---

Deploy to GitHub Pages

Create a GitHub Repository

  1. Log in to GitHub, click New repository
  2. Repository name: your-username.github.io (must match exactly)
  3. Select Public (GitHub Pages free tier requires public)
  4. Do not check “Add a README file”

Manual Deployment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 1. Build the static website (output to public/)
hugo -D

# 2. Enter the public directory
cd public

# 3. Initialize Git and push
git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/your-username/your-username.github.io.git
git push -u origin main

After pushing successfully, visit https://your-username.github.io/ to see your blog (the first time may take 1-2 minutes).

Automatic Deployment (GitHub Actions)

Manually building and pushing every time is tedious. Use GitHub Actions to automatically build and deploy when you push code.

Step 1: Create a Source Repository

In addition to the username.github.io deployment repository, create a source repository (e.g., myblog) and push the entire Hugo project to it:

1
2
3
4
5
6
7
# In the site root directory (not inside public/)
git init
git add .
git commit -m "init hugo site"
git branch -M main
git remote add origin https://github.com/your-username/myblog.git
git push -u origin main

Step 2: Create GitHub Actions Workflow

Create .github/workflows/deploy.yml in the site root:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
name: Deploy Hugo site to GitHub Pages

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: true
          fetch-depth: 0

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'
          extended: true

      - name: Build
        run: hugo --minify

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v4
        with:
          personal_token: ${{ secrets.PERSONAL_TOKEN }}
          external_repository: your-username/your-username.github.io
          publish_branch: main
          publish_dir: ./public

Step 3: Configure GitHub Token

  1. Go to GitHub โ†’ Settings โ†’ Developer settings โ†’ Personal access tokens โ†’ Tokens (classic)
  2. Generate a new Token with repo and workflow permissions
  3. Copy the generated Token
  4. Go to your source repository โ†’ Settings โ†’ Secrets and variables โ†’ Actions โ†’ New repository secret
  5. Name: PERSONAL_TOKEN, Value: paste the Token

From now on, every git push to the source repository’s main branch will trigger GitHub Actions to automatically build and deploy to username.github.io.

Tip: Enable Automatic lastmod Add the following to config/_default/hugo.toml (new version) or hugo.yaml (legacy):

1
2
3
enableGitInfo = true
[frontmatter]
  lastmod = [":git", ":fileModTime"]

This will automatically display the Git commit time as the last modified time for articles. This requires fetch-depth: 0 in the GitHub Actions checkout step (already included in the configuration above).


FAQ

Q1: Page is blank/incomplete after starting?

Check whether you copied the demo’s content folder. Missing example pages (search, archives, etc.) will cause the theme to display incompletely.

Q2: hugo server throws “Theme not found” error?

  • New version: Check that theme = "xxx" in config/_default/hugo.toml matches the folder name under themes/
  • Legacy: Check the theme field in hugo.yaml

Q3: Root hugo.toml conflicts with config/_default/hugo.toml?

Delete or back up the root hugo.toml. Hugo will prioritize config files under config/_default/.

Q4: Push to GitHub fails?

This may be a network issue. Try removing the proxy:

1
2
git config --global --unset http.proxy
git config --global --unset https.proxy

Q5: What is the new [[module.imports]]?

The new Stack uses Hugo Modules (Go modules) to import the theme by default, which requires a Go environment. If you don’t want to deal with Go, simply switch to the traditional theme = "theme-folder-name" method.

Q6: Blog styles are broken after deployment?

Check that baseURL is correctly set to https://your-username.github.io/ (note the trailing /). An incorrect baseURL will cause CSS/JS resources to fail to load.


References

comments powered by Disqus