Intro
I used to have a blog, but it was running on a theme that was becoming less and less maintained. Eventually, the moment had to come: burn it down and start again from scratch.
Starting fresh felt like the right decision β not just technically, but also as an opportunity to refactor and polish my blog.
On The Value of Blogging.
This blog exists as a place to think slowly.
Most technical work is ephemeral: incidents fade, decisions are forgotten, and lessons learned are rarely written down. Blogging is my way of pushing back against that.
I just want to write my thoughs and continue them later on. There is no schedule. Some posts may be rough or unfinish. If these notes help someone else along the way, thatβs a bonus β but not the objective.
The Tech choice
For this new iteration of my blog, I stay on Hugo with the HBStack theme cards, deployed on GitHub Pages.
It’s an old and eproved receipe.
Why Hugo?
Hugo is a fast, opinionated static site generator that focuses on content first.
Once generated, the site is just plain HTML, CSS, and JavaScript β easy to host, easy to secure, and extremely fast.
For me, Hugo offers:
- Excellent performance
- No runtime dependencies
- A simple content workflow
- Long-term stability
- Some Fun in customization (with widget or shortcode)
Why HBStack and its themes?
HBStack builds on top of Hugo using modules, offering a flexible and well-structured ecosystem of themes and extensions.
What really sold me was the availability of hooks, which allow deep customization without forking or hacking the theme itself (js,css or html).
Some HBStack features I consider essential for my blog:
- Post and documentation layouts
- Sidebar and table of contents (TOC)
- Emoji and Bootstrap icon support
- Notification badge for new articles
- Customization hooks
- Syntax highlighting
- Comment system (Giscus, backed by GitHub)
- Light / Dark mode
- Search index
Why GitHub Pages?
GitHub Pages provides a simple, reliable hosting solution for static sites. Combined with Hugo, it allows me to:
- Host the site for free
- Version content alongside code
- Deploy automatically via GitHub Actions
- Avoid server maintenance entirely
Start from Scratch
It’s always better. Even though, I had already a blog, I started from scratch and imported the content and assests in the new blog to avoid all the assles.
This maybe repeating the tutorials here but just for the records:
1# install go
2sudo apt install golang-go
3go version
4
5# install Hugo
6HUGO_VERSION="0.148.0"
7curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz
8tar -xzf hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz
9sudo mv hugo /usr/bin/hugo
10hugo version
11
12# install nodejs 16 or higher
13sudo apt install nodejs npm git
14nodejs -v
15
16# install Dart Sass
17npm install -g sass
18sass --version
19
20# clone theme
21git clone --depth 1 https://github.com/hbstack/theme-cards
22cp -r theme-cards/exampleSite mysite
23cd mysite
24sed -i '1s/.*/module github.com\/user\/repo/' go.mod
25sed -i '/^replace/d' go.mod
26
27# Install hugo dependencies
28npm ci
29
30# Run locally
31npm run dev
Hugo - some Keys Concepts
First - Hugo behavior is format-agnostic configuration, it matches all config files (.yaml, .yml, .json, .toml all work from ./data or ./config)
Second - In Hugo, everything is a page.
Third - Folder names under content/ define sections. Each section can have its own templates.
π Front Matter is the page metadata which strongly influences rendering and behavior.
1---
2title: "My Post"
3date: 2026-01-01
4draft: false
5tags: ["hugo", "static-site"]
6---
π Hugo Pipes:
- Asset processing (SCSS β CSS)
- Minification, fingerprinting
- JS bundling
- Cache-friendly builds
Hugo Structure
1βββ archetypes # Front matter templates used by `hugo new`
2βββ assets # Source files processed by Hugo Pipes (SCSS, JS, images)
3βββ config # Site configuration (baseURL, params, menus, languages)
4βββ content # Markdown content; structure defines URLs
5β βββ _index.en.md # Section list page
6β βββ categories
7β βββ docs
8β βββ posts
9βββ data # Global data files (YAML/TOML/JSON) accessible in templates
10βββ layouts # HTML templates
11β βββ _default # Fallback templates (single, list, baseof)
12β βββ partials # Reusable HTML components
13β βββ shortcodes # Template logic callable from Markdown
14βββ public # Generated static site (build output)
15βββ static # Static files copied directly to public/
Tweak the config
- The basics
1# in ./config/_default/hugo.yaml
2baseURL: https://mozebaltyk.github.io/
3title: BaΕtyk Blog
- Change background
1# in ./config/_default/params.yaml
2hb:
3 background_image:
4 brightness: 10
5 modern_format: webp
then put images in assets\images\background.jpg
- To organize menu and add icons
Either define in ./config/_default/menus.en.yaml:
1main:
2 - identifier: navigate
3 name: Navigate
4 weight: 9
5 params:
6 icon:
7 vendor: bootstrap
8 name: signpost-split
9 color: "#fd7e14"
then you can defined the children like ./content/categories/_index.en.md with :
1---
2title: Categories
3menu:
4 main:
5 parent: navigate
6 params:
7 icon:
8 vendor: bs
9 name: folder
10 color: orange
11 description: All of categories.
12---
or directly from the index.en.md:
1---
2title: Posts
3menu:
4 main:
5 weight: 1
6 params:
7 icon:
8 vendor: bs
9 name: body-text
10 color: "#20c997"
11 description: Some posts on IT topics.
12---
- Change the back-to-top icon
1# in ./config/_default/params.yaml
2hb:
3 back_to_top:
4 animation: true
5 icon_height: 2em
6 icon_name: hand-index
7 icon_width: 2em
8 position_bottom: 1rem
9 position_end: 1rem
The Taxonomies
Taxonomies give structure to a growing collection of articles.
They allow posts to be categorized, indexed, and connected to one another beyond simple chronology. Instead of a linear stream, the blog becomes a graph: topics intersect, ideas resurface, and related articles can be discovered naturally.
In practice, taxonomies help both the reader and the author. Readers can navigate by themes rather than dates, while I can spot recurring subjects, gaps, or patterns in what I write over time.
Used well, taxonomies are not just metadata β they are a lightweight form of knowledge organization that keeps a blog coherent as it evolves
in params.yaml, you can tell sidebar which one to use to propose some switch button:
1hb:
2 blog:
3 sidebar:
4 taxonomies:
5 count: true # whether to show the number of posts associated to the item.
6 limit: 10 # the maximum number of the item.
7 style: pills # pills, tabs or underline.
8 separate: false # whether to separate into mutliple sections.
9 authors:
10 disable: true # whether to disable this taxonomy.
11 weight: 1 # the weight of this taxonomy, lower gets higher priority.
12 count: false # override the global count setting.
13 limit: 5 # override the global limit setting.
14 categories:
15 disable: false
16 weight: 2
17 series:
18 disable: false
19 weight: 3
20 tags:
21 disable: false
22 weight: 4
23 limit: 25
Editing some content
Based on the Archetypes that I defined, I can create a new posts :
1hugo new --kind posts posts/my-new-blog.md
or docs:
1hugo new --kind docs docs/Devops/IaC/index.md
A word on giscus
In ./config/_default/params.yaml, there is giscus blocks config. Giscus is a comments system powered by GitHub Discussions, so the comments left on your articles goes in discussions of your github Pages.
To do so, you will need to:
Make your repository public.
Enable discussions in the project settings.
Activate giscus app for on your account (you can limit to your blog project)
Then, giving the URL of your repository
1hb:
2 blog:
3 giscus:
4 repo: MozeBaltyk/mozebaltyk.github.io
5 repo_id: R_kgDOKJSCfA
6 category_id: DIC_kwDOKJSCfM4CYvA_
7 docs:
8 giscus:
9 repo: MozeBaltyk/mozebaltyk.github.io
10 repo_id: R_kgDOKJSCfA
11 category_id: DIC_kwDOKJSCfM4CYvA_
On their side, visitors will need a Github account and must authorize the giscus app to post on their behalf using the GitHub OAuth flow.
Shortcodes
HBstack theme provides a bench shortcodes embended in its bootstrap module here
NB: remove the backslash to use those blocks of code.
- Toogle of config files between toml/yaml/json:
1{{< bs/config-toggle "params" >}}
2hb:
3 blog:
4 home:
5 pinned_posts_position: list
6{{< /bs/config-toggle >}}
This one is a nice one, since it automaticly create a block of code with 3 tabs to switch between the 3 type of config (TOML/YAML/JSON) like below:
params.toml
1[hb]
2 [hb.blog]
3 [hb.blog.home]
4 pinned_posts_position = 'list'
params.yaml
1hb:
2 blog:
3 home:
4 pinned_posts_position: list
params.json
1{
2 "hb": {
3 "blog": {
4 "home": {
5 "pinned_posts_position": "list"
6 }
7 }
8 }
9}
- Simple toggle
1{{< bs/toggle name=sdk style=pills >}}
2
3 {{< bs/toggle-item JS >}}
4 {{< highlight js >}}
5 console.log('hello world');
6 {{< /highlight >}}
7 {{< /bs/toggle-item >}}
8
9 {{< bs/toggle-item PHP >}}
10 {{< highlight php >}}
11 echo 'hello world';
12 {{< /highlight >}}
13 {{< /bs/toggle-item >}}
14
15 {{< bs/toggle-item Go >}}
16 {{< highlight go >}}
17 fmt.Println("hello world")
18 {{< /highlight >}}
19 {{< /bs/toggle-item >}}
20
21{{< /bs/toggle >}}
The result:
1console.log('hello world');1echo 'hello world';1fmt.Println("hello world")- Some Alert banner - primary, secondary, success, danger, warning, info, light, dark options:
1{{< bs/alert info >}}
2{{< markdownify >}}
3Create a *info* **banner** to inform readers about this syntax and with markdown inside.
4{{< /markdownify >}}
5{{< /bs/alert >}}
give this effect:
Some other which could be usefull:
The collapse shortcode - show and hidde content:
The Clearfix - Quickly and easily clear floated content within a container
Modules
A simple example, add modules inside config/_default/module.yaml, for instance github.com/hbstack/blockquote-alerts
the blockquote-alerts module allow those below effects (instead of using shortcode):
Important
The
TYPEis required TYPE = “NOTE” | “TIP” | “IMPORTANT” | “WARNING” | “CAUTION” | “QUESTION” SIGN = “+” | “-”
NoteThe
SIGNis optional, which is used to indicate whether the alert is foldable, the+sign expands the alert by default.
Is the TITLE required?The
TITLEis required when using theQUESTIONtype, it also can be used to customize title.
Each module have its own doc page and provides different customization effects on your blogs.
Update Hugo modules
1hugo mod get -u ./... && hugo mod tidy
2
3npm update
4
5npm ci
Images
- Featured image:
The first image of the images parameter, usually used for static and external images.
The page imageβs resources that naming in pattern feature*, such as feature.png, featured-xx.jpg. The featured image resource will be resized in smaller size, to save userβs and serverβs bandwidth.
- Image used in article goes in
static/<article-filename>/image.jpg
Deployment
On this side as well, there is improvment since a new docker images with all dependencies is provided on docker.io. Which is the local testing of the blog and reproductibilty.
But the github workflows deployment in .github/workflows/gh-pages.yaml with a build job and a “deploy” job which trigger when I push on main.
Whatβs next?
At this stage, what could you do more:
Share your website with the HB to showcase that you are using HB theme on their hompage. doc
Create custom widget like in this article
Check the uptime of your site with a simple github action
Auto-update with
renovate.jsonWrite your docs with Obsidian: Here are some elements about how to set it correctly.
Dive into shortcodes and write some custom.
Polish and customize RSS feed







