Blog with Hugo and Github
As it is customary, my first post is about building this website. This post assumes that you have a basic understanding of git, GitHub, and web domains. The focus will be on the tools chosen and integration of these tools to build a static website.
Goals
- Write content in your favorite text editor
- Manage content in source control (git)
- Automate deployment of the content to the website
- Privacy and security of website visitors
Quick tools summary:
Hugo
Hugo is a static site generation tool written in Go. Hugo has strong theme support and a variety of themes.
Features that matter to me:
- Incremental build - Site generation is incremental and blazing fast
- Powerful template support - Go templates
- Privacy compliance - GDPR
- Explicit security model - Security
A full feature list is available here.
There are many static site generators out there, here is a comparison:
Comparisons with other static site generators
| Feature | Zola | Cobalt | Hugo | Pelican |
|---|---|---|---|---|
| Single binary | yes | yes | yes | no |
| Language | Rust | Rust | Go | Python |
| Syntax highlighting | yes | yes | yes | yes |
| Sass compilation | yes | yes | yes | yes |
| Assets co-location | yes | yes | yes | yes |
| Multilingual site | ehh | no | yes | yes |
| Image processing | yes | no | yes | yes |
| Powerful template engine | yes | yes | yes | yes |
| Themes | yes | no | yes | yes |
| Shortcodes | yes | no | yes | yes |
| Internal links | yes | no | yes | yes |
| Link checker | yes | no | no | yes |
| Table of contents | yes | no | yes | yes |
| Automatic header anchors | yes | no | yes | yes |
| Aliases | yes | no | yes | yes |
| Pagination | yes | no | yes | yes |
| Custom taxonomies | yes | no | yes | no |
| Search | yes | no | no | yes |
| Data files | yes | yes | yes | no |
| LiveReload | yes | no | yes | yes |
| Netlify support | yes | no | yes | no |
| Vercel support | yes | no | yes | yes |
| Breadcrumbs | yes | no | no | yes |
| Custom output formats | no | no | yes | no |
Source: zola
Hugo's single binary and Go module based extension mechanism makes it simpler to deploy and integrate it into the gitops based workflow.
Install Hugo
1brew update && brew install Hugo
Pick a theme
To jump-start, your website, select a theme that suits your needs. After reviewing a ton of Hugo themes and experimenting with a few, I finally settled on hugo-clarity. A huge shout out to Chip Zoller and Dan Weru for this awesome theme. Design is clean with no clutter what so ever, and has all the features required for a technical blog. I particularly love the superb rich code block functionality.
There are many ways to install a theme, but I prefer the cool go mod approach:
1hugo new site yourSiteName
2cd yourSiteName
3git init
4hugo mod init yourSiteName
NOTE: You will need the latest Hugo binary and Go installed on the system for this method.
Configure the theme
Most themes provide an exampleSite, copy it over to your root directory, and edit the config.toml. You can find the config.toml for this site here.
1cd yourSiteName
2git clone https://github.com/chipzoller/hugo-clarity /tmp/hugo-clarity
3cp -a /tmp/hugo-clarity/exampleSite/* .
4rm -rf /tmo/hugo-clarity
Customize logo and icon
Create a simple logo and favicon for the website. There are many free to use icons available at flaticon.com. I used draw.io to create the logo and the icons and this favicon generator to generate the website's icons. Unpack the icons into the static folder.
Local testing
Hugo comes with a built-in server that you can use to test your website live:
1# Serve the files, including draft posts
2hugo server -D
To generate the site:
1# Generate content including drafts
2hugo -D
The above command generates the full static content in the public folder,
which can be copied to your webserver.
Github
Create a new empty repository on github for your website and push your content.
1cd yourSiteName
2# Make sure you configured your .gitignore correctly to ignore the addition of
3# unnecessary files.
4git add .
5git commit -s -m "commit comment here"
6git remote add origin "https://github.com/yourUserName/yourSiteName.git"
7git checkout -b initial-commit
8git push origin +initial-commit
Actions and checks
Github support actions to define your deployment workflows. I strongly recommend adding merge checks for your content for the following:
- Hyperlink Check
1# .github/workflows/check-md-links.yml
2name: Check Markdown links
3
4on: push
5
6jobs:
7 markdown-link-check:
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@master
11 - uses: gaurav-nelson/github-action-markdown-link-check@v1
12 with:
13 use-quiet-mode: "yes"
14 use-verbose-mode: "yes"
- Spelling Check
1# .github/workflows/spell-check.yml
2name: Spellcheck Action
3on: push
4
5jobs:
6 build:
7 name: Spellcheck
8 runs-on: ubuntu-latest
9 steps:
10 - uses: actions/checkout@master
11 - uses: rojopolis/spellcheck-github-actions@0.5.0
12 name: Spellcheck
To enable the checks, go to GitHub repository settings -> Branches. Add a branch
protect rule for your main branch and enable the following checks:

Hosting
When I started, I considered using github.io to host the website, looking
a bit further I found vercel and render.
Both of them offer static website hosting for free, with the upside of hosting
APIs if you add services to your website. In the end, vercel's
cli support sealed the deal.
- Create an account using your Github account
- Integrate with GitHub and allow access to your blog repo
- Vercel app will listen for all changes to Github repo and perform deployment
Vercel supports staging and production deployments. Setup the
main branch as the production branch. Render your content by pushing it
to the main branch. To avoid accidental rendering, add the vercel check
to the main branch, as shown in the GitHub section. Vercel Github integration
will automatically do a staging deployment for all pull requests. You can verify
the staging deployment before merging to production branch.
Custom Domains
If you have a custom domain like me, you need to set up a forwarding record with your domain provider. Please note that you need to use the CNAME record for sub-domains like webbook.chamarthy.dev. For more details on configuring custom domains with vercel, refer to the documentation.
Blog Workflow
Once you completed the above steps, you can focus on writing. The following is my workflow:
- Create a branch for your post
1git checkout -b drafts/building-webbook
- Create a new post
1hugo new post/2020-12/building-webbook.md
- Edit the content, I used VS Code with following extensions:
- Test locally using
hugo server -D - Commit and Push after local tests succeeded
1git add .
2git commit -s -m "blog: building webbook"
3git push origin +drafts/building-webbook
- Create a pull request to the
mainbranch - Github actions will take over and give you a blessing to merge
Rebase and Mergeto themainbranch- On merge, vercel application will build the website using Hugo and deploy to your website.
- Check your website for the new content
Summary
With this workflow, you can focus on your writing and enjoy a familiar workflow to manage and publish content to your website.