Setting up a static HTML based blog can be a bit challenging, and deciding which software and theme to use even more! Hugo is a widely used and well-supported solution with some great themes. So here’s a quick start guide on how to set up a good-looking Hugo blog!
Configuring Dev Containers
First, we have will have to install Hugo. Using Hugo in a container is a good idea to make sure we don’t clutter the host OS, to make our installation portable and also make sure we can use a recent Hugo version on older OS. A simple way to use containers and get good integration into Visual Studio Code is using its Dev Containers feature.
As a first step, let’s create a new git repository where we will place all data and create the folder for the Dev Container configuration:
git init jpfau.org
mkdir jpfau.org/.devcontainer
Next, let’s create the .devcontainer/devcontainer.json
file with this content:
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
{
"name": "jpfau.org",
"build": {
"dockerfile": "Dockerfile",
"args": {
"HUGO_VERSION": "0.140.2"
}
},
"forwardPorts": [1313],
"customizations": {
"vscode": {
"extensions": [
"valentjn.vscode-ltex",
"eamodio.gitlens",
"eliostruyf.vscode-front-matter"
]
}
}
}
This will instruct VS Code to build a container using the local Dockerfile
, pass HUGO_VERSION
as a build variable, forward port 1313 when running the container and install the listed VS Code extensions.
Even when editing markdown instead of latex, valentjn.vscode-ltex
will be useful for spell and grammar checking. eamodio.gitlens
provides extended GIT support and eliostruyf.vscode-front-matter
acts as a CMS VS Code add-on.
Although there are ready-to-use Hugo containers from the HugoMods project, those can’t run the LanguageTool
server used in LTeX.
Furthermore, those images don’t include SSH support for GIT.
Because of this, we will build a custom image based on Ubuntu and the latest official Hugo binary releases.
Add the following to .devcontainer/Dockerfile
:
FROM docker.io/ubuntu:24.04
ARG HUGO_VERSION
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get -qq -y install curl git golang-go \
&& apt-get clean
RUN curl -sL "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb" -o hugo.deb && \
dpkg -i hugo.deb && \
rm hugo.deb
This will use the latest Ubuntu LTS release, install some dependencies and finally will install the official Hugo binaries. The Hugo version can be specified as a build variable.
Installing the PaperMod Theme
Open the newly created folder in VS Code and let it set up a container. Once the container has been built and opened, open a terminal in VS Code. Then initialize a new Hugo site:
hugo new site jpfau.org --format yaml
Next, follow the PaperMod install instructions and set up the git submodule:
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
You might want to set up .gitignore
to ignore built files:
/public/
.hugo_build.lock
Then, to get the basic site ready, create content/archive.md
:
---
title: "Archive"
layout: "archives"
summary: "archive"
---
and content/search.md
:
---
title: "Search"
placeholder: Site Search
layout: "search"
---
Finally, modify your hugo.yaml
to look like this:
baseURL: https://jpfau.org/
languageCode: en-us
title: JP's Techblog
theme:
- PaperMod
enableInlineShortcodes: true
enableRobotsTXT: true
buildDrafts: false
buildFuture: false
buildExpired: false
enableEmoji: true
pygmentsUseClasses: true
pluralizelisttitles: false
mainsections: ["blog"]
frontmatter:
date:
- ':filename'
- ':default'
languages:
en:
languageName: "English"
weight: 1
taxonomies:
category: categories
tag: tags
series: series
menu:
main:
- name: Series
url: series/
weight: 5
- name: Archive
url: archive/
weight: 5
- name: Search
url: search/
weight: 10
- name: Tags
url: tags/
weight: 10
outputs:
home:
- HTML
- RSS
- JSON
params:
env: production
defaultTheme: auto
ShowShareButtons: true
ShowReadingTime: true
displayFullLangName: true
ShowPostNavLinks: true
ShowBreadCrumbs: true
ShowCodeCopyButtons: true
ShowRssButtonInSectionTermList: true
ShowAllPagesInArchive: true
ShowPageNums: true
ShowToc: true
homeInfoParams:
Title: "Johannes Pfau"
Content: >
Blogging about all things tech, software, hardware and IT stuff.
socialIcons:
- name: github
title: Github
url: "https://github.com/jpf91"
- name: LinkedIn
title: LinkedIn
url: "https://linkedin.com/in/johannes-pfau-a3963b277"
- name: ORCID
title: ORCID
url: "https://orcid.org/0000-0003-1087-1814"
The frontmatter
snippet ensures that dates are read from filenames, if you name your files YYYY-MM-DD-blog-name.md
.
The mainsections
configuration tells Hugo that it should look for posts in content/blog
.
Refer to the PaperMod Example Site for more configuration options.
Previewing the Site
You can now preview the site by executing hugo serve --bind 0.0.0.0
.
When the server is running, open localhost:1313
in your browser, or press Ctrl-Shift-P and type Simple browser show
to open a web browser in VS Code.
To add articles, simply place them in content/blog
and name them YYYY-MM-DD-blog-name.md
, e.g. 2025-01-14-setting-up-hugo.md
.
Deploying with GitHub Actions
To build using GitHub Actions and deploy to GitHub Pages, create .github/workflows/site.yaml
with this content:
name: site
on:
# trigger deployment on every push to main branch
push:
branches: [master]
# trigger deployment manually
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
docs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
# fetch all commits to get last updated time or other git log info
fetch-depth: 0
submodules: true
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: '0.140.2'
extended: true
# Build
- name: Build Hugo site
run: hugo --minify
# Deploy to github pages
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'public'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Next Steps
In the next posts, we’ll see how to add comments, how to install DecapCMS, how to set up Latex, how to get article series working and how to get info boxes and other markdown enhancements.