Hinter diesem Türchen verbirgt sich Hugo: ein mächtiger und äusserst performanter Generator für statische Webseiten. Der Name dürfte einerseits an die Programmiersprache Go erinnern, in der er implementiert ist. (Go macht es einfach, Aufgaben zu parallelisieren, was wohl ein wichtiger Faktor für die ausserordentlich hohe Performance von Hugo sein dürfte.) Das “Hu” (wie “huge”) dürfte eine Anspielung darauf sein, das man mit Hugo riesige Seiten in nützlicher Frist generieren kann.
Themes: vorgefertigte und eigene
Zum Einstieg in Hugo wird oft empfohlen ein vorgefertigtes Theme zu wählen. Das ist für die meisten Seiten sicherlich ein guter Rat. So habe ich positive Erfahrungen mit dem äusserst mächtigen Relearn-Theme gemacht, das u.a. LaTeX-Formeln mit MathJax, Diagramme mit Mermaid und eine clientseitige JavaScript-Suche out of the box mitbringt. Ich brauche das für meine Unterrichtsmaterialien, siehe etwa die Webseite für mein Cloud-Modul.
Privat habe ich zwei Webseiten am Laufen: zum einen meine Hauptwebseite paedubucher.ch, die auf einem selber gebauten Hugo-Theme basiert. Neulich habe ich mir an einem Abend einen neuen Blog namens Read, Think, Write zusammengehackt. Hier kommt ebenfalls ein eigenes Theme zum Einsatz, aber ein äusserst minimalistisches. Die Webseite ist ein one pager im wahrsten Sinne des Wortes, dank HTML-Minifizierung aber trotzdem sehr schlank. (Die .woff-Schrift Bitter, die ich mit ausliefere, ist zugegebenermassen ein Luxus.) Wie man so etwas baut, möchte ich in diesem Türchen zeigen.
Liebes Tagebuch
Analog zu meinem Blog Read, Think, Write möchte ich zeigen, wie man mit Hugo eine kleine Tagebuch-Webseite erstellt. Von einer frischen Installation von Debian 12 “Bookworm” ausgehend soll zunächst einmal Hugo installiert werden:
Code: Alles auswählen
$ sudo apt install -y hugo
Nun soll die Tagebuchseite initialisiert werden:
Code: Alles auswählen
$ hugo new site tagebuch
Code: Alles auswählen
$ tree tagebuch
tagebuch/
├── archetypes
│ └── default.md
├── assets
├── config.toml
├── content
├── data
├── layouts
├── public
├── static
└── themes
- archetypes: Dieses Verzeichnis enthält Vorlagen für neue Seiten. Das Template default.md enthält einen YAML-Header für den Titel und das Tagesdatum. Das werden wir gleich in Aktion sehen.
- assets: Hier kommen Dateien hinein, die von Hugo verarbeitet (z.B. “minifiziert”) werden, wie z.B. CSS- oder JavaScript-Quellcodedateien.
- config.toml: Hierbei handelt es sich um die Konfigurationsdatei für die ganze Webseite, die auf der Hugo-Webseite sehr detailliert dokumentiert ist. Diese liegt standardmässig im TOML-Format vor. Wichtige Einstellungen sind die baseURL der Webseite, die ich auf https://tagebuch.paedubucher.ch ändere; der languageCode, den ich gut schweizerisch auf de-ch umstelle; und der Titel, den ich auf Mein Tagebuch ändere. Weitere Ergänzungen finden sich unten.
- content ist das Verzeichnis, welche die Seiteninhalte als Markdown-Dateien enthält. Dieses Verzeichnis werden wir gleich mit Inhalt befüllen.
- data enthält Dateien, die in den Hugo-Templates angesprochen werden können. Ich selber habe das noch nie verwendet, doch die Dokumentation gibt Auskunft darüber.
- layouts enthält eigene Templates um die Seite zu generieren. Es kommen die selbst für Go-Programmierer etwas gewöhnungsbedürftigen Go-Templates zum Einsatz.
- public ist das Verzeichnis, in welches das generierte HTML mit den Zusatzdateien (CSS, JavaScript) landet. Dieses Verzeichnis kann man von einem Webserver ausliefern lassen. Ich selber schliesse es aus meinem Git-Repository aus; es gibt aber Leute, die auch das generierte HTML in die Versionskontrolle aufnehmen.
- static ist für statische Dateien wie Bilder oder Schriftarten gedacht, die 1:1 (ohne weiteren Verarbeitungsschritt durch Hugo) ausgeliefert werden.
- themes kann mehrere Themes enthalten, die dann über die Konfiguration aktiviert werden. Wir werden in diesem Beispiel keine Themes verwenden.
Code: Alles auswählen
baseURL = 'https://tagebuch.paedubucher.ch'
languageCode = 'de-ch'
title = 'Mein Tagebuch'
[minify]
minifyOutput = true
[params]
author.name = "Patrick Bucher"
meta.description = "Mein Tagebuch"
meta.keywords = "Tagebuch, Blog, Persönliches"
Metadaten sind im Abschnitt params definiert. Dies sind Angaben für die Meta-Tags author, description und keywords, die später im Template zum Einsatz kommen sollen.
Das Tagebuch wäre nun von technischer Seite her aufgesetzt. Nun soll das Layout erstellt werden.
Layout mit Go-Templates
Beim Layout handelt es sich um eine HTML-Datei, in welcher der dynamische Teil als Go-Template eingestreut wird. Die Datei wird unter layouts/index.html abgelegt:
Code: Alles auswählen
<!doctype html>
<html lang="de-ch">
<head>
<meta charset="UTF-8" />
<meta name="author" content="{{ .Site.Params.Author.Name }}" />
<meta name="description" content="{{ .Site.Params.Meta.Description }}" />
<meta name="keywords" content="{{ .Site.Params.Meta.Keywords }}" />
{{ $css := resources.Get "style.css" | minify }}
<link rel="stylesheet" type="text/css" href="{{ $css.RelPermalink }}" />
<title>{{ .Site.Title }}</title>
</head>
<body>
<header>
<h1>{{ .Site.Title }}</h1>
</header>
<main>
{{ range $_, $page := .Pages }}
<article>
<h2>{{ $page.Params.Title }}</h2>
<p><em>{{ time.Format "02.01.2006" $page.Params.Date }}</em></p>
{{ $page.Content }}
<hr />
</article>
{{ end }}
</main>
<footer>
<p>© {{ .Site.Lastmod.Format "2006" }} by {{ .Site.Params.Author.Name }}.</p>
</footer>
</body>
</html>
Die CSS-Datei style.css wird zuerst “minifiziert” und dann per link-Tag eingebunden.
Der Seitentitel .Site.Title kommt sowohl für den title- als auch für den h1-Tag zum Einsatz.
Im Hauptbereich der Seite wird über die Inhaltsseiten (.Pages) iteriert. Die $page-Datenstruktur steht dann für eine einzelne Inhaltsseite, deren Inhalt als $page.Content ausgegeben werden kann. Das Markdown wurde in HTML gerendert. Die Datumsangabe wird typisch für Go formatiert: Man gibt einfach das gewünschte Format exemplarisch für den zweiten Januar 2006 an, das dann mit der Funktion time.Format anhand der Angabe $page.Params.Date dargestellt wird.
Zuunterst gibt es noch einen footer mit Copyright-Angaben. Auch hier kommt wieder eine Datumsformatierung anhand des gleichen Beispieldatums (Jahr 2006) zum Einsatz.
Eine minimalistische CSS-Datei soll unter assets/style.css zu liegen kommen:
Code: Alles auswählen
body {
margin: 0 auto;
max-width: 30em;
}
p {
text-align: justify;
}
Inhalt
Nun geht es ans Erstellen des ersten Eintrags. Hierbei ist uns Hugo behilflich:
Code: Alles auswählen
$ hugo new content/hallo-welt.md
Code: Alles auswählen
---
title: "Hallo Welt"
date: 2024-12-10T20:49:25+01:00
draft: false
---
Liebes Tagebuch. Es freut mich, mit dir bekannt zu werden. Ich möchte dich in Zukunft täglich pflegen und dich mit Inhalt füllen. Dank Hugo geht das sehr kombortabel und W3C-Standardkonform obendrein!
Code: Alles auswählen
$ hugo new content/dfde-adventskalender.md
Code: Alles auswählen
---
title: "DFDE-Adventskalender"
date: 2024-12-10T20:54:18+01:00
draft: false
---
Liebes Tagebuch. Ich sollte wirklich an meinem Zeitmanagement arbeiten. Es ist Dienstagabend kurz vor 21 Uhr, und ich bin nun seit ungefähr einer Stunde daran, meinen Türchen für morgen zu schreiben. Damit hätte ich schon [im Oktober](https://debianforum.de/forum/viewtopic.php?t=190688) anfangen sollen! Aber letztes Jahr ging ja auch alles gut.
Code: Alles auswählen
$ hugo server
Eine Seite, die unter der angegebenen Domain (siehe baseURL in config.toml) ausgeliefert werden kann, wird folgendermassen ins public-Verzeichnis generiert:
Code: Alles auswählen
$ hugo
Nun?
Was meint ihr zu Hugo? Kommt das für euch in Frage? Ist die Template-Sprache einigermassen verständlich? Habt ihr Lust bekommen, einen kleinen Blog zu starten?
Nachtrag: Offenbar macht die Forensoftware völlig unnötig einen Link aus tagebuch.paedubucher.ch. Die Seite existiert nicht, und ich habe die URL mit tt-Tags umgeben. Warum die als Hyperlink angezeigt wird, ist mir schleierhaft.