Creating a blog with Hugo and GitHub Pages


In this post, we will be creating a simple blog using Hugo, a really fast static site generator and host it for free on GitHub Pages. This guide is Linux focused, but on Windows you can use WSL and follow along if you wish. The final site created is the one you will be reading this post on.

Installing Hugo

I run Arch Linux, where Hugo is available in the community repository. For other distros, checkout their official documentation.

sudo pacman -S hugo

Next, change to the directory where you wish to create the website related files. I generally use /home/github/parimal7 for all my projects.

cd ~/github/parimal7
# hugo new site <name of directory which hugo will create>
hugo new site
The directory structure should look like this:
├── archetypes
│   └──
├── config.toml
├── content
├── data
├── layouts
├── public
├── static
└── themes
# Commit files to git version control
git init
git add .
git commit -m 'Added initial hugo files'

You can find information on the files and folders created by Hugo on this documentation page.

Installing Hugo theme

Themes for Hugo can be found on I will be using Bear Blog theme for my site, instructions for setting up a theme should be similar for most of them.

# Run this in the root directory which we created earlier
# i.e. for me
git submodule add themes/hugo-bearblog

Most themes have an exampleSite folder which you can copy into your directory and edit the files as per your choice. I will be copying Hugo Bear’s example site and do a test run on how the site looks on local server.

# From the root directory i.e.
cp -r themes/hugo-bearblog/exampleSite/. .

This copies over the config.toml file as well as the content and static directories to our root folder.

  1. In the content directory, the file is home page of our site.
  2. Any markdown files created in content directory and having menu=‘main’ in YAML front matter will get a hyperlink in the home page.
  3. Blog posts can be created in content/blog/ directory.

To test the look and feel of the current site, run

# In root directory
hugo server
# This will serve static files from memory at http://localhost:1313/

Editing the config.toml file, files or blog posts is fairly straightfoward. Below is how my config.toml looks for current site:

# Base URL used when generating links to your pages
# Set to the URL for your site
baseURL = ""

# The name of this wonderful theme ;-).
theme = 'hugo-bearblog'

# Basic metadata configuration for your blog.
title = ""
author = "Parimal Prasoon"
copyright = "Copyright © 2022, Parimal Prasoon."
languageCode = "en-US"

# Generate a nice robots.txt for SEO
enableRobotsTXT = true

# Generate "Bearblog"-like URLs !only!, see
disableKinds = ["taxonomy"]
ignoreErrors = ["error-disable-taxonomy"]
  blog = "/:slug/"
  tags = "/blog/:slug"

  # The "description" of your website. This is used in the meta data of your generated html.
  description = "A blog on Emacs, Linux and STEM."

  # The path to your "favicon". This should be a square (at least 32px x 32px) png-file.
  # Hint: It's good practise to also put a "favicon.ico"-file into your "static"-folder.
  favicon = "images/favicon.png"

  # These "images" are used for the structured data templates. This will show up, when
  # services like Twitter or Slack want to generate a preview of a link to your site.
  # See and
  images = ["images/share.png"]

  # Another "title" :-). This one is used as the site_name on the Hugo's internal
  # opengraph structured data template.
  # See and
  title = ""

  # This theme will, by default, inject a made-with-line at the bottom of the page.
  # You can turn it off, but we would really appreciate if you don’t :-).
  # hideMadeWithLine = true

  # By default, this theme displays dates with a format like "02 Jan, 2006", but
  # you can customize it by setting the `dateFormat` param in your site's config
  # file. See [Hugo's Format function docs](
  # for details. An example TOML config that uses [ISO
  # 8601]( format:
  # dateFormat = "2006-01-02"

When the static sites are being served on localhost, any changes to files or static files will get reflected almost immediately. Quite fast and frictionless way to check how changes look before you deploy them.

Deploying to Github Pages using Github Actions

# Run this in the root directory

The above command creates all the static HTML files which we will publish into a public directory. The public directory can then be published to whichever hosting site you wish. Hugo has a good summary for the same:

  1. Creata a GitHub account if you don’t have one.
  2. Create a new repository <your-github-username>
  3. Create the below file at .github/workflows/gh-pages.yml (i.e. in your root site directory)
  4. If you have a custom domain (i.e. for me), also create a CNAME file under static directory with your domain name as it’s only content.
name: GitHub Pages

	  - master  # Set a branch name to trigger deployment

	runs-on: ubuntu-20.04
	  contents: write
	  group: ${{ github.workflow }}-${{ github.ref }}
	  - uses: actions/checkout@v3
		  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
		  hugo-version: '0.85.0'

	  - name: Build
		run: hugo --minify

	  - name: Deploy
		uses: peaceiris/actions-gh-pages@v3
		# If you're changing the branch from main,
		# also change the `main` in `refs/heads/main`
		# below accordingly.
		if: ${{ github.ref == 'refs/heads/master' }}
		  github_token: ${{ secrets.GITHUB_TOKEN }}
		  publish_dir: ./public

Finally, we can push our code to GitHub.

  1. git remote add origin
  2. git branch -M master
  3. git push -u origin master

This will push all our code to the master branch. Due to certain limitations of above Github action (check here), we need to do a couple of more steps before you can see your site at <username>

First, make another commit and push to GitHub.

Second, in Github settings for your repository, i.e.


Pick the Source branch as gh-pages.

Finally, you will be able to find your site hosted on <username>