Creating a Theme from Scratch
Hugo HTMLWhile I like many themes from the corresponding hugo page, with this post I start creating a new theme for my own site, with the goal to explore and use some CSS (and Markdown/Hugo, of course). For simplcity, I start from a completely new site with hugo
:
hugo new site from_scratch
The folder themes
is empty. Normally, I would clone an existing theme, and start configuring. In this example, however, I want to work step by step. For reference, I follow this guide. I create a completely new theme, and I call it bareMinimum
:
hugo new theme bareMinimum
This lead to the following structure for the folder themes/bareMinimum
:
bareMinimum/
├── archetypes
│ └── default.md
├── hugo.toml
├── layouts
│ ├── 404.html
│ ├── _default
│ │ ├── baseof.html
│ │ ├── list.html
│ │ └── single.html
│ ├── index.html
│ └── partials
│ ├── footer.html
│ ├── header.html
│ └── head.html
├── LICENSE
├── static
│ ├── css
│ └── js
└── theme.toml
Then, I create a new post:
hugo new content posts/creating_a_theme.md
and edit the hugo.toml
file:
baseURL = "/"
languageCode = "en-us"
title = "Site from scratch"
theme = "bareMinimum"
I build my site:
hugo
obtaining (I cut the output to the first columns for clarity):
Start building sites …
hugo v0.113.0+extended linux/amd64 BuildDate=2023-08-30T08:06:23Z VendorInfo=debian:0.113.0-3
WARN 2023/10/29 11:25:09 found no layout file for "html" for kind "home": You should create a...
WARN 2023/10/29 11:25:09 found no layout file for "html" for kind "taxonomy": You should create a...
WARN 2023/10/29 11:25:09 found no layout file for "html" for kind "taxonomy": You should create a...
| EN
-------------------+-----
Pages | 3
Paginator pages | 0
Non-page files | 0
Static files | 0
Processed images | 0
Aliases | 0
Sitemaps | 1
Cleaned | 0
Total in 23 ms
So, no errors, but some important warning. In the next session, I am going to fix them.
Creating the partials
I keep following retrolog.io guide, but I choose not to include bootstrap
. I first create my themes/bareMinimum/layouts/partials/head.html
:
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/css/style.css">
{{ $title := print .Site.Title " | " .Title }}
{{ if .IsHome }}{{ $title = .Site.Title }}{{ end }}
<title>{{ $title }}</title>
</head>
which is (quoting retrolog.io):
This will be the place for metadata like the document title, character set, styles, scripts, and other meta information
Then, I create themes/bareMinimum/layouts/partials/header.html
:
<div id="nav-border" class="container">
<nav id="nav" class="nav justify-content-center">
{{ range .Site.Menus.main }}
<a class="nav-link" href="{{ .URL }}">
{{ if .Pre }}
{{ $icon := printf "<i data-feather=\"%s\"></i> " .Pre | safeHTML }}
{{ $icon }}
{{ end }}
{{ $text := print .Name | safeHTML }}
{{ $text }}
</a>
{{ end }}
</nav>
</div>
that represent the beginning of each page in the site, and a footer themes/bareMinimum/layouts/partials/footer.html
:
<p class="footer text-center">Copyright (c) {{ now.Format "2006"}} Marco Carnini</p>
This is the bottom of each page, adding the copyright information.
Default layouts
As a first step, I create a minimalistic layout for my homepage (themes/bareMinimum/layouts/index.html
):
{{ define "main" }}
<div>
<h1 class="title">{{ .Site.Title }}</h1>
</div>
{{ end }}
I keep the themes/bareMinimum/layouts/_default/baseof.html
as the initial, default value:
<!DOCTYPE html>
<html>
{{- partial "head.html" . -}}
<body>
{{- partial "header.html" . -}}
<div id="content">
{{- block "main" . }}{{- end }}
</div>
{{- partial "footer.html" . -}}
</body>
</html>
For themes/bareMinimum/layouts/_default/list.html
, I consider the following:
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{ range .Pages.ByPublishDate.Reverse }}
<p>
<h3><a class="title" href="{{ .RelPermalink }}">{{ .Title }}</a></h3>
{{ partial "metadata.html" . }}
<a class="summary" href="{{ .RelPermalink }}">
<p>{{ .Summary }}</p>
</a>
</p>
{{ end }}
{{ end }}
and for themes/bareMinimum/layouts/_default/single.html
:
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{ partial "metadata.html" . }}
<br><br>
{{ .Content }}
{{ end }}
The site
The look and feel of the site is not eye-catching. The home page look like this:
The page with the list of all posts look like this:
A single post, instead look like this:
Of course, some customization some styling are needed to improve: thus, I need to create a CSS for my theme.