I tried creating my first website using HUGO . Here, I’ll leave a record of the steps as a memorandum.
Static Site Generators
| Feature | Plain HTML | Jekyll | Hugo |
|---|---|---|---|
| Language Base | HTML/CSS/JS | Ruby | Go |
| Setup | None | Medium | Somewhat Hard |
| GitHub Pages | ◎ (Direct) | ◎ (Official) | ○ (Push after build) |
| Build Speed | – | Slow | Ultra-fast |
| Multilingual | Manual | Partially | ◎ (Standard) |
| Templates/Themes | Manual | Many | Very Many |
| Best For | Small/Free | Medium/Blog | Medium-Large/Multi-lang |
This time, I decided to use Hugo. The key points for this choice were:
- For sites where pages will increase, like a blog or research log, Jekyll or Hugo are suitable.
- I want to support both Japanese and English → Hugo is a good fit.
- Auto-deployment with GitHub Actions is easy with Hugo.
Environment Setup
Installing Hugo
For macOS:
brew install hugo
If you can confirm the version with hugo version, you’re good to go.
Creating a New Site
In your desired location, enter the following command (replace my-website with any name you like):
hugo new site my-website
cd my-website
Selecting a Website Theme
| Theme | Features |
|---|---|
| hugo-coder | Simple & lightweight. Suitable for profile sites. |
| PaperMod | Easy to read & blog format. Popular for academic use. |
| Academic (Wowchemy) | Best for researchers. Supports publication lists and project intros. A bit heavy. |
This time, I chose PaperMod.
After moving to the website directory created above, I cloned the theme with the following commands:
git init
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
This completes the environment setup.
How to Create Web Pages with Hugo
Creating web page content is basically done by editing Markdown files. Based on the created md files, Hugo outputs the static site as HTML.
File Structure
.
├── .github/
│ └── workflows/
│ └── deploy.yml # Automation by means of Github Actions
├── archetypes/
│ └── default.md # Template for markdown files
├── assets/
├── content/ # Create site content here
│ ├── en/ # For English
│ │ │── _index.md # Description for the section's top page
│ │ └── blog/
│ │ │── _index.md # Description for the section's top page
│ │ └── 01-first-post.md # Content for the page
│ └── ja/ # For Japanese
│ ├── _index.md
│ └── blog/
│ │── _index.md # Description for the section's top page
│ └── 01-first-post.md # Content for the page
├── data/
├── hugo.toml # Site configuration
├── i18n/
├── layouts/
├── public/ # Generated static site by Hugo (output)
├── static/
└── themes/
└── PaperMod/
├── ... (Theme files)
Configuration of archetypes/default.md
By setting this up, you can create a template for your markdown files generated by hugo new <file-name>.md.
---
date: '{{ .Date }}'
draft: true
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
type: '{{ .Section }}'
tags: []
categories: []
---
Configuration of hugo.toml
This is the central file for managing the entire Hugo site’s configuration. It determines the site’s appearance, functionality, and structure.
baseURL = 'https://riichisugai.github.io/' # Public URL of the site
languageCode = 'en-us' # Main language of the site
theme = "PaperMod" # Theme design to use
title = 'Riichi Sugai' # Title of the site
relativeURLs = false # Disable relative URLs
canonifyURLs = true # Use absolute URLs
# Explicitly set the default language
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = true
# Multilingual support settings
[languages]
# English page settings
[languages.en]
weight = 1
languageName = "English"
contentDir = "content/en" # Directory where the site's content is located
mainSections = ["blog"]
# English page header menu settings
[[languages.en.menu.main]]
identifier = "blog"
name = "Blog" # Header name displayed on the site
url = "/blog/" # Site directory
weight = 1 # Display order priority
# Japanese page settings
[languages.ja]
weight = 2
languageName = "日本語"
contentDir = "content/ja"
mainSections = ["blog"]
# Japanese page header menu settings
[[languages.ja.menu.main]]
identifier = "blog"
name = "Blog"
url = "/blog/"
weight = 1
[params]
# Display a copy button in code blocks on the page
ShowCodeCopyButtons = true
author = "Riichi Sugai"
# Settings for displaying recent posts on the top page
[params.homeInfoParams]
ShowRecentPosts = true # Show recent posts
RecentPostsCount = 3 # Set number of posts to display to 3
# Validate Top page
[outputs]
home = ["HTML", "RSS", "JSON"]
Creating the Top Page
Create a top page under content/en/ or content/ja..
hugo new content/en/_index.md
hugo new content/ja/_index.md
_index.md functions as the top page and should be prepared for each section.
※ Note
Always use the hugo new command when creating markdown files.
Not doing so can cause bugs in the web page preference and display.
Creating Content
As an example of content to create, let’s make a directory blog.
Create a directory named blog at the same level as the top page, and move into that directory.
- Create a top page
_index.mdin/content/en/blog/
hugo new /content/en/blog/_index.md
Then create a file with the following content.
---
date: '2025-11-01T02:14:44+09:00'
draft: true
title: 'Blog'
type: 'blog'
tags: []
categories: []
---
Here, draft: false indicates the page is published and will be displayed on the web. On the other hand, draft: true means it’s a draft and won’t be displayed.
- Create content
01-first-post.mdin/content/en/blog
hugo new /content/en/blog/01-first-post.md
And at the beginning of the file, add the following:
---
date: '2025-11-01T02:14:44+09:00'
draft: true
title: 'Blog'
type: 'blog'
tags: []
categories: []
---
By having the same header as the top page, each piece of content will be displayed in a card format on the top page. The content itself should follow this header. The writing method follows the usual markdown syntax.
Previewing the Site
To preview the site locally, run the following command in the site’s root directory:
hugo server -D
Then, open http://localhost:1313/ in your web browser to view the site.
The -D option includes pages marked as draft: true in the output.
You can stop the server by pressing Ctrl + C in the terminal.
Publishing on Github.io
To publish the web page, we will use GitHub Pages, a free hosting service provided by GitHub for static sites.
- First, create a public GitHub repository named
<username>.github.io. - From [Settings], set the Default branch to
gh-pages(optional). - In [Settings] > [Pages], set Source to Deploy from a branch, and specify the branch set in step 2.
The web site will be pushed to the gh-pages branch of this repository to publish it in the following steps.
- Build the Hugo site on GitHub’s server (execute the hugo command).
cd publicgit initgit remote add origin https://github.com/<username>/<username>.github.io.gitgit add .git commit -m "Deploy website"git push -f origin gh-pages- Open your browser and navigate to
https://<username>.github.io/to see your published site.
Automating Deployment with Github Actions
To automate the deployment process, we can use GitHub Actions to set up a workflow that automatically builds and deploys the site whenever changes are pushed to the main branch of the source repository.
- Build the site on GitHub’s server (execute the hugo command).
- Extract the contents of the generated public directory.
- Push to the gh-pages branch of the public repository (
<username>.github.io).
Preparation
Source code repository:
riichisugai/hugo-source- This repository contains the source code of the Hugo site.
Public repository:
riichisugai/riichisugai.github.io- This repository is used to publish the generated static site.
Personal Access Token (PAT):
- A token with write access (repo scope) to the public repository.
- This acts as a password for GitHub Actions to push to
riichisugai.github.io.
GitHub Secret:
- A place to securely store the PAT in the source code repository (
hugo-source). - This will be registered as
GH_PAT.
- A place to securely store the PAT in the source code repository (
Steps to Create the Workflow
Step 1: Create the Workflow File
- Navigate to [Settings] > [Developer settings] > [Personal access tokens] > [Tokens (classic)] in GitHub.
- Click [Generate new token]
- Fill in the required fields:
- Note:
Hugo Deploy Token - Expiration: Choose as needed
- Scopes: Select
repo
- Note:
- Click [Generate token] and copy the generated token.
Step 2: Register the Token as a GitHub Secret
- Go to the
riichisugai/hugo-sourcerepository. - Navigate to [Settings] > [Secrets and variables] > [Actions] > [New repository secret].
- Set the name to
GH_PATand paste the copied token into the value field. - Click [Add secret].
Step 3: Create the Workflow YAML File
- In the
riichisugai/hugo-sourcerepository, create a directory.github/workflows/if it doesn’t exist. - Inside this directory, create a file named
deploy.ymlwith the following content:
name: Deploy Hugo site to GitHub Pages
on:
push:
branches:
- main # Trigger on pushes to the main branch
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4
with:
submodules: true # Ensure submodules (themes) are checked out
fetch-depth: 0 # Fetch all history for all branches and tags
persist-credentials: false
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: 'latest'
- name: Generate commit message
id: commitmsg
run: |
# Obtain the list of changed files in the 'content' directory
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD content 2>/dev/null)
if [ -z "$CHANGED_FILES" ]; then
echo "MESSAGE=Deploy site on $(date '+%Y-%m-%d %H:%M:%S')" >> $GITHUB_ENV
else
TITLES=$(echo "$CHANGED_FILES" \
| sed 's|content/||g' \
| sed 's|/_index.md||g' \
| sed 's|.md||g' \
| tr '\n' ', ')
echo "MESSAGE=Update: ${TITLES} ($(date '+%Y-%m-%d %H:%M:%S'))" >> $GITHUB_ENV
fi
echo "Commit message: $MESSAGE"
- name: Build Hugo site
run: hugo --cleanDestinationDir --minify
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{ secrets.GH_PAT }}
external_repository: riichisugai/riichisugai.github.io
publish_dir: ./public
punlish_branch: gh-pages
commit_message: ${{ env.MESSAGE }}
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
Checkout source; with: submodules: truemust need to be included to properly fetch the theme which is a submodule.
Step 4: Execute and Verify the Workflow
- Push the created
deploy.ymlfile to the main branch of thehugo-sourcerepository. - Go to the Actions tab of the
hugo-sourcerepository to see the workflow execution. - If the workflow completes successfully with a green check mark, the auto-deployment is successful.
- Verify that the site is displayed correctly.
That’s the procedure for creating a website with Hugo and publishing it using Github Pages. Enjoy building your site!