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 configurationcontent
markdown files which forms the content of the site go hereassets
global resources such as CSS, sass and javascriptarchetypes
page templates for new contentlayouts
templates to transform content i.e. html templates that I have overwritten from the themestatic
resources to be copied to public directory such as favicon, images, javascriptpublic
contains published websitethemes
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.
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
- Setup private github repo which will host code for the website (excluding
/public/
) - Setup a public github repo for the website static pages
- 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.