For some time now, I’ve been considering starting a blog to share my thoughts and projects with the world. Initially, my personal website was a simple online CV, built with plain HTML and Bootstrap, and hosted on AWS S3.

After exploring my options, I began searching for a suitable static site generator that would allow me to publish blog posts using markdown. This approach seemed perfect since I was already familiar with markdown. This search led me to Jekyll. The learning curve with Jekyll was minimal, and setting up the website on GitHub Pages was straightforward. However, I eventually got caught up in other projects and life, and never managed to complete the blog.

Recently, I came across Hugo. Its simplicity and speed made it the ideal choice for revisiting this project. The ease of use and quick build times were major selling points. I opted for the hugo-coder theme for its clean and professional look, and added a nice touch to my homepage with particle.js for a subtle, interactive effect.

In this blog, I am sharing a small guide to how I got this blog website up and running.

Step-by-step instructions: Link to heading

First I installed hugo with the hugo-coder theme

Setting up website with Hugo Link to heading

# Install hugo
$ brew install hugo

# Create website and git repo
$ hugo new site <mywebsite>
$ cd <mywebsite>
$ git init

# Install hugo-coder theme
$ git submodule add https://github.com/luizdepra/hugo-coder.git themes/hugo-coder
$ echo "theme = 'hugo-coder'" >> hugo.toml

# Start Hugo's development server to view site
$ hugo server

A more comprehensive guide can be found on Hugo’s getting started docs

Personalizing Link to heading

Next steps after getting basic hugo site working was to understand hugo site structure, update avatar, favicons and site configuration. For this I followed theme docs and updated configurations that made sense for my site.

A quick intro to hugo directory structure

  • hugo.toml contains site configuration
  • content markdown files which forms the content of the site go here
  • assets global resources such as CSS, sass and javascript
  • archetypes page templates for new content
  • layouts templates to transform content i.e. html templates that I have overwritten from the theme
  • static resources to be copied to public directory such as favicon, images, javascript
  • public contains published website
  • themes theme goes in here

There are a few others as well which I didn’t use.

To personalize further, I made some modifications to the theme using custom CSS, header, footer and other pages.

Tip
Do not modify the theme files directly; instead copy the theme template that you want to modify under the same path in layout ex: layout/partials/<foo> in your site. Similarly, if you want to make any CSS/sass changes, make a copy under assets ex: assets/scss/<foo>.

This will allow you to be able to seamlessly update the site and still be able to fetch theme updates in future without conflicts. Hugo layers your site files to the same path from the theme.

Adding particle.js Link to heading

To give a nice touch to the website homepage, I opted to add particles.js. I used demo/generator to design particles effect and downloaded the configuration. Then I added particles.min.js and app.js javascript files from the example to static/js/.. path replacing contents of the example app.js file with the configuration of the effect I generated.

To move particles content to be behind all other content, I used the following CSS.

#particles-js {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1; /* Make sure the particles are behind other content */
}

.content {
  position: relative;
  z-index: 1; /* Content is above the particles */
}

Now to add particles.js to my home page, I needed to add following two lines to home.html in layout directory.

  <div id="particles-js"></div>
  <script src="{{ "js/particles.min.js" | relURL }}"></script>
  <script src="{{ "js/app.js" | relURL }}"></script>

Alternatively, I could have added these JavaScript files to the customJS section of the configuration file, but that would have applied them to every page, which I didn’t want. Instead, I’ve opted to include them only on the homepage for a more targeted effect.

With the setup and customizations complete, I was pleased with the final design. Now on to adding content and publishing.

Publishing the site Link to heading

I am hosting this website on GitHub pages. I wanted separation between website code and static public pages. To achieve this, I use two repos - one public and one private. I configured GHA workflow such that when I push changes to the private repo, it builds hugo site and publishes static content under public directory to the website repo that is public.

Steps Link to heading
  1. Setup private github repo which will host code for the website (excluding /public/)
  2. Setup a public github repo for the website static pages
  3. Setup github actions workflow using actions-hugo
name: Deploy Hugo site to Pages

on:
  push:
    branches:
      - main  # Set a branch to deploy
  pull_request:

jobs:
  deploy:
    runs-on: ubuntu-22.04
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        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@v3
        with:
          hugo-version: 'latest'
          extended: true

      - name: Build
        run: hugo --minify

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          deploy_key: ${{ secrets.PRIVATE_KEY }}
          external_repository: your_username/public_repository_name
          publish_branch: main
          publish_dir: ./public

Conclusion Link to heading

There is a bit of learning curve with Hugo compared to Jekyll, specially if like me, you want to make modifications to the theme you chose to use. Most of my dev time went into personalizing the theme further. I like the outcome and will continue to add more functionality such as comments and search in the future.