
Denkpass.de läuft in Hugo und deployed automatisch
Auf meiner Arbeit, bei alpha-board gmbh, einem Berliner Dienstleister für agile Hardware-Entwicklung und PCB-Design / Layouts, haben wir vor kurzem unsere Webseite mithilfe eines LLMs zu 11ty.dev portiert, und auch automatisches deployen mit Git-Actions eingerichtet.
Auf Arbeit nutzen wir Github Copilot und der hat das hingekriegt: ich schreibe eine Markdown-Datei in einem speziellen Ordner, pushe dann den ganzen Ordner nach git und dort wird es mit 11ty gebaut und danach auf https://alpha-board.de deployed.
Da habe ich mir gedacht, so eine coole Sache brauche ich auch für Denkpass.de, denn wenn es so einfach ist, blogge ich vielleicht öfter? Also habe ich mich mit Chat-GPT hingesetzt, um dieses Blog zu Static Site Generator Hugo zu portieren. Das lief gut, aber dies Blog ist ja auch recht simpel.
Probleme gab es, als ich nachts in meinem Editor zed irgendeine Tastenkombination betätigte und auf einmal in mehreren Dateien irgendwas einfügte und umher schob. Das hielt mich eine Weile auf und ich zweifelte schon langsam, ob ich das mit einem LLM wirklich hinkriege. Aber am Ende läuft es, wie man sieht.
Künftig fällt also Bloggen viel einfacher. Unter Umständen blogge ich dann also öfter.
Setup von Hugo
- Hugo + Whiteplain Theme
- Inhalte in /content/posts/
- Lokales Setup über Python3-Skript für Frontmatter-Anpassung mit YAML (für Import von Frontmatter aus Jekyll-Setup)
- Preview via
hugo server
- Feed via jekyll-feed ersetzt durch Hugo RSS unter /index.xml
Der eigentliche Grund, von Jekyll abzuhauen war ja, dass mein LLM-Kumpel und ich Probleme hatten, das System zu updatem, weil eine Abhängigkeit bei Jekyll, die mit jekyll-feed zu tun hatte, auf meinem Silicon-Apple nicht installieren wollte. Da kam dann nach einer Weile die Idee auf, einfach nur die Blogposts, die in Markdown vorlagen, zu einem anderen Static Site Generator zu übertragen.
Die Installation Hugo ist einfach, s.Hugo Quick Start. Die Markdown-Blogposts aus Jekyll gingen einfach zu übertragen, nur am Frontmatter mussten wir arbeiten und haben dafür ein kleines Skript geschrieben (und ein Virtual Environment für Python aufgemacht, um das Skript auszuführen). Hier das Skript, dass Frontmatter von Jekyll anfässt und für Hugo umschreibt:
from pathlib import Path
import yaml
posts_path = Path("./content/posts") # anpassen, falls nötig
for md_file in posts_path.glob("*.md"):
content = md_file.read_text(encoding="utf-8")
if content.startswith("---"):
parts = content.split("---", 2)
if len(parts) >= 3:
_, front_matter_raw, body = parts
try:
front_matter = yaml.safe_load(front_matter_raw)
# Felder anpassen
front_matter.pop("layout", None)
if isinstance(front_matter.get("tags"), str):
front_matter["tags"] = [front_matter["tags"]]
elif isinstance(front_matter.get("tags"), list):
flat = []
for item in front_matter["tags"]:
if isinstance(item, str) and "," in item:
flat.extend([t.strip() for t in item.split(",")])
else:
flat.append(item)
front_matter["tags"] = flat
if "date" in front_matter:
front_matter["date"] = str(front_matter["date"])
# Neue Datei schreiben
new_content = "---\n" + yaml.dump(front_matter, sort_keys=False) + "_
Hugo individualisieren mit CSS und eigenem HTML
Das hier ging eigentlich alles gut, bis ich meinen nächtlichen Editor-Tasten-Krieg erlebte und nichts mehr lief. Wir probierten rum, aber dabei war auch eine Datei (custom.css) in einem falschen Verzeichnis gelandet, wo sie nicht funktionierte. Nur brauchten wir eine Weile, bis das auffiel. Chat-GPT fragte irgendwann, ob ich sicher sei, dass diese Datei wirklich in diesem Verzeichnis liegt. Und da prüfte ich das im Finder statt in meinem Editor und sah es auf einmal.
Beim Aufsetzen eines Blogs mit Hugo kann man sich ein Hugo-Theme aussuchen. Das landet dann im Verzeichnis deiner Hugo-Seite unter /themes/name_deines_themes
, in meinem Fall Whiteplain. Jetzt was Wichtiges: Wenn du was ändern willst, z.B. den Footer, dann kopierst Du die entsprechende Datei aus dem Theme (also z.B. themes/whiteplain/layouts/partials/footer.html
) an den entsprechenden Ort in deinem Hugo-Verzeichnis, in diesem Fall /layouts/partials/footer.html
. Dann kann sich das Theme aktualisieren, aber Hugo nimmt immer deine Kopie anstatt der des Themes.
Dasselbe gilt für custom.css. Wenn Du eine custom.css in /static/css/
erzeugst, überschreibt diese mit ihren Regeln alle vorher getroffenen CSS-Styles, z.B. aus dem Theme. So bleiben die CSS-Einstellungen, die dir wichtig sind, immer im selben File.
- Menü mit: Blog / Tags / Impressum / Suche / Substack / RSS
- Suche live mit JavaScript (lunr.js)
- Footer mit: Lizenz (CC BY-SA 4.0), LinkedIn
- Tag-Seite mit gewichteter Liste
- Sprache Deutsch (Datum lokalisiert)
- Monospace-Font: Fira Code lokal eingebunden
- Nur letzte 10 Artikel auf Startseite
- Readme.md als Impressum / Readme im Menü
- Mobile Menü wurde ausprobiert, wieder verworfen (flex-direction rückgesetzt, noch offen)
- Style.css wieder korrekt eingebunden
Automatisches Deployment via Netlify
Nachdem ich mein Hugo-Verzeichnis aufgesetzt, mit Blogposts gefüllt hatte, habe ich das ganze Verzeichnis zu Github gepusht. Dann habe ich auf Netlify einen kostenlosen Account eröffnet und dort ein neues Projekt mit meinem Github-Repository für Denkpass.de mit Hugo verbunden:
Git-Repository mit Netlify verbinden
- Logge dich bei Netlify ein.
- Klicke auf “Add new site” → “Import an existing project”.
- Wähle GitHub (oder GitLab/Bitbucket) und gib den Zugriff frei.
- Wähle das Repository mit der Hugo-Seite.
- Gib folgende Werte ein:
- Branch to deploy:
main
odermaster
- Build command:
hugo
- Publish directory:
public
- Branch to deploy:
- Klicke auf “Deploy site”.
Netlify baut nun die Seite bei jedem Push auf dein Repository automatisch neu.
Domain mit Netlify verbinden (z. B. denkpass.de)
Option 1 – Netlify verwaltet DNS (optional)
Wenn du möchtest, dass Netlify auch deine DNS-Zone verwaltet, musst du die Nameserver beim Domain-Provider umstellen:
Nameserver |
---|
dns1.p04.nsone.net |
dns2.p04.nsone.net |
dns3.p04.nsone.net |
dns4.p04.nsone.net |
Danach richtest du deine Domain direkt in Netlify ein und Netlify setzt die A/CNAME-Einträge selbst.
Option 2 - Beim Domain-Provider (z. B. Netcup, IONOS) DNS-Einträge setzen
Wenn du die DNS-Einträge selbst verwaltest (z. B. bei Netcup, IONOS, Cloudflare), gehst Du dort hin ins Setup und gibst diese Werte in dein DNS ein:
Typ | Name | Ziel |
---|---|---|
A | denkpass.de oder leer | 75.2.60.5 |
A | denkpass.de oder *leer" | 99.83.190.102 |
CNAME | www | dein-site-name.netlify.app (z. B. eiapopeia-salomina-8c6079.netlify.app ) |
Wichtig: Entferne alte A- oder CNAME-Einträge, die noch auf den vorherigen Hoster zeigen (z. B. 213.160.x.x). Einträge mit mail solltest Du aber stehen lassen.
Netlify-Einstellungen konfigurieren
Custom Domain einrichten:
- Gehe in Netlify zu:
Site Settings → Domain Management
- Klicke auf “Add custom domain”
- Trage
denkpass.de
ein und bestätige - Klicke auf “Verify DNS configuration”
Das kann eine Weile dauern, also geduldig bleiben. Bei mir wurde alles in nicht mal einer Stunde übertragen.
HTTPS aktivieren:
Nach erfolgreicher DNS-Prüfung erscheint die Option:
“Provision certificate”
Klicke darauf, um ein kostenloses SSL-Zertifikat (Let’s Encrypt) und somit auch https
zu aktivieren. Netlify kümmert sich danach automatisch um die Verlängerung des Zertifikats.
- Jeder
git push
ins verknüpfte Repo triggert automatisch einen neuen Deploy. - Du kannst bei Netlify auch manuell ein neues Deployment starten (“Trigger deploy”).
- Für Live-Preview nutze
https://dein-site-name.netlify.app
, auch wenn DNS noch nicht propagiert ist.
Noch offen
Hier stehen ein paar Punkte, die noch in Bearbeitung sind. Wir haben nicht alles geschafft und irgendwann wollte ich einfach was posten und deployen.
- Optional: Subdomain-Verknüpfung
- Optional: Newsletter richtig einbetten statt nur Link
- Optional: Tag-Cloud als visuelle Darstellung
VENV, neue Fonts, etc.
Damit Frontmatter geändert werden konnte, liessen wir ein Python-Skript laufen. Dafür haben wir auch ein Virtual Environment aufgesetzt, dass auch gegitted wurde (auch wenn wir eigentlich keine Frontmatter mehr importieren wollen).
Ich fand, ich wollte schon immer mal ein Blog mit einem Monospace-Font haben und habe mich für Fira Code entschieden.
Wir haben auch eine Readme.md aufgesetzt, die als Impressum fungiert. Damit sie im Blog nicht zuoberst angezeigt wird (sondern nur in der oberen Menüleiste), habe ich sie weit zurück datiert. So wird sie nun irgendwo unter allen Posts angezeigt, falls da mal jemand hinscrollt.
- Python venv für Frontmatter-Konvertierung:
hugo-denkpass-venv
- Fonts lokal in /static/fonts/
- Styles in /static/css/custom.css
- Search-Template in /layouts/pages/search.html
- Readme.md: datiert auf 2017 für Sortierung