Looking back at my first post in Bahasa Indonesia, I said that I was using Hugo to build this blog. So in this post I will share my documentation about it here.


Below are the main goals of this post:

  • Installing Hugo
  • Creating a Site with Hugo
  • Deploying the site using GitHub pages


There are some prerequisites needed to accomplish these goals:

  • A GitHub account
  • Familiarity with CLI commands and basic Git workflow
  • Git Bash for Windows users

If you don’t meet any of these prerequisites, just follow along!

Installing Hugo

First thing first, we’ll need the Hugo executable binary, which you can grab it here.

Pick your Hugo version according to what OS you’re running. There is also the extended version, which you should use if you’re building your own theme or picking a theme that uses Sass/SCSS.

Once the download is completed, just extract it somewhere on your system.

$ ls -l
total 47488
-rw-r--r-- 1 Fahmi FJ 197121    11357 Mar 22 00:17 LICENSE
-rw-r--r-- 1 Fahmi FJ 197121    12345 Mar 22 00:17 README.md
-rwxr-xr-x 1 Fahmi FJ 197121 48599040 Mar 22 01:04 hugo.exe

Let’s see if the executable works by checking its version:

$ hugo.exe version
hugo v0.82.0-9D960784+extended windows/amd64 BuildDate=2021-03-21T17:28:04Z VendorInfo=gohugoio

At this time, Hugo’s binary is not available in the system-wide, in other words it’s couldn’t be called outside the current directory where you extracted it. So we’ll add the folder path where the binary lives on to what is known as PATH variable.

System-wide in Windows

For Windows users, let’s create a folder called bin in C:/ .

C:\>mkdir bin

Once the folder is created, move your Hugo binary into it.

C:\>dir bin
 Volume in drive C is Windows
 Volume Serial Number is AC06-7D93

 Directory of C:\bin

13/06/2021  08:07    <DIR>          .
13/06/2021  08:07    <DIR>          ..
22/03/2021  01:04        48.599.040 hugo.exe
               1 File(s)     48.599.040 bytes
               2 Dir(s)  57.909.837.824 bytes free

After that, hit Win + R on your keyboard, type the following command and hit enter:

rundll32.exe sysdm.cpl,EditEnvironmentVariables

You should see a window titled “Environment Variables”. Now we’re going to edit the Path variable there.


On the edit window, add a new path and type C:\bin.


After that, just hit all the OK button.

Then re-open your Windows terminal and run hugo version. If it returns the same output as previous one, then go to the next section.

System-wide in Linux

I know those who use Linux probably already know how to 😁.

For Linux users, let’s create a folder called bin under /home/username/.local/[here].

$ mkdir -p ~/.local/bin

Then move your Hugo binary into the newly created bin folder.

$ mv /previous/path/of/hugo ~/.local/bin/hugo

Next, open your .bashrc or .zshrc file which is located at /home/username/.(zsh|bash)rc with your favorite text editor such as vim, and then simply add these lines at the top of your .bashrc/.zshrc file.


Re-open your terminal and run hugo version from any directory and see if it’s returns the version.

Creating First Site

We can create a site in anywhere by issuing the command below.

$ hugo new site [site-name]

I recommend you to create a site in a specific folder such as workspace or something like /workspace/your.blog.domain.com

For now, let’s call our new site my-blog.

$ hugo new site my-blog
Congratulations! Your new Hugo site is created in C:\Users\fahmi\Desktop\test\my-blog.

Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
   Choose a theme from https://themes.gohugo.io/ or
   create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
   with "hugo new <SECTIONNAME>\<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.

We see that Hugo creates a new folder called my-blog at C:\Users\fahmi\Desktop\test\my-blog, and this my-blog has the following directory structure:

├── archetypes
│   └── default.md
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes

We can host that site locally by typing hugo server within my-blog directory. By default, the site is hosted at http://localhost:1313/.

$ cd my-blog
$ hugo server

For now, it’ll be empty because we haven’t added any content yet.

For site configuration (config.toml), I’ll recommend you to use YAML format over TOML . So if you want to change the configuration format to YAML, just delete the previous my-blog and recreate it with the following command:

$ rm ./my-blog/ -rfi # becareful with this or just delete it from explorer
$ hugo new site my-blog -f yml

Using a Theme

Since my blog uses a theme called PaperMod, we’ll be using that too here. For other themes, have a look at https://themes.gohugo.io/.

To add the PaperMod theme by cloning it into the my-blog/themes/ directory/

$ git clone https://github.com/adityatelange/hugo-PaperMod themes/PaperMod --depth=1

Then replace/overwrite our config.yml with this one, and modify the value of baseUrl and theme to these:

baseURL: ""
theme: PaperMod

Let’s see how it looks like by visiting http://localhost:1313 on the browser after we run this command.

$ hugo server

Creating First Post

We can create a new post by issuing the following command:

$ hugo new post/new-post.md

You can edit new-post.md after that, the file should be under my-blog/content/post/[here].

$ ls -l my-blog/content/post/
total 1
-rw-r--r-- 1 Fahmi FJ 197121 70 Jun 13 09:34 my-post.md

To see your post in the site, change the value draft from true to false:

title: "My Post"
date: 2021-06-13T09:34:43+07:00
draft: false

My first post

It should be on your site now.

Publish Your Site on GitHub

One thing you need to know is that when you run $ hugo server, Hugo generates all the site resources (html, images, etc.) and serves them directly from memory. But, if you just run $ hugo, Hugo generates all the site resources under the public folder (my-blog/public/[here]).

├── archetypes
│   └── default.md
├── config.yaml
├── content
├── data
├── layouts
├── static
└── themes

These files in the public folder are the files that we are going to publish on GitHub. We can simply upload all the files in the public folder into a GitHub repository.

But, before that, you have to change your site’s base URL in config.yml to:

baseURL: "https://[your_user_name].github.io/my-blog/"

For example, my username is fahmifj , so my config would be:

baseURL: "https://fahmifj.github.io/my-blog/"

Once you done with the config, type hugo within the root directory of your site to re-generate all the site resources.

$ hugo
Start building sites …

                   | EN | FR | FA
  Pages            | 14 | 10 | 10
  Paginator pages  |  0 |  0 |  0
  Non-page files   |  0 |  0 |  0
  Static files     |  0 |  0 |  0
  Processed images |  0 |  0 |  0
  Aliases          |  3 |  0 |  1
  Sitemaps         |  2 |  1 |  1
  Cleaned          |  0 |  0 |  0

Total in 147 ms

Now, let’s navigate to Github and create a new repository called my-blog. Once the repo is created, click on Upload an existing file.


Then simply drag and drop all the files from the my-blog/public folder there.


Once all the files are uploaded, commit the changes. I’ll just leave the default commit message.


After that, let’s head to the repository settings and find the Github Pages menu or visit https://github.com/your-username/my-blog/settings/pages.

Since we’ll host this whole repository using GitHub pages, we need to define our “Source” which is the root directory of main branch, and then click on the Save button.


Once you done with that, navigate to https://yourusername.github.io/my-blog, and you should see your site there.


If you don’t see it or the page returns a 404 error, then just wait for a few minutes more because our site needs to be cached by the Internet.

Deployment Script

Finally, we’re going to (semi) automate the deployment process using a bash script.

Let’s go back to the directory of my-blog and then initialize public folder as a git repository. We’ll also add the public folder as a submodule.

$ cd public
$ git init
$ git remote add origin https://github.com/your-username/my-blog.git

Now let’s create a deployment script at the site root directory and name it as deploy.sh.


echo -e "\033[0;32mDeploying blog to GitHub...\033[0m"

# Clean public folder
hugo --cleanDestinationDir

# Go to to public folder
cd public/

# Add untracked files, hide output
git add -A > /dev/null

# Generate a fixed commit message with date and time
msg="[`date "+%R %d-%h-%Y"]` Site update"
# Check for additional commit message
read -p "Add commit message: " add_msg
if [ "$add_msg" != "" ]
	msg="$msg - $add_msg"

git commit -m "$msg"

# Deploy
git push -u origin main

# Go back to the root directory
cd ../

You can run the script on Windows if you have Git Bash installed or WSL.

Let’s create another post to test the deployment script.

$ hugo new post/second-post.md
$ echo 'This is second post' >> content/post/second-post.md

Don’t forget to change the value of draft from true to false, here is a small trick with sed.

$ sed -i 's/draft: false/draft: true/g' content/post/second-post.md

Now we can run the script after giving it execute permission.

$ chmod +x deploy.sh
$ ./deploy.sh
Deploying blog to GitHub...
Start building sites …

                   | EN | FR | FA
  Pages            | 15 | 10 | 10
  Paginator pages  |  0 |  0 |  0
  Non-page files   |  0 |  0 |  0
  Static files     |  0 |  0 |  0
  Processed images |  0 |  0 |  0
  Aliases          |  3 |  0 |  1
  Sitemaps         |  2 |  1 |  1
  Cleaned          |  0 |  0 |  0

Total in 155 ms
Add commit message:
[main af4c483] [11:00 13-Jun-2021] Site update
 9 files changed, 459 insertions(+), 8 deletions(-)
 create mode 100644 post/second-post/index.html
Enumerating objects: 27, done.
Counting objects: 100% (27/27), done.
Delta compression using up to 8 threads
Compressing objects: 100% (13/13), done.
Writing objects: 100% (15/15), 3.54 KiB | 1.77 MiB/s, done.
Total 15 (delta 9), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (9/9), completed with 7 local objects.
To https://github.com/fahmifj/my-blog.git
   f7141a3..af4c483  main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

And the repo should be updated.


That’s it!

This is how I deployed my site on my first try. However, this is an inefficient method because it wastes your bandwidth. Therefore, in the next post, let’s employ GitHub action 😼.

[Updated on 2021-11-01]