Here are the main features of Hugo I use to generate all the static pages of this site.
You might also want to see how I used Jekyll for this site before migrating to Hugo.
$ ls
archetypes config.toml content data
layouts resources static themes
The config.toml file content is:
baseURL = "https://kaue.me"
languageCode = "en-us"
title = "Kaue's Way of Life"
publishDir = "../server/_site"
[markup]
[markup.highlight]
style = "rrt"
[outputs]
home = [ "RSS", "HTML"]
[outputFormats]
[outputFormats.RSS]
mediatype = "application/rss"
baseName = "feed"
[author]
name = "Kaue Silveira"
This uses the rrt markup highlight style to address the accessibility problem “Background and foreground colors do not have a sufficient contrast ratio” present in the default style.
The RSS is configured to output to feed.xml.
This is what the content folders look like:
$ ls content/
about all goals headless_goals health
_index.md love meaning robots.txt wealth
$ ls content/health/
exercise _index.md nutrition sleep
$ ls content/health/exercise/ | head
_index.md
levered-body-weight-exercises.md
phil-maffetone-the-180-formula-....md
stronglifts-5x5-workout-and-app-review.md
Content files look like this:
$ cat health/sleep/_index.md | head -n 11
---
title: "Sleep"
weight: 100
description: "Sleep."
---
# Sleep
{{< goal >}}
## Challenges
I have some custom shortcodes (like goals) and partials which I cover next.
This is based on the official Hugo documentation, with some modifications.
{{- if not .IsHome -}}
<hr>
<ol class="breadcrumb">
{{- template "breadcrumb"
(dict "p1" . "p2" .) -}}
</ol>
<hr>
{{- end -}}
{{- define "breadcrumb" -}}
{{- if .p1.Parent -}}
{{- template "breadcrumb"
(dict "p1" .p1.Parent "p2" .p2 ) -}}
{{- else if not .p1.IsHome -}}
{{- template "breadcrumb"
(dict "p1" .p1.Site.Home "p2" .p2 ) -}}
{{- end -}}
{{- if ne .p1 .p2 -}}
<li>
<a href="{{- .p1.Permalink -}}">
{{- .p1.Title -}}
</a>
</li>
<li>/</li>
{{- else -}}
<li>{{- .p1.Title -}}</li>
{{- end -}}
{{- end -}}
Some content pages (like sleep/_index.md above) include the corresponding goals using:
$ ls content/headless_goals/
awareness.md career.md exercise.md
friends.md fun.md good.md index.md
investing.md nutrition.md parents.md
partner.md saving.md sleep.md
$ cat content/headless_goals/index.md
---
headless: true
---
$ cat layouts/shortcodes/goal.html
{{- $headless := .Site.GetPage
"/headless_goals" -}}
{{- $name := print (index (
split $.Page.File.Dir "/") 1) ".md" -}}
<h2>Goals</h2>
{{- range $headless.Resources.Match $name -}}
{{- .Content -}}
{{- end -}}
The overall goals page lists all goals like:
{{- $headless := .Site.GetPage
"/headless_goals" -}}
{{- range site.Home.Sections -}}
<h2>{{- .Title -}}</h2>
{{- range .Pages -}}
<h3>{{- .Title -}}</h3>
{{- $name := print (index (
split .Page.File.Dir "/") 1) ".md" -}}
{{- range
$headless.Resources.Match $name -}}
{{- .Content -}}
{{- end -}}
{{- end -}}
{{- end -}}
Hugo automatically sorts pages by their weight.
This lists sub-pages:
{{- if .Pages -}}
{{- $found := false -}}
{{- range .Pages -}}
{{- if .Pages -}}
{{- $found = true -}}
{{- end -}}
{{- end -}}
{{- if $found -}}
<h2>Pages</h2>
{{- else -}}
<h2>Posts</h2>
{{- end -}}
<ul>
{{- range .Pages -}}
<li>
<a href="{{- .Permalink -}}">
{{- .Title -}}
</a>
</li>
{{- end -}}
</ul>
{{- if not .IsHome -}}
{{- if $found -}}
<h2>Posts</h2>
{{- range .Pages -}}
{{- if .Pages -}}
<h3>{{- .Title -}}</h3>
<ul>
{{- range .Pages -}}
<li>
<a href="{{- .Permalink -}}">
{{- .Title -}}
</a>
</li>
{{- end -}}
</ul>
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
The all page recursively lists all pages in the site:
{{- template "posts" site.Home -}}
{{- define "posts" -}}
{{- if .Pages -}}
<ul>
{{- range .Pages -}}
<li>
<a href="{{- .Permalink -}}">
{{- .Title -}}
</a>
</li>
{{- template "posts" . -}}
{{- end -}}
</ul>
{{- end -}}
{{- end -}}
This includes a file from the page resources:
{{- with .Page.Resources.Match (.Get 0) -}}
{{- range . -}}
{{- .Content | safeHTML -}}
{{- end -}}
{{- end -}}
Used like:
$ cat content/...page.../index.md |
grep '{{< include .* >}}'
{{< include cave.html >}}
$ ls content/...page.../
cave.html index.md
The layout conditionally includes dependencies only for the pages that need them, e.g.:
{{- $hasMath := .HasShortcode "math" -}}
{{- $hasMathPlot :=
.Page.Params.include_math_plot -}}
{{- if $hasMath -}}
loadJS("https://cdnjs.cloudflare.com/....js");
{{- end -}}
{{- if $hasMathPlot -}}
loadJS("https://unpkg.com/mathjs....js");
loadJS("https://cdn.plot.ly/plotly....js");
{{- end -}}
The layout also checks that all pages have a date:
{{- if .Date -}}
<h6>Updated on
{{ .Date.Format "2006 Jan 2" -}}.</h6>
{{- else -}}
{{- if and
(ne .Path "categories")
(ne .Path "tags") -}}
{{- errorf
"missing .Date for page %s" .Path -}}
{{- end -}}
{{- end -}}
The index page shows the most recent posts:
<h2>Latest</h2>
<ul>
{{- range first 7 site.RegularPages -}}
<li>
<a href="{{- .Permalink -}}">
{{- .Title -}}
</a>
</li>
{{- end -}}
</ul>
Posts automatically include a page resource named include.html if present:
{{- with .Resources.Match "include.html" -}}
{{- range . -}}
{{- .Content | safeHTML -}}
{{- end -}}
{{- end -}}
Used like:
$ ls content/...page.../
include.html index.md