Den Blog hier baue ich mit Hugo. Hugo ist ein statischer Site-Generator. Im Hintergrund läuft kein CMS, keine Datenbank, kein PHP. Am Ende fällt nur statisches HTML raus, das jeder Webspace ausliefern kann.
Was ist Hugo
Hugo ist ein Static Site Generator, geschrieben in Go. Aus Markdown-Dateien, Templates und einer Konfiguration baut Hugo eine fertige Webseite aus statischem HTML. Diese Dateien legst Du auf einem beliebigen Webspace ab.
Was der Browser bekommt, sind nur HTML, CSS, JavaScript und Bilder. Die Seite ist beim Aufruf schon fertig generiert, der Server liefert sie nur aus.
Hugo ist Open Source und auf gohugo.io zu finden.
Hugo und WordPress
Mit WordPress arbeite ich seit über 20 Jahren, privat und beruflich, viel und intensiv. Das eine ist nicht besser als das andere, nur anders, und liegt dem einen oder anderen vielleicht mehr.
WordPress ist ein dynamisches CMS, Inhalte liegen in einer Datenbank, gerendert wird bei jedem Aufruf, bearbeitet im Web-Backend. Hugo dreht das um. Aus Markdown-Dateien baut Hugo einmal HTML, das nur noch ausgeliefert wird. Inhalt sind Dateien im Dateisystem, Editor frei wählbar.
Für meinen Blog wollte ich genau das. Lokal in neovim schreiben, in Markdown, und mich nicht um PHP, Datenbank und Plugin-Kompatibilität kümmern müssen.
Installation
Hugo läuft auf macOS, Linux und Windows. Auf dem Mac:
brew install hugo
Für die anderen Systeme stehen die Optionen in der Hugo-Doku. Auf dem Server selbst muss Hugo nicht installiert sein, Du brauchst es nur lokal zum Bauen.
Aufbau einer Hugo-Site
Eine neue Site legst Du mit einem Befehl an:
hugo new site meinblog
cd meinblog
Standardmäßig schreibt Hugo dabei eine hugo.toml. Wer lieber YAML mag, hängt --format yaml an:
hugo new site meinblog --format yaml
Ich nutze YAML, weil ich es lesbarer finde und PaperMod das im Wiki empfiehlt.
Im Ordner findest Du:
meinblog/
├── archetypes/ Vorlagen für neue Inhalte
├── assets/ Quelldateien für Pipelines, etwa Bilder oder CSS
├── content/ Deine Beiträge als Markdown
├── data/ Strukturierte Daten als YAML oder JSON
├── i18n/ Übersetzungen für Theme-Strings
├── layouts/ Eigene Templates, überschreiben das Theme
├── public/ Wird beim Build erzeugt, das ist die fertige Site
├── static/ Wird 1:1 nach public kopiert
├── themes/ Themes als Submodul oder Klon
└── hugo.yaml Konfiguration (oder hugo.toml, hugo.yml, hugo.json)
Die meiste Zeit lebst Du in content/ und im Theme.
Beiträge liegen üblicherweise als Page Bundles unter content/blog/<jahr>/<slug>/. Ein Page Bundle ist ein Ordner mit index.md und allem, was zum Beitrag gehört. Übersetzungen wie index.en.md leben darin.
Konfiguration
Bei einer frischen Site liegt die ganze Konfiguration in einer einzigen Datei im Projekt-Root. Für mehrere Umgebungen erlaubt Hugo eine aufgeteilte Variante unter config/_default/ mit Overrides pro Umgebung wie config/production/. So habe ich es hier eingerichtet: Basis unter config/_default/config.yml, eine kleine Production-Variante mit dem produktiven baseURL. Praktisch, wenn Du in der Entwicklung einen anderen baseURL brauchst als im Live-Build.
Ein Minimalbeispiel als hugo.yaml:
baseURL: "https://example.com/"
title: "Mein Blog"
theme: hugo-PaperMod
defaultContentLanguage: de
languages:
de:
languageName: "Deutsch"
weight: 1
en:
languageName: "English"
weight: 2
params:
ShowReadingTime: true
ShowToc: true
defaultTheme: auto
baseURL ist die produktive Adresse, wichtig für Sitemap, RSS und absolute Links. theme ist der Ordnername unter themes/. Mit defaultContentLanguage und languages baust Du Mehrsprachigkeit. Die Default-Sprache hat kein Sprachkürzel im Pfad, alle anderen liegen unter /<sprachkürzel>/. Was unter params geht, hängt vom Theme ab.
Themes am Beispiel PaperMod
Ein Theme bringt das Aussehen und die Layouts mit. Du installierst es einmal, konfigurierst es über params: und Hugo nimmt die Templates aus dem Theme, wenn es in Deinem Projekt keine eigenen gibt.
Ich nutze PaperMod. Aktiv gepflegt, mit Dark-Mode-Toggle, Suche, Archiven und Inhaltsverzeichnis. Die Installations-Anleitung im Wiki ist ausführlich, kurzform als Git-Submodul:
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/hugo-PaperMod
In der Config aktivieren:
theme: hugo-PaperMod
PaperMod hat eine ganze Reihe eigener Schalter, die Liste steht ebenfalls im Wiki. Auch eigene Shortcodes wie figure, collapse, audio und video bringt das Theme mit.
Inhalte schreiben
Beiträge sind Markdown-Dateien mit einem YAML-Frontmatter oben drin:
---
title: "Mein erster Beitrag"
date: 2026-04-27
description: "Kurzer Anriss für Vorschau und SEO."
categories: ["Tech"]
tags: ["hugo"]
draft: false
---
Hier kommt der Text. Markdown wie immer.
Du brauchst dafür kein spezielles Werkzeug. Markdown öffnest Du mit jedem Texteditor, von VS Code über Sublime Text bis Vim oder neovim. Die Datei landet im richtigen Ordner unter content/, beim nächsten Build ist der Beitrag dabei.
Für strukturierte Vorlagen gibt es Archetypes. In archetypes/<typ>.md legst Du eine Vorlage an, der Befehl hugo new füllt sie aus.
Hugo-Befehle für den Alltag
Die paar Befehle, die Du am häufigsten brauchst:
# Neue Site anlegen
hugo new site meinblog
# Neuen Beitrag aus dem Default-Archetype anlegen
hugo new content blog/2026/mein-beitrag/index.md
# Lokalen Server mit Drafts und Live-Reload
hugo server --buildDrafts
# Fertig bauen für Produktion (nach public/)
hugo --minify
hugo server läuft auf Port 1313. Während er läuft, baut Hugo bei jeder Dateiänderung neu und der Browser lädt automatisch.
Statische Seite zum Hoster bringen
Nach hugo --minify liegt die komplette Seite in public/. Was Du damit machst, ist Deine Wahl. Üblich sind rsync über SSH, rclone für SFTP, S3 und WebDAV, git push zu Anbietern wie Netlify oder Cloudflare Pages, oder aws s3 sync. Ich packe das gerne in ein deploy.sh im Projekt-Root, das Build und Upload zusammenfasst:
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
hugo --minify
rclone copy public/ <remote>:/<zielpfad>/ \
--exclude ".DS_Store" \
--progress
<remote> ist Dein vorher mit rclone config angelegtes Ziel, <zielpfad> das Verzeichnis beim Hoster. Skript ausführbar machen mit chmod +x deploy.sh, dann reicht ein Aufruf zum Bauen und Hochladen.
Hugo direkt im Editor
Vieles davon sind kleine, wiederkehrende Schritte, die ich direkt aus neovim heraus erledige. Wie das aussieht, beschreibe ich in einer eigenen Reihe rund um mein Plugin hugo-cms.nvim.