Aller au contenu
Documentation medium

Hugo : créer un site de documentation DevOps

75 min de lecture

logo hugo

Hugo transforme des fichiers Markdown en un site de documentation professionnel en quelques millisecondes. C'est un binaire unique écrit en Go, sans dépendance runtime (pas de Node.js, pas de Python, pas de Ruby). Combiné au thème Relearn (l'équivalent Hugo de Material for MkDocs), on obtient un outil complet pour toute équipe DevOps : notices (admonitions), onglets synchronisés, diagrammes Mermaid, recherche Lunr, mode sombre et déploiement en une commande. Ce guide couvre l'installation, la configuration complète, le contenu enrichi et le déploiement CI/CD. Prérequis : Git installé.

  • Installer Hugo extended depuis un binaire vérifié par empreinte, sur Linux, macOS, Windows ou en conteneur
  • Monter un projet complet avec le thème Relearn en sous-module Git, et le servir en local
  • Configurer le site : navigation, recherche Lunr, mode sombre, coloration syntaxique
  • Rédiger du contenu enrichi avec les notices, onglets, diagrammes Mermaid, cartes et badges de Relearn
  • Structurer le contenu avec les archétypes, la cascade de front matter et les taxonomies
  • Déployer en CI/CD sur GitHub Pages, GitLab Pages ou Netlify, thème inclus

Hugo est un générateur de site statique (SSG) écrit en Go, créé par Steve Francia en 2013. Son principal atout : la vitesse. Là où d'autres SSG mettent plusieurs secondes à builder un site, Hugo le fait en quelques dizaines de millisecondes.

Le fonctionnement tient en trois temps : Hugo lit les fichiers Markdown du dossier content/, les injecte dans des templates Go fournis par le thème, puis écrit des fichiers HTML statiques dans public/. Aucun code ne s'exécute ensuite côté serveur : n'importe quel hébergeur de fichiers statiques suffit.

CaractéristiqueHugoMkDocsJekyll
LangageGo (binaire unique)PythonRuby
Dépendances runtimeAucune (binaire autonome)pip + extensionsgem + bundler
Vitesse de buildTrès rapide (ms)Rapide (secondes)Lent (dizaines de secondes)
MultilingueNatifPluginPlugin
Formats de contenuMarkdown, AsciiDoc, Org, HTMLMarkdownMarkdown, HTML
ThèmesLarge catalogue200+ (Material domine)500+
Traitement d'imagesIntégré (resize, crop, filtres)NonPlugin

Hugo est particulièrement adapté aux projets de documentation DevOps pour plusieurs raisons :

  • Pas de dépendances runtime : un seul binaire à installer, idéal en CI/CD (les thèmes et modules peuvent toutefois ajouter des prérequis)
  • Build ultra-rapide : feedback instantané pendant la rédaction
  • Multilingue natif : documentation en plusieurs langues sans plugin
  • Traitement d'images intégré : redimensionnement, conversion à la volée
  • Modules Go : partager des composants de documentation entre projets

Avant de commencer, vérifiez que votre machine dispose de :

  • Git : pour le versioning et l'installation de thèmes
  • Un éditeur de texte (VS Code recommandé avec l'extension Hugo)
  • Aucune autre dépendance (Hugo est un binaire autonome)
Fenêtre de terminal
git --version

Vérification : cette commande doit afficher la version de Git installée. Si Git n'est pas trouvé, installez-le avec sudo apt install git (Debian/Ubuntu) ou brew install git (macOS).

Hugo existe en deux éditions :

  • Hugo : la version de base, suffisante pour la plupart des usages
  • Hugo extended : ajoute le support Sass/SCSS et le traitement d'images avancé avec WebP, c'est celle qu'on recommande (le thème Relearn nécessite extended pour certaines fonctionnalités)
Fenêtre de terminal
# Télécharger l'archive ET le fichier de sommes de contrôle officiel
curl -fsSLO \
https://github.com/gohugoio/hugo/releases/download/v0.164.0/hugo_extended_0.164.0_linux-amd64.tar.gz
curl -fsSLO \
https://github.com/gohugoio/hugo/releases/download/v0.164.0/hugo_0.164.0_checksums.txt
# Vérifier l'intégrité AVANT d'extraire quoi que ce soit
sha256sum --check --ignore-missing hugo_0.164.0_checksums.txt
# Extraire uniquement le binaire, puis le rendre accessible
tar xzf hugo_extended_0.164.0_linux-amd64.tar.gz hugo
sudo install -o root -g root -m 0755 hugo /usr/local/bin/hugo

La commande sha256sum --check doit afficher le nom de l'archive suivi de OK (Réussi en locale française). Si elle signale une non-concordance, l'archive a été altérée ou tronquée : ne l'extrayez pas. Cette vérification est la raison pour laquelle on ne redirige jamais un téléchargement directement dans tar : le contenu serait extrait avant tout contrôle.

Vérification :

Fenêtre de terminal
hugo version

Le résultat attendu contient :

hugo v0.164.0-...+extended linux/amd64

Le mot extended confirme que les fonctionnalités avancées sont disponibles.

Un projet Hugo se monte en quatre gestes : générer le squelette, ajouter le thème, écrire la page d'accueil, lancer le serveur. Comptez deux minutes. Le thème est installé en sous-module Git, ce qui fige sa version dans votre dépôt et permet à la CI de le récupérer sans dépendance supplémentaire.

  1. Créez le squelette du projet :

    Fenêtre de terminal
    hugo new site mon-site-docs
    cd mon-site-docs

    Hugo génère la structure suivante :

    mon-site-docs/
    ├── archetypes/
    │ └── default.md # Template pour le nouveau contenu
    ├── assets/ # Fichiers traités par Hugo Pipes (Sass, JS...)
    ├── content/ # Contenu Markdown
    ├── data/ # Données structurées (YAML, JSON, TOML)
    ├── i18n/ # Traductions (multilingue)
    ├── layouts/ # Templates personnalisés
    ├── static/ # Fichiers copiés tels quels (images, CSS, PDF...)
    ├── themes/ # Thèmes installés
    └── hugo.toml # Configuration du projet
  2. Installez le thème Relearn :

    Fenêtre de terminal
    git init
    git submodule add \
    https://github.com/McShelby/hugo-theme-relearn.git \
    themes/hugo-theme-relearn
  3. Créez la page d'accueil :

    content/_index.md
    +++
    archetype = "home"
    title = "Documentation DevOps"
    description = "Documentation technique de notre équipe DevOps"
    +++
    Bienvenue sur la **documentation technique** de l'équipe DevOps.
    {{% children %}}

    Le shortcode {{% children %}} génère automatiquement la liste des sections enfants. L'archétype "home" indique à Relearn d'utiliser le template de la page d'accueil.

  4. Lancez le serveur de développement :

    Fenêtre de terminal
    hugo server -D

    Le site est accessible sur http://localhost:1313. Le -D inclut les brouillons (pages avec draft = true). Le live reload est activé par défaut : chaque sauvegarde rafraîchit automatiquement le navigateur.

Page d'accueil Hugo Relearn avec menu latéral dépliable, barre de recherche et sélecteur de thème

Si ça ne marche pas : si le port 1313 est déjà utilisé, changez-le avec hugo server -p 1314.

Le fichier hugo.toml (ou hugo.yaml / hugo.json) centralise toute la configuration. Quand on modifie ce fichier, Hugo recharge automatiquement le site si le serveur tourne.

La configuration ci-dessous est un modèle complet et commenté, adapté à une documentation d'équipe DevOps. Chaque section est expliquée après le bloc :

hugo.toml
# -- Métadonnées du site --
baseURL = 'https://mon-equipe.github.io/docs/'
languageCode = 'fr'
title = 'Documentation DevOps'
theme = 'hugo-theme-relearn'
enableGitInfo = true
# -- Paramètres Relearn --
[params]
author.name = 'Équipe DevOps'
editURL = 'https://github.com/mon-org/docs/edit/main/content/${FilePath}'
titleSeparator = '::'
showVisitedLinks = true # Coche les pages déjà lues
collapsibleMenu = true # Menu latéral dépliable
alwaysopen = false # Sections fermées par défaut
ordersectionsby = 'weight' # Trier par poids (pas alphabétique)
themeVariant = ['auto', 'relearn-light', 'relearn-dark']
[params.image]
errorlevel = 'warning'
[params.imageEffects]
border = true # Bordure autour des images
lightbox = true # Zoom au clic sur les images
lazy = true # Chargement différé (performance)
shadow = false
# -- Recherche (Lunr) --
[params.search]
[params.search.adapter]
identifier = 'lunr' # Moteur de recherche côté client
# -- Coloration syntaxique --
[markup]
[markup.highlight]
codeFences = true # Blocs ``` activés
guessSyntax = true # Détection automatique du langage
lineNumbersInTable = false
noClasses = false # Utilise des classes CSS (pas inline)
style = 'monokai' # Thème de coloration
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = false # Interdit le HTML brut (sécurité XSS)
[markup.goldmark.extensions.extras.delete]
enable = true # ~~texte barré~~
[markup.goldmark.extensions.extras.insert]
enable = true # ++texte inséré++
[markup.goldmark.extensions.extras.mark]
enable = true # ==texte surligné==
[markup.goldmark.extensions.extras.subscript]
enable = true # H~2~O
[markup.goldmark.extensions.extras.superscript]
enable = true # E = mc^2^
[markup.goldmark.extensions.passthrough]
enable = true # Formules MathJax
[markup.goldmark.extensions.passthrough.delimiters]
inline = [['$', '$']] # $O(n \log n)$
block = [['$$', '$$']] # $$ ... $$
[markup.goldmark.parser.attribute]
block = true # Attributs sur blocs {.class}
[markup.tableOfContents]
endLevel = 4
ordered = false
startLevel = 2
# -- Taxonomies --
[taxonomies]
tag = 'tags'
category = 'categories'
# -- Formats de sortie --
[outputs]
home = ['html', 'rss', 'print'] # 'print' active l'impression Relearn

Vérification : lancez hugo config pour afficher la configuration active et détecter les erreurs de syntaxe. Le site doit se recharger avec le thème Relearn, le menu latéral et le sélecteur de thème.

Décomposons les sections clés de cette configuration :

Paramètres Relearn : la section [params] contrôle le comportement du thème. collapsibleMenu rend le menu latéral dépliable (les sections se ferment/ouvrent au clic). showVisitedLinks coche les pages déjà visitées, pratique pour suivre la progression dans une formation. editURL génère automatiquement un lien "Modifier cette page" vers votre dépôt Git, avec ${FilePath} remplacé par le chemin du fichier source.

Variantes de thème : themeVariant définit les thèmes disponibles. auto suit les préférences système (clair/sombre). Le sélecteur se trouve en bas à gauche du menu latéral. D'autres variantes intégrées sont disponibles : zen-light, zen-dark, neon, blue, green, red.

Recherche Lunr : la recherche est activée côté client (aucun serveur nécessaire). Lunr indexe automatiquement les titres, le contenu et les tags. Le raccourci clavier pour ouvrir la recherche est accessible via l'icône de loupe.

Barre de recherche Lunr avec suggestions et résultats en temps réel

Extensions Goldmark : c'est la liste des extensions qui enrichissent la syntaxe Markdown. Sans elles, vous n'avez que le Markdown de base. Chaque extension ajoute une fonctionnalité : delete pour le texte barré, mark pour le surlignage, passthrough pour les formules MathJax. Ces extensions sont natives de Hugo (Goldmark), pas du thème Relearn.

Formats de sortie : print active le bouton d'impression de Relearn, qui génère une version imprimable de la page ou de la section entière.

Dans Hugo, l'arborescence de content/ détermine les URL et la navigation : il n'existe aucun fichier de sommaire à maintenir en parallèle. Déplacer un fichier change donc son adresse publique, et renommer un dossier réorganise le menu latéral. Cette section détaille les briques qui structurent ce contenu : pages, front matter, sections, taxonomies, bundles et archétypes.

Cette commande ne crée pas un fichier vide : elle applique l'archétype correspondant au chemin et pré-remplit le front matter, dont un draft = true qui empêchera la page d'être publiée tant que vous ne l'aurez pas retiré.

Fenêtre de terminal
hugo new content guides/installer-docker.md

Le répertoire content/ est implicite : Hugo place automatiquement le fichier dans content/guides/installer-docker.md.

Hugo utilise l'archétype archetypes/default.md comme template. Le fichier créé contient un front matter pré-rempli :

content/guides/installer-docker.md
+++
date = '2026-02-25T08:00:00+01:00'
draft = true
title = 'Installer Docker'
+++

Le front matter Hugo supporte TOML (+++), YAML (---) et JSON ({}).

Au-delà des quatre champs générés, Hugo reconnaît une série de clés qui pilotent le classement et l'affichage. Les champs libres se rangent sous [params] : Hugo ne les interprète pas, mais ils restent accessibles aux templates et aux thèmes.

Front matter complet
+++
title = 'Installer Docker sur Ubuntu'
date = 2026-02-25T08:00:00+01:00
draft = false
tags = ['docker', 'conteneurs', 'ubuntu']
categories = ['guides']
description = 'Guide pas à pas pour installer Docker CE sur Ubuntu.'
weight = 10
[params]
difficulty = 'debutant'
duration = '10 min'
+++

Le champ weight contrôle l'ordre d'affichage dans les listes et les menus (Relearn utilise ordersectionsby = 'weight' pour trier les pages). Les tags et categories créent automatiquement des taxonomies (pages de regroupement).

Chaque dossier dans content/ doit avoir un fichier _index.md. Dans Relearn, on utilise l'archétype chapter pour les sections principales :

content/guides/_index.md
+++
archetype = "chapter"
title = "Guides"
weight = 1
+++
Guides pas à pas pour installer et configurer les outils DevOps.

Le fichier _index.md est la page de section : il contrôle le titre, la description et le contenu affiché pour chaque dossier dans le menu latéral. Sans lui, Hugo génère une liste automatique mais le rendu est dégradé.

Pour un projet docs-as-code, organisez le contenu par type de document :

content/
├── _index.md # Page d'accueil (archetype "home")
├── guides/ # Guides pas à pas
│ ├── _index.md # Chapitre (archetype "chapter")
│ ├── installer-docker.md
│ └── configurer-nginx.md
├── runbooks/ # Procédures d'exploitation
│ ├── _index.md
│ ├── incident-base-de-donnees.md
│ └── rollback-production.md
├── reference/ # Référence CLI, API, configuration
│ ├── _index.md
│ └── cli-kubectl.md
├── adr/ # Architecture Decision Records
│ └── _index.md
└── onboarding/ # Guides de démarrage pour les nouveaux
└── _index.md

Cette structure correspond aux besoins réels d'une équipe DevOps : les guides expliquent comment faire, les runbooks disent quoi faire en situation d'urgence, les ADR documentent les décisions d'architecture, et la référence sert de mémento quotidien.

Les taxonomies sont le système de classification de Hugo. Par défaut, Hugo crée deux taxonomies : tags et categories. Chaque taxonomie génère automatiquement des pages de listing (la liste de tous les tags, la liste de toutes les pages ayant un tag donné).

La configuration dans hugo.toml déclare les taxonomies actives :

hugo.toml (extrait)
[taxonomies]
tag = 'tags'
category = 'categories'

Dans le front matter de chaque page, on assigne les valeurs :

content/guides/installer-docker.md (extrait)
+++
title = 'Installer Docker sur Ubuntu'
tags = ['docker', 'conteneurs', 'ubuntu']
categories = ['guides']
+++

Hugo génère automatiquement :

  • /tags/, page listant tous les tags utilisés
  • /tags/docker/, page listant toutes les pages taguées "docker"
  • /categories/guides/, page listant toutes les pages de la catégorie "guides"

On peut créer des taxonomies personnalisées pour des besoins spécifiques. Par exemple, pour classer les guides par niveau de difficulté :

hugo.toml
[taxonomies]
tag = 'tags'
category = 'categories'
difficulty = 'difficulties'
Front matter
+++
difficulties = ['debutant']
+++

Hugo crée alors /difficulties/debutant/ avec la liste de toutes les pages marquées "debutant". Relearn affiche les taxonomies dans le menu latéral si elles sont configurées.

Hugo distingue deux types de bundles (dossiers) dans content/ :

TypeFichier indexContenuUsage
Branch bundle_index.mdSection (chapitre) avec sous-pagesDossiers de navigation : guides/, runbooks/
Leaf bundleindex.mdPage unique avec ses ressourcesPage autonome avec images, fichiers associés

Un branch bundle (_index.md) crée une section dans l'arborescence. C'est ce qu'on utilise pour chaque dossier du menu latéral. Le contenu de _index.md s'affiche quand on clique sur la section.

Un leaf bundle (index.md, sans underscore) crée une page autonome qui regroupe ses ressources (images, PDF, fichiers de données) dans le même dossier :

content/guides/installer-docker/
├── index.md # Le contenu de la page
├── architecture.png # Image locale (page resource)
├── docker-compose.yaml # Fichier joint
└── data.json # Données associées

L'intérêt des leaf bundles est de garder les ressources à côté du contenu qui les utilise. On accède à l'image directement dans le Markdown :

![Architecture Docker](architecture.png)

Pas besoin de chemin absolu ou de dossier static/. Hugo résout le chemin automatiquement par rapport au bundle.

Les archetypes sont des templates de front matter utilisés par la commande hugo new content. L'archétype par défaut se trouve dans archetypes/default.md. On peut créer des archetypes spécialisés par type de document.

Archétype pour un guide :

archetypes/guides.md
+++
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
date = {{ .Date }}
draft = true
tags = []
categories = ['guides']
description = ''
weight = 0
[params]
difficulty = 'debutant'
duration = ''
+++
## Prérequis
## Installation
## Configuration
## Vérification
## Dépannage

Archétype pour un runbook :

archetypes/runbooks.md
+++
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
date = {{ .Date }}
draft = true
tags = []
categories = ['runbooks']
description = ''
weight = 0
[params]
severity = 'medium'
estimated_time = '15 min'
+++
## Symptômes
## Diagnostic
## Résolution
## Post-mortem

Hugo sélectionne l'archétype en fonction du chemin passé à hugo new content :

Fenêtre de terminal
# Utilise archetypes/guides.md
hugo new content guides/configurer-nginx.md
# Utilise archetypes/runbooks.md
hugo new content runbooks/incident-redis.md
# Utilise archetypes/default.md (fallback)
hugo new content onboarding/premier-jour.md

Les archetypes standardisent la structure des documents et font gagner du temps à toute l'équipe : chaque nouveau guide ou runbook part d'un squelette cohérent.

Le mécanisme de cascade permet d'appliquer des propriétés du front matter à toutes les pages descendantes d'une section. Cela évite de répéter les mêmes valeurs dans chaque fichier.

content/guides/_index.md
+++
archetype = "chapter"
title = "Guides"
weight = 1
[cascade]
[cascade.params]
difficulty = 'intermediaire'
[cascade._target]
kind = 'page'
+++

Toutes les pages dans content/guides/ héritent automatiquement de params.difficulty = 'intermediaire', sauf si elles le redéfinissent explicitement.

Cas d'usage courants pour la cascade :

  • Bannière de brouillon sur toute une section en cours de rédaction
  • Auteur par défaut pour les pages d'une équipe
  • Catégorie appliquée à toutes les pages d'un dossier
  • Paramètre de thème (ex : désactiver la table des matières sur les runbooks)

Le thème Relearn fournit plus de 20 shortcodes intégrés qui enrichissent considérablement le Markdown standard. Les fonctionnalités sont regroupées par niveau d'utilité :

  • Essentiel : notices, onglets, blocs de code avancés, Mermaid
  • Très utile : badges, boutons, icônes, cartes en grille
  • Bonus : arborescence de fichiers, accordéons, formules MathJax, formatage avancé (barré, surligné, indices)

Commencez par les fonctionnalités essentielles, puis enrichissez au fil des besoins de votre équipe.

Les notices sont l'équivalent Relearn des admonitions de Material for MkDocs. Elles permettent de mettre en valeur des informations importantes avec un code couleur et une icône.

{{%/* notice note "Information" */%}}
Une information complémentaire utile mais pas critique.
Supporte le **Markdown** : `code inline`, *italique*, [liens](/).
{{%/* /notice */%}}
{{%/* notice tip "Astuce" */%}}
Bonne pratique ou raccourci qui fait gagner du temps.
{{%/* /notice */%}}
{{%/* notice warning "Attention" */%}}
Point qui peut causer des problèmes si ignoré.
{{%/* /notice */%}}
{{%/* notice danger "Danger" */%}}
Action irréversible ou risque de perte de données.
{{%/* /notice */%}}

Les 7 types disponibles sont : note, info, tip, warning, danger, caution, important.

Les 7 types de notices Relearn : note, info, tip, warning, danger, caution et important

Pour créer une notice dépliable (fermée par défaut), on utilise les paramètres nommés :

{{%/* notice style="tip" title="Cliquez pour déplier" expanded="false" */%}}
Ce contenu est masqué par défaut. L'utilisateur doit cliquer pour le voir.
Utile pour les détails optionnels ou les configurations avancées.
{{%/* /notice */%}}

Les onglets permettent de présenter des variantes d'une même procédure (distributions Linux, langages, outils). Relearn synchronise automatiquement les onglets qui partagent le même groupid : cliquer sur "Linux" dans un groupe met à jour tous les autres groupes de la page ayant le même groupid.

{{</* tabs groupid="os" */>}}
{{%/* tab title="Linux" */%}}
```bash {title="Installation Linux"}
sudo apt-get install -y docker.io
sudo usermod -aG docker $USER
```
{{%/* /tab */%}}
{{%/* tab title="macOS" */%}}
```bash {title="Installation macOS"}
brew install --cask docker
```
{{%/* /tab */%}}
{{%/* tab title="Windows" */%}}
```powershell {title="Installation Windows"}
winget install Docker.DockerDesktop
```
{{%/* /tab */%}}
{{</* /tabs */>}}

Onglets synchronisés Linux, macOS et Windows avec contenu adapté à chaque OS

Hugo et Relearn offrent une coloration syntaxique puissante avec des options qui s'ajoutent directement aux blocs de code Markdown :

Titre, numéros de lignes et lignes surlignées :

```python {title="deploy.py", lineNos=true, hl_lines=["2-3"]}
def deploy(env: str) -> bool:
"""Déploie sur l'environnement cible."""
print(f"Déploiement sur {env}...")
return True
if __name__ == "__main__":
deploy("production")
```

avec highlight (shortcode intégré Hugo) :

{{</* highlight python "linenos=table,hl_lines=2 3" */>}}
def deploy(env: str) -> bool:
"""Déploie sur l'environnement cible."""
print(f"Déploiement sur {env}...")
return True
{{</* /highlight */>}}

Les deux syntaxes produisent le même résultat. La syntaxe Markdown avec accolades est plus concise et recommandée.

OptionEffet
{title="fichier.py"}Affiche un titre au-dessus du bloc
{lineNos=true}Numéros de lignes
{hl_lines=["2-3"]}Surligner les lignes 2 et 3
{linenostart=10}Commencer la numérotation à 10

Bloc de code avec titre, numéros de lignes et lignes surlignées dans Relearn

Relearn intègre Mermaid nativement : il suffit d'utiliser un bloc de code avec le langage mermaid. Aucune configuration supplémentaire n'est nécessaire. Mermaid génère des diagrammes à partir de texte, idéal pour documenter des architectures et des flux.

```mermaid
flowchart LR
A[Push Git] --> B[Lint & Tests]
B --> C{Tests OK ?}
C -->|Oui| D[Build Image]
C -->|Non| E[Notification Slack]
D --> F[Push Registry]
F --> G[Deploy Staging]
G --> H{Smoke Tests ?}
H -->|OK| I[Deploy Production]
H -->|KO| J[Rollback]
```

Mermaid supporte de nombreux types de diagrammes : flowcharts, diagrammes de séquence, diagrammes d'architecture (C4-style avec subgraphs), diagrammes de Gantt, diagrammes de classes, diagrammes d'état, etc. Tout est rendu côté client, sans serveur supplémentaire. Relearn ajoute le pan & zoom automatiquement sur les diagrammes.

Diagramme Mermaid flowchart d'un pipeline CI/CD rendu dans Hugo Relearn

Relearn fournit des badges inline, des boutons cliquables et l'accès à toutes les icônes Font Awesome 6 Free.

Badges (intégrés dans le texte) :

- Docker {{%/* badge style="info" */%}}v27.5{{%/* /badge */%}}
- Kubernetes {{%/* badge style="tip" */%}}v1.31{{%/* /badge */%}}
- Status : {{%/* badge style="danger" */%}}Incident{{%/* /badge */%}}

Les styles sont les mêmes que les notices : note, info, tip, warning, danger, important.

Boutons (liens cliquables avec icône) :

{{%/* button href="https://gohugo.io/" style="tip"
icon="fa-fw fas fa-external-link-alt" */%}}Site officiel Hugo{{%/* /button */%}}

Icônes (inline dans le texte) :

- {{%/* icon "fa-fw fas fa-rocket" */%}} Déploiement
- {{%/* icon "fa-fw fas fa-shield-alt" */%}} Sécurité
- {{%/* icon "fa-fw fas fa-database" */%}} Base de données

Le catalogue complet des icônes est disponible sur fontawesome.com/icons. Tous les icônes fas (solid), far (regular) et fab (brands) sont disponibles.

Badges de version, boutons avec icônes et icônes Font Awesome inline dans Relearn

Les cartes organisent le contenu en grille responsive, parfaites pour les pages d'index ou les listes de fonctionnalités. Elles utilisent les shortcodes cards (conteneur) et card (élément) :

{{</* cards */>}}
{{</* card title="Docker" icon="fa-fw fab fa-docker" */>}}
Plateforme de conteneurisation. Isolez vos applications
dans des conteneurs légers et reproductibles.
{{</* /card */>}}
{{</* card title="Kubernetes" icon="fa-fw fas fa-dharmachakra" */>}}
Orchestrateur de conteneurs. Gérez le scaling, le networking
et le déploiement de vos applications.
{{</* /card */>}}
{{</* card title="Terraform" icon="fa-fw fas fa-cloud" */>}}
Infrastructure as Code. Provisionnez et gérez vos ressources
cloud de manière déclarative.
{{</* /card */>}}
{{</* /cards */>}}

Pour des cartes cliquables (qui redirigent vers une page), ajoutez le paramètre href :

{{</* cards */>}}
{{</* card title="Guides" href="/guides/" icon="fa-fw fas fa-book-open" */>}}
Guides pas à pas pour maîtriser les outils DevOps essentiels.
{{</* /card */>}}
{{</* /cards */>}}

Grille de cartes cliquables avec icônes Docker, Kubernetes et Terraform

Le shortcode tree affiche une arborescence de fichiers interactive, parfaite pour montrer la structure d'un projet :

```tree
- mon-site-docs | folder
- archetypes | folder
- default.md
- content | folder
- _index.md
- guides | folder
- _index.md
- installer-docker.md
- layouts | folder
- shortcodes | folder
- callout.html
- themes | folder
- hugo-theme-relearn | folder
- hugo.toml
- .gitignore
```

La syntaxe est simple : chaque ligne est un fichier ou dossier, l'indentation (2 espaces) définit la hiérarchie, et le suffixe | folder marque les dossiers.

Arborescence interactive de fichiers générée par le shortcode tree de Relearn

Le shortcode expand crée des sections dépliables, utiles pour les configurations longues ou les détails optionnels :

{{%/* expand title="Voir la configuration complète" */%}}
```toml {title="hugo.toml"}
baseURL = 'https://docs.example.com/'
languageCode = 'fr'
title = 'Documentation DevOps'
theme = 'hugo-theme-relearn'
```
{{%/* /expand */%}}

Chaque accordéon est fermé par défaut. Le lecteur clique sur le titre pour voir le contenu. C'est l'équivalent des admonitions dépliables ??? de Material for MkDocs.

Accordéon fermé et ouvert avec le shortcode expand de Relearn

Pour les pages nécessitant des formules, ajoutez math = true dans le front matter. La syntaxe utilise les délimiteurs configurés dans hugo.toml (section passthrough) :

Inline :

La complexité du tri rapide est $O(n \log n)$ en moyenne.

Block :

$$
\text{SLA} = \frac{\text{Uptime}}{\text{Uptime} + \text{Downtime}} \times 100
$$

Le rendu est géré par MathJax côté client. Les formules sont utiles pour documenter des calculs de SLA, MTTR, formules de scaling (nombre de réplicas) ou de performance.

Ces fonctionnalités sont activées par les extensions Goldmark dans hugo.toml (pas par le thème Relearn) :

SyntaxeRenduExtension
~~texte barré~~Barré (suppression)extras.delete
==texte surligné==Surbrillance jauneextras.mark
++texte inséré++Souligné (insertion)extras.insert
H~2~OSubscriptextras.subscript
E = mc^2^Superscriptextras.superscript

Formatage avancé Goldmark : texte barré, surligné, inséré, indices et exposants

Au-delà des shortcodes de Relearn, Hugo permet de créer les siens. Les shortcodes sont le mécanisme qui permet d'insérer du HTML complexe tout en restant dans du Markdown, sans activer unsafe = true.

Créez le fichier layouts/shortcodes/callout.html :

layouts/shortcodes/callout.html
<div class="callout callout-{{ .Get 0 | default "info" }}">
<p>{{ .Inner | markdownify }}</p>
</div>

Utilisation dans le Markdown :

{{%/* callout warning */%}}
**Attention** : Hugo nécessite la version extended pour le
support Sass/SCSS.
{{%/* /callout */%}}

Figure avec légende (shortcode intégré Hugo) :

{{</* figure src="/images/architecture.png"
title="Architecture de déploiement"
caption="Schéma simplifié du pipeline CI/CD" */>}}

Hugo utilise le système de templates Go pour le rendu HTML. Pour la documentation, on personnalise rarement les templates de base (le thème Relearn s'en charge), mais il est utile de comprendre le mécanisme pour les ajustements.

Hugo cherche les templates dans cet ordre :

  1. layouts/ (projet), prioritaire
  2. themes/hugo-theme-relearn/layouts/, fallback

Un fichier dans layouts/ écrase automatiquement celui du thème. Pour personnaliser un template, copiez-le du thème dans layouts/ et modifiez-le.

Exemple de partial : date de dernière modification

Section intitulée « Exemple de partial : date de dernière modification »

Ce partial n'affiche rien tant que enableGitInfo est désactivé : le test if .GitInfo protège le rendu, car la variable est vide quand Hugo n'a pas accès à l'historique. En CI, cela impose un clone complet du dépôt.

layouts/partials/last-modified.html
{{ if .GitInfo }}
<p class="text-muted">
Dernière modification :
{{ .GitInfo.AuthorDate.Format "02/01/2006" }}
par {{ .GitInfo.AuthorName }}
</p>
{{ end }}

Activez les informations Git dans la configuration :

enableGitInfo = true

Cette fonctionnalité est précieuse pour la documentation DevOps : chaque page affiche automatiquement la date et l'auteur de la dernière modification depuis l'historique Git. Relearn affiche d'ailleurs ces informations nativement quand enableGitInfo = true.

Relearn génère automatiquement ce lien grâce au paramètre editURL dans hugo.toml. La variable ${FilePath} est remplacée par le chemin du fichier source :

editURL = 'https://github.com/mon-org/docs/edit/main/content/${FilePath}'

C'est le mécanisme qui transforme une doc statique en doc collaborative : chaque lecteur peut proposer une correction via pull request, sans avoir à chercher le fichier source manuellement.

Hugo propose deux modes qui ne produisent pas le même site : un serveur de développement qui garde les pages en mémoire et recharge le navigateur à chaque sauvegarde, et un build de production qui écrit des fichiers sur disque. Les brouillons, la minification et l'environnement diffèrent entre les deux, d'où les mauvaises surprises au premier déploiement.

Le serveur ne crée aucun fichier dans public/ : tout reste en mémoire, ce qui explique sa rapidité.

Fenêtre de terminal
hugo server -D

Le serveur démarre sur http://localhost:1313 avec le live reload activé. Le -D inclut les brouillons (pages avec draft = true).

Options utiles :

OptionEffet
-D / --buildDraftsInclure les brouillons
-E / --buildExpiredInclure le contenu expiré
-F / --buildFutureInclure le contenu avec une date future
-p 1314Changer le port
--disableFastRenderForcer le rebuild complet (utile si le cache pose problème)
--navigateToChangedRediriger le navigateur vers la page modifiée

Cette commande écrit le site dans public/ sans vider le dossier au préalable : un fichier supprimé du contenu peut donc y survivre d'un build à l'autre. Les brouillons sont exclus par défaut, contrairement au serveur lancé avec -D.

Fenêtre de terminal
hugo --gc --minify
# Start building sites …
# hugo v0.164.0-ce2470e7+extended linux/amd64
#
# │ EN
# ──────────────────┼────
# Pages │ 9
# Paginator pages │ 0
# Non-page files │ 0
# Static files │ 0
# Processed images │ 0
# Aliases │ 0
# Cleaned │ 0
#
# Total in 85 ms

Le tableau récapitule ce qui a été produit. La ligne Pages compte les pages HTML générées, y compris celles que Hugo crée seul (listes de sections, pages de taxonomies) : un site d'une seule page d'accueil en produit déjà neuf. La ligne Cleaned ne bouge qu'avec --cleanDestinationDir, elle reste à zéro ici.

OptionEffet
--gcGarbage collection : supprime les fichiers cache inutilisés
--minifyMinifie HTML, CSS, JS, JSON, SVG, XML
--baseURLÉcrase le baseURL de la configuration
-d public_htmlChange le dossier de sortie
--enableGitInfoAjoute les infos Git aux pages

Vérification : après le build, le dossier public/ contient le site complet. Vérifiez avec du -sh public/ que la taille est raisonnable.

Sur Hugo 0.164.0, un build avec Relearn affiche quatre lignes WARN avant le tableau. Elles surprennent, mais le build réussit et le site est correct :

WARN deprecated: .Language.LanguageCode was deprecated in Hugo v0.158.0 ...
WARN deprecated: .Language.LanguageDirection was deprecated in Hugo v0.158.0 ...
WARN deprecated: .Site.Sites and .Page.Sites was deprecated in Hugo v0.156.0 ...
WARN deprecated: .Site.Languages was deprecated in Hugo v0.156.0 ...

Ces avertissements ne viennent pas de votre configuration mais des templates du thème : Hugo a renommé plusieurs variables de langue entre les versions 0.156.0 et 0.158.0, et Relearn utilise encore les anciens noms dans layouts/partials/opengraph.html et le sélecteur de langue. Vérifié sur la release 9.0.3 du thème, la plus récente : les quatre lignes sont toujours là.

Vous n'avez donc rien à corriger de votre côté, et surtout rien à modifier dans themes/ : vos changements seraient écrasés à la prochaine mise à jour du sous-module. Attendez une release du thème. Si ce bruit gêne la lecture des journaux de CI, hugo --gc --minify --logLevel error ne conserve que les vraies erreurs, au prix de la visibilité sur les futures dépréciations.

Le résultat d'un build Hugo est un dossier de fichiers statiques : n'importe quel hébergeur capable de servir du HTML fait l'affaire. Les trois cibles ci-dessous couvrent l'essentiel des besoins d'une équipe, et toutes trois partagent la même exigence : récupérer le sous-module du thème et forcer le bon baseURL au moment du build.

Le workflow ci-dessous se découpe en deux jobs : le premier construit le site et publie l'artefact, le second le déploie. Cette séparation permet de confiner les droits d'écriture au seul job de déploiement.

Créez le fichier .github/workflows/hugo.yml :

.github/workflows/hugo.yml
name: Déployer la documentation Hugo
on:
push:
branches:
- main
permissions: {}
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
pages: read
env:
HUGO_VERSION: '0.164.0'
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
fetch-depth: 0
persist-credentials: false
- name: Installer Hugo
run: |
base="https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}"
curl -fsSLO "${base}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
curl -fsSLO "${base}/hugo_${HUGO_VERSION}_checksums.txt"
sha256sum --check --ignore-missing "hugo_${HUGO_VERSION}_checksums.txt"
tar xzf "hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz" hugo
sudo install -o root -g root -m 0755 hugo /usr/local/bin/hugo
- name: Configurer GitHub Pages
id: pages
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
- name: Build
env:
BASE_URL: ${{ steps.pages.outputs.base_url }}
run: hugo --gc --minify --baseURL "${BASE_URL}/"
- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
with:
path: ./public
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5

Vérification : activez GitHub Pages dans Settings > Pages avec la source "GitHub Actions".

GitLab déclenche la publication sur la seule présence d'un job nommé pages qui expose un artefact. L'image hugomods/hugo évite d'installer Hugo à chaque exécution, et GIT_SUBMODULE_STRATEGY: recursive ramène le thème, sans quoi le build échoue sur un thème introuvable.

.gitlab-ci.yml
image: hugomods/hugo:dart-sass-0.164.0@sha256:327eee888514c5c13f195aaeaed2d4b4982d139803502e2a599bc4f135db14cb
variables:
GIT_SUBMODULE_STRATEGY: recursive
pages:
stage: deploy
script:
- hugo --gc --minify
artifacts:
paths:
- public
only:
- main

GitLab Pages attend un dossier public/, qui est exactement le dossier de sortie par défaut de Hugo. Pas de renommage nécessaire (contrairement à MkDocs).

Hugo est nativement supporté par Netlify. Il suffit de créer un fichier de configuration :

netlify.toml
[build]
command = "hugo --gc --minify"
publish = "public"
[build.environment]
HUGO_VERSION = "0.164.0"

Les trois mécanismes qui suivent ne servent pas à tous les projets, mais chacun résout un problème que les autres générateurs traitent par extension : traduire un site, partager du contenu entre plusieurs dépôts, et produire des images dérivées pendant le build.

Hugo gère nativement le multilingue sans plugin. Chaque langue déclarée produit son propre jeu d'URL, et weight fixe l'ordre dans le sélecteur de langue affiché par le thème.

hugo.toml (extrait)
defaultContentLanguage = 'fr'
[languages]
[languages.fr]
languageName = 'Français'
weight = 1
[languages.en]
languageName = 'English'
weight = 2

Le contenu est organisé par suffixe de langue : installer-docker.fr.md et installer-docker.en.md, ou dans des dossiers séparés.

Les modules Hugo permettent de partager des composants (thèmes, layouts, contenu) entre projets, comme des dépendances Go :

Fenêtre de terminal
hugo mod init github.com/mon-org/mon-site
hugo.toml
[module]
[[module.imports]]
path = 'github.com/McShelby/hugo-theme-relearn'

Hugo extended peut redimensionner, recadrer, convertir et optimiser les images à la volée dans les templates :

Dans un template
{{ $image := resources.Get "images/architecture.png" }}
{{ $resized := $image.Resize "800x webp" }}
<img src="{{ $resized.RelPermalink }}" alt="Architecture">

L'image est traitée pendant le build et le résultat est mis en cache dans resources/_gen/. Relearn ajoute en plus un lightbox automatique (zoom au clic) sur toutes les images quand lightbox = true est activé dans [params.imageEffects].

Deux erreurs reviennent systématiquement sur les projets Hugo, et toutes deux se manifestent au pire moment : après la mise en ligne. La première touche l'URL de base, la seconde l'écart entre ce que vous voyez en local et ce que la CI publie.

Le baseURL dans hugo.toml est utilisé pour générer les URL canoniques, les flux RSS, les sitemaps et les chemins absolus des images. Si vous le définissez mal, le site fonctionne en local mais casse en production :

  • Images manquantes : les chemins absolus pointent vers le mauvais domaine
  • RSS invalide : les liens dans le flux renvoient vers localhost
  • SEO dégradé : les balises canoniques sont incorrectes

Règle : utilisez toujours --baseURL dans votre pipeline CI/CD pour écraser la valeur du fichier de configuration. Cela évite de versionner un baseURL de production dans le code.

La ligne la plus coûteuse de ce tableau est la première : une page oubliée en draft = true s'affiche parfaitement en local avec -D, puis disparaît du site publié sans qu'aucune erreur ne soit remontée.

Aspecthugo serverhugo --gc --minify
BrouillonsInclus avec -DExclus par défaut
MinificationNonOui
Environnementdevelopmentproduction
Comportement CSS/JSCertains thèmes chargent des assets de debugAssets optimisés
LiveReloadActivéNon applicable

Testez toujours un hugo --gc --minify localement avant de pousser pour vérifier que le rendu production correspond à vos attentes.

Les pannes Hugo se répartissent en trois familles : une édition manquante (standard au lieu d'extended), un thème absent parce que le sous-module n'a pas été récupéré, et un cache du serveur de développement qui masque vos modifications. Le tableau ci-dessous donne la commande de sortie pour chacune.

SymptômeCause probableSolution
command not found: hugoHugo pas dans le PATHVérifier avec which hugo ou réinstaller
TOCSS: ... this feature is not availableVersion standard au lieu de extendedInstaller hugo_extended_*
Les modifications ne s'affichent pasCache du serveur de développementhugo server --disableFastRender
Error: module "xxx" not foundThème non installégit submodule update --init --recursive
Build lentTraitement d'images non cachéVérifier que resources/_gen/ n'est pas dans .gitignore
Raw HTML omittedGoldmark bloque le HTML brutCréer un shortcode au lieu d'utiliser du HTML dans le Markdown
Pages non affichéesFront matter draft = truePasser -D au serveur ou mettre draft = false
Images cassées en productionbaseURL incorrectVérifier baseURL ou utiliser --baseURL en CI
Notices affichent du HTML brutMauvais délimiteur sur cardsUtiliser {{</* */>}} pour cards/card, {{%/* */%}} pour notice/tab
Recherche ne fonctionne pasFormat de sortie manquantVérifier [outputs] dans hugo.toml

Pour les équipes qui connaissent Material for MkDocs et veulent migrer ou comparer, voici la traduction directe des constructions les plus utilisées. Les blocs de code et les diagrammes Mermaid s'écrivent à l'identique : l'essentiel de la migration porte sur les admonitions, les onglets et les grilles.

Fonctionnalité MaterialÉquivalent Relearn
!!! note "Titre"{{% notice note "Titre" %}}
??? tip "Dépliable"{{% notice style="tip" title="..." expanded="false" %}}
=== "Onglet"{{< tabs >}} {{% tab title="..." %}}
```python title="..."```python {title="..."}
```mermaid```mermaid (identique)
> [!NOTE]> [!NOTE] (identique depuis Relearn 7.x)
Grilles <div class="grid cards">{{< cards >}} {{< card >}}
:material-icon: emojis{{% icon "fa-fw fas fa-icon" %}}
{== surligné ==}==surligné== (Goldmark extras.mark)
Recherche intégréeRecherche Lunr intégrée
Mode sombre palettethemeVariant = ['auto', ...]
glightbox (lightbox)lightbox = true dans [params.imageEffects]
Plugin git-revision-dateenableGitInfo = true (natif Hugo)
mkdocs gh-deployGitHub Actions workflow
  • Hugo est un des générateurs de site statique les plus rapides : un seul binaire Go, pas de dépendance runtime, build en millisecondes.
  • La version extended est recommandée pour le support Sass/SCSS et le traitement d'images avancé (WebP, resize). Le thème Relearn en tire parti.
  • Le thème Relearn est l'équivalent de Material for MkDocs : notices (admonitions), onglets synchronisés, Mermaid, recherche Lunr, mode sombre, badges, cartes en grille, arborescence, accordéons, formules MathJax, impression et lien "modifier cette page".
  • La configuration est centralisée dans hugo.toml (TOML, YAML ou JSON). Le baseURL est le paramètre le plus critique en production.
  • Gardez unsafe = false dans Goldmark et utilisez des shortcodes pour tout contenu HTML riche (sécurité XSS).
  • Organisez le contenu par type (guides, runbooks, reference, adr) avec un _index.md (archétype chapter) dans chaque dossier.
  • Commencez par les git submodules pour les thèmes. Passez aux Hugo Modules quand vous avez besoin de partager des layouts entre projets.
  • Le déploiement CI/CD sur GitHub Pages (avec actions/configure-pages), GitLab Pages ou Netlify tient en quelques lignes.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn