This short article aims to address issues I encountered during hosting personal static blog on Github Page.

Problem Description

Github Page provides three different ways to host a static personal website, for free.

  • host in /docs folder
  • host in gh-pages branch
  • host in master branch

However, in the case of personal blogs, i.e. using repo <github_username>.github.io limits the option to just build the website on master branch.

It indeed created some minor issues on publishing flow and setup when I switched from jekyll to hugo, and it is not that straight-forward on the official docs (they are great docs), hence this article.

Solution

1. Install Hugo and necessary notes

Click to view offical docs.

Docs are pretty good, and IMHO Hugo has the most UI friendly and comprehensive docs among its competitors.

More docs here on hosting.

Note in the second last section, build and publish on master branch is omitted because

Steps should be similar to that of the gh-pages branch, with the exception that you will create your GitHub repository with the public directory as the root.

Not cool! Especially inconvenient for people like me, who often enjoys blindly following instructions in a tutorial or documentation.

So I have to read the gh-pages section carefully, and made some tweaks.

2. Understand the structure

The website is built when we run the command hugo at project root, the project root initiated from hugo new site <project_name>, all the static content are automatically stored in public folder by default.

In the official instructions, they git worktree add the gh-pages to make it become a linked worktree to the main git worktree, and then hosted the content of public folder there. This is just like having a mini-repo in a repo (not accurate at all but you get the idea).

In order to have the static content in public at the project root on master branch, we first switch to a separate branch, called builder.

Then we build the project by running hugo, by adapting the command in the docs, we could make the master branch become the mini-repo we want, set up stream to master as well.

git worktree add -B master public origin/master

Checkout to local master branch by simply cd public, and do git push, use --force if necessary.

Remember to push your changes in builder branch to remote as well.

In summary, use builder branch to write, build and publish the static content, use master branch to host on Github Pages

3. For people who are lazy

For those who are lazy to read, or for lazy publication, I have the following deployment script, I copy-paste the entire thing here because I want to see how it looks like when a large chunk of code is rendered using this Hugo Theme.

#!/bin/sh

if [[ $(git status -s) ]]
then
    echo "The working directory is dirty. Please commit any pending changes."
    exit 1;
fi

echo "Deleting old publication"
rm -rf public
mkdir public
git worktree prune
rm -rf .git/worktrees/public/

echo "Checking out gh-pages branch into public"
git worktree add -B master public origin/master

echo "Removing existing files"
rm -rf public/*

echo "Generating site"
hugo

echo "Copy README.md"
cp README.md public/README.md

echo "Updating master branch"
cd public && git add --all && git commit -m "Publishing to github personal page master branch"

git push

echo "Updating builder branch"
cd ../
git push

Create a deploy.sh file at project root and copy paste the above code in.

Check the original script in my repo.

Then follow the steps below:

  • always work on builder branch locally

  • preview blogs with hugo serve

  • commit your changes on local builder branch

  • run bash deploy.sh

Side Note

I originally wanted to write a detailed comparison and user experience between hugo and jekyll, but I think similar articles are all over the Internet, so never mind.

In short, hugo is more architecturally-pleasing to me, but requires some simple tweaks. I also learned git worktree because of this, it is pretty cool.

jekyll is easier to setup, and to publish as well, but it is slow to build, it does not really matter to me at this point because I only have one aritcle, but I do not like to see a long list of red/green git status result (weirdo alert!).