iTranslated by AI
Build a Website with a Custom Domain Using Hugo, GitHub Pages, and GitHub Actions
Introduction

As I wrote more articles on various web services like Zenn, Qiita, and note, I suddenly wanted my own blog where I could write about miscellaneous topics exactly how I liked. When I researched how to build one, using a Static Site Generator (SSG) seemed the quickest way, and I chose Hugo because it appeared to be the easiest among them to set up.
For deployment, I wanted a simple process, so I chose GitHub Pages. The deciding factors were that it supports everything from custom domain assignment to HTTPS for free, and I could use GitHub, which I am already familiar with, as the deployment target.
While I was able to build my blog with Hugo and publish it on GitHub Pages, I realized that manually building and deploying every time I updated the content or wrote a new article was surprisingly tedious. Therefore, I automated the build and deploy process using GitHub Pages action.
By following these steps, I was able to create an environment where I could focus solely on writing and updating my blog. Aside from designing the website, I could set up a satisfying blogging environment with Hugo just by performing a few simple tasks. I have summarized those steps here.
By the way, here is the blog I actually created using the steps in this article:
Installing Hugo on Your PC
I installed Hugo using Chocolatey on Windows and Homebrew on Mac. The installation methods using Chocolatey or Homebrew are available in the official documentation.
# Install Hugo on Mac using Homebrew
brew install hugo
# Install Hugo on Windows using Chocolatey
choco install hugo -confirm
# If you want to modify the website design using Sass/SCSS,
# install Hugo with Chocolatey using the following command
choco install hugo-extended -confirm
Building Your Website with Hugo
Creating a Hugo Project
You can generate a Hugo project folder with the following command:
hugo new site <path-to-project-folder>
The default configuration format for Hugo is TOML, but you can also generate it in JSON format by adding the -f option, like hugo new site <path-to-project-folder> -f json.
As mentioned later, some Hugo themes provide sample configuration files in JSON. In such cases, keeping your configuration in JSON might make it easier to adjust various settings.
Finding a Website Theme
A theme is a design template for your website. Themes are published on Hugo Themes, where you can choose one that suits your preferences. In Hugo, you can customize or replace theme content, allowing you to modify parts of the design to your liking later on.

Page when accessing Hugo Themes
Once you find a theme you like, click the Download button and take note of the theme's GitHub URL.

Theme page for Kiera
Applying a Theme to Your Hugo Project
While the application method for each theme is introduced in the official documentation, it basically involves running the following commands at the root of your Hugo project folder and adding theme to your configuration file.
git clone <Theme GitHub URL> themes/<theme-name> --depth=1
echo 'theme = "<theme-name>"' >> config.toml
Almost all themes use the same application method. For example, if you want to apply PaperMod, the theme I chose, you would run the following commands:
git clone https://github.com/adityatelange/hugo-PaperMod themes/hugo-PaperMod --depth=1
echo 'theme = "hugo-PaperMod"' >> config.toml
You are now ready to start building your website.
Building Your Website
Each theme has an exampleSite folder that serves as a helpful reference for creating your Hugo website. At first, you can proceed smoothly by copying and pasting various files from the exampleSite folder into your own project and modifying them as you go.
While the exampleSite folder is usually located at the root of the GitHub project, some themes manage it in a separate GitHub branch. PaperMod, which I adopted, manages it in the exampleSite branch.
Since such details should be listed on the Hugo theme page, I recommend checking where the exampleSite folder is located and what settings are available beforehand. To check the actual appearance of your website, run the following command at the root of your Hugo project folder:
hugo server
While hugo server is running, if you change website settings or add articles, a build will be executed automatically, allowing you to always check the latest appearance of your website. Additionally, any errors will be output to the console, so you can proceed with creating your website while making corrections as needed.
Setting up the Deployment Environment on GitHub
Once you have built your website, the next step is to deploy it. In this guide, we will use GitHub Actions for deployment, so the remaining tasks will be carried out on GitHub. For those interested, the manual deployment procedure without using GitHub Actions is introduced in the official documentation.
The advantages of using GitHub Actions for deployment include:
- It saves the effort of manually executing multiple commands for every deployment.
- Automation helps prevent command errors during deployment.
- A consistent Hugo build environment is always available.
Initially, I also deployed manually on my Mac following the official documentation. However, when I performed deployment tasks in a Windows environment, an SRI-related error occurred during production deployment, resulting in a bug where the stylesheet was not applied to the website.
Ultimately, the cause wasn't entirely clear, but switching to deployment via GitHub Actions fixed it. Once you can deploy via CI, you no longer need to worry about such behavioral differences caused by different execution environments.
Creating a Repository to Deploy Your Website
Follow the official documentation to create a repository for deploying your website. In this article, we treat the Hugo project repository separately from the deployment repository, so we will also create a new repository for the Hugo project.
In this guide, we assume the Hugo project repository is named hugo-blog. Register the remote repository information in your Hugo project using the following commands:
# Create a Git repository at the root of the Hugo project folder
git init
# Register the Hugo project repository information (the GitHub URL for hugo-blog)
git remote add origin <URL of the Hugo project repository>
Setting up an environment to automate Hugo build and deployment with GitHub Actions
In this case, we want to deploy from the Hugo project repository hugo-blog to the deployment repository, so first, we register a deploy key in the deployment repository. After registering the deploy key following the official documentation, register the private key in the secrets of the hugo-blog repository.
Register the secret according to the official documentation. In this guide, we assume that the private key is registered with the name ACTIONS_DEPLOY_KEY.
Next, introduce the GitHub Pages action to set up an environment to automate the Hugo build and publishing process.
Add a workflow file to the hugo-blog repository, referring to the Getting started guide for the GitHub Pages action. Only the - name: Deploy section needs to be modified to point to the deployment repository.
name: github pages
on:
push:
branches:
- main # Set a branch name to trigger deployment
jobs:
deploy:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
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
with:
hugo-version: '0.78.2'
- name: Build
run: hugo --minify
# - name: Deploy
# uses: peaceiris/actions-gh-pages@v3
# with:
# github_token: ${{ secrets.GITHUB_TOKEN }}
# publish_dir: ./public
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
external_repository: nikaera/nikaera.github.io
publish_branch: main
cname: nikaera.com
The various parameters set in the - name: Deploy section are as follows:
| Key | Description |
|---|---|
| deploy_key | Private key used for deployment |
| external_repository | Remote repository for deployment |
| publish_branch | Branch of the remote repository for deployment |
| cname | Custom domain name to be set |
Set the private key registered in secrets to deploy_key. In external_repository, specify the deployment repository for the Hugo build in the format <username>/<repository-name>. publish_branch is the branch name to be used for deployment. Specify the domain name you want to set in cname. You can check the details of cname here.
Update DNS settings with the values configured in the custom domain
When using a custom domain for GitHub Pages, you need to configure a CNAME record or an A record in the DNS settings for the corresponding domain. Set it up according to the official documentation.
Additionally, after setting up the custom domain, it is recommended to enable the Enforce HTTPS setting in the deployment repository unless there is a specific reason not to.
The configuration work is now complete. Next, we will check if the build and deployment are performed via GitHub Actions by actually updating the Hugo project and pushing it to the hugo-blog repository.
Confirm that automatic deployment occurs when the Hugo project is updated
The Hugo project should already have the GitHub URL of the hugo-blog repository set as origin, so let's try pushing to the hugo-blog repository as follows.
# Push the Hugo project to the hugo-blog repository
git add -A
git commit -m "initial commit"
git push origin main
Next, check the Actions tab of the GitHub repository to see if the GitHub Pages action workflow is running.

GitHub Pages actions successful execution
After confirming that the workflow has run successfully, check the status of the deployment repository.

Confirming that the latest Hugo build is pushed to the deployment repository
The latest commit message should include a comment like deploy: <username>/hugo-blog@<commit-hash>. Clicking the link in the comment should take you to the confirmation screen for the latest commit in the hugo-blog repository.
Once you have confirmed this, verify that the website looks the same on GitHub Pages as it did when you were checking it with hugo server locally.
If the deployment repository name is <username>/<username>.github.io, you can access the website at https://<username>.github.io. In my case, it is https://nikaera.github.io. At that time, if you can also confirm that it redirects to the custom domain, then the custom domain settings are also correctly reflected.

Page displaying correctly and accessible via custom domain
If the intended page is displayed upon access, everything is fine. Now, by simply pushing your Hugo project to the hugo-blog repository after updating your website, you can automatically update your own website.
Conclusion
While I used Hugo as an example this time, the GitHub Pages action introduced in this article supports various SSGs. Therefore, if you feel that you have reached the limits of customization with Hugo, it is also possible to switch to something like Next.js or Gatsby.
Furthermore, with Hugo, you can write articles in Markdown without much thought and the build is fast, so I felt it was perfect for quickly setting up your own website.
On an unrelated note, because I included insights on building a website with Hugo, the amount of text ended up being nearly double what I intended... I need to become able to write concise and easy-to-understand sentences.
Reference Links
- The world’s fastest framework for building websites | Hugo
- Complete List | Hugo Themes
- About GitHub Pages - GitHub Docs
- GitHub Pages action
- Install Hugo | Hugo
- Quick Start | Hugo
- Host on GitHub | Hugo
- GitHub Pages | Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live.
- Managing deploy keys - GitHub Docs
- Encrypted secrets - GitHub Docs
- Managing a custom domain for your GitHub Pages site - GitHub Docs
- Securing your GitHub Pages site with HTTPS - GitHub Docs
Discussion