Comment j'ai créé ce site - partie 1
Par JF Poilprêt
Introduction
Ce billet fait partie d’un triptyque décrivant mon expérience avec Hugo pour créer ce site web:
- Partie 1: Fondamentaux et Pratique
- Partie 2: Configuration Avancée et Améliorations
- Partie 3: Déploiement
Pourquoi écrire un billet sur la mise en place de ce blog?
Probablement parce que:
- cela n’était pas ma première tentative de créer un blog, mais les précédentes avaient échoué
- Je voulais “apprendre quelque chose de nouveau” et après quelques mois, je ressens le besoin de partager ce que j’ai appris, en espérant pouvoir être utile à d’autres, désireux de faire de même
Cette série explique:
- pourquoi j’ai choisi Hugo pour mon blog
- comment je l’ai mis en place de zéro
- comment j’ai appris à configurer, utiliser Hugo, ses modèles et ses idiomes, pas à pas
- ce que j’ai dû faire (CSS, usage de Tachyons) pour améliorer le look de ce site selon mes désirs
- comment j’ai configuré mon VPS ("Virtual Private Server" ou Serveur Virtuel Privé) comme serveur de mon blog avec nginx
- ce qui reste encore à venir en ce qui concerne la construction et l’amélioration de ce site
Brève Historique de mon Blog
J’avais commencé à écrire un blog il y a plus de 2 ans, au dernier trimestre 2022:
- je voulais écrire à propos de randonnées (pratique que j’avais découverte un peu plus tôt cette année)
- j’avais besoin d’“amortir” le VPS que je louais depuis quelques années déjà
- Je voulais un endroit où poster mon CV
Aussi, je voulais:
- un système léger: pas de base de donnée, pas de CMS (“Content Management System”, Système de Gestion de Contenu) sur étagère
- une manière simple de créer des nouvelles pages, en particulier des billets de blog
- je voulais “apprendre quelque chose de nouveau”
Fin 2022, j’avais opté pour un “Générateur de Site Statique”, il en existait déjà pléthore sur le marché Open Source; cependant, à ce moment, j’ai utilisé de mauvais critères de sélection pour cet outil:
- En quel langage de programmation il était implémenté
- En combien de temps peut-on créer son premier site (simple) avec
Mais j’avais mis de côté plusieurs critères importants comme:
- simplicité d’utilisation
- facilité d’internationalisation
- documentation (tutoriels, références, complétude)
- thèmes disponibles
- étendue des possibilités de personnalisation
- communauté
À cause de cela, j’avais sélectionné Pelican pour l’unique raison qu’il est développé en Python, et que Python fait partie de mes langages de programmation préférés!
Après plusieurs semaines passées, j’avais pu publié quelques pages sur mon VPS mais:
- le site était laid (et difficile à personnaliser au niveau du style, des couleurs, de la mise en page)
- la personnalisation n’était pas aussi simple que j’avais espéré
- créer des billets n’était pas aussi évident que je le souhaitais
J’ai conservé ce site tel quel pendant 2 ans, jusqu’au jour où j’ai décidé, cet été, qu’il était temps de le “ressusciter”, tel un phœnix qui renaît de ses cendres.
Mais d’abord, je devais sélectionner un nouvel outil, selon les bons critères cette fois-ci!
Pourquoi Hugo
En m’appuyant sur mes nouveaux critères (énumérés ci-dessus), j’ai fait une nouvelle revue des “meilleurs générateurs de sites statiques de 2024”, et j’ai rapidement retenu Hugo dans la liste de candidats, car:
- il est bien documenté
- il a beaucoup de fonctionnalités, y compris le support intégré de l’internationalisation
- il existe un paquet de tutoriels sur presque toutes les fonctionnalités (y compris avancées)
- il y a beaucoup de thèmes variés de divers types, certains avec un joli style
- il semble offrir beaucoup d’options de personnalisation (mais les thèmes eux-mêmes doivent avoir été conçus pour être personnalisables)
- il a une large communauté (forums, Stack Overflow, blogs…)
La sélection de Hugo a été faite en même temps que le choix du meilleur thème pour mon blog. J’ai choisi Ananke parce que:
- il a un style cool et beau
- il semble facile à utiliser et personnaliser
Parmi la liste des thèmes disponibles, il y en a aussi quelques-uns permettant de publier son CV, j’ai choisi Almeida CV qui a un bon format, supporte également l’internationalisation, et fournit un bon niveau de personnalisation.
Il convient de noter que, le fait qu’Hugo est implémenté avec le langage de programmation Go, que je ne connais pas du tout, ne fut pas un problème bloquant (alors que ça l’avait été en 2022…)
Première Installation
Installer Hugo
Sur mon ordinateur personnel, j’utilise la distribution Linux Fedora (version 39 actuellement) avec l’environnement de bureau XFCE (que j’apprécie car il est plus léger que la plupart des bureaux “communs” tels que Gnome).
Les distributions Fedora utilisent le gestionnaire de paquets dnf
, lié à plusieurs dépôts officiels.
Au début, je voulais installer Hugo avec dnf
(ce que j’ai fait) mais je me suis aperçu que:
- la version disponible pour Fedora 39 était 0.111, alors que la toute dernière version officielle de Hugo à ce moment était déjà 0.128
- Hugo existe en deux paquets: “standard” et “étendu” (honnêtement, je trouve la différence entre les deux plutôt mal documentée), mais seul le paquet standard est disponible avec
dnf
Après quelques jours passés à travailler avec Hugo standard 0.111, il se trouve que:
- je suis tombé sur des bogues connus et déjà corrigés dans des versions plus récentes
- j’avais besoin de certaines fonctionnalités disponibles seulement dans le paquet étendu
Voilà pourquoi j’ai finalement installé le dernier paquet étendu de Hugo à ce moment.
Je l’ai directement installé (avec juste gunzip
et tar xvf
) dans mon répertoire privé puis j’ai créé un lien symbolique depuis /usr/local/bin
:
$ sudo ln -s /home/jfpoilpret/hugo/hugo /usr/local/bin/hugo
Depuis, il faut noter que j’ai effectué quelques mises à jour, et aujourd’hui j’utilise Hugo 0.135.0.
Création d’un nouveau site
Tout d’abord, j’ai créé un nouveau site dans un de mes sous-répertoires “~/webdev
”, pour cela j’ai suivi ce tutoriel (en anglais):
$ hugo new site hugoweb-blog
$ cd hugoweb-blog
$ git init
$ git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
$ echo "theme = 'ananke'" >> hugo.toml
$ hugo server -D &
Les commandes ci-dessus:
- créent un nouveau répertoire
hugoweb-blog
avec un “squelette” de site Hugo: structure complète de répertoires, fichier de configuration par défaut (hugo.toml
)… - installent le thème Ananke depuis github vers mon nouveau site Hugo
- lance un serveur local (pour visualiser “en direct” depuis un navigateur les effets de changements de configuration, l’ajout ou la modification de billets)
Pour en apprendre plus sur Hugo, j’ai également suivi ce tutoriel vidéo, très complet, juste un peu obsolète; c’était très utile de toute façon.
Enfin j’ai créé un dépôt privé sur github afin d’avoir un historique de mes travaux et une gestion de problèmes et de tâches pour la mise en place de mon site web.
Premières commandes Hugo
Hugo fournit un certain nombre de commandes à utiliser dans diverses situations. Lors de la création de billets il faut utiliser une des commandes suivantes:
hugo new content hiking/second-ride/index.md
: crée un nouveau billet de contenu, sous la catégoriehiking
, avec le nom (qu’on retrouve dans l’URL d’accès)second-ride
, sous la forme d’un “page bundle”, dont nous verrons la signification dans un instant.hugo new content hiking/second-ride.md
: fait la même chose, mais sans page bundle; au début, je n’utilisais que cette commande mais c’était une mauvaise idée, les page bundles sont préférables dans la plupart (sinon tous) des cas, parce que cela permet de placer les images liées au même endroit que le contenu du billet.
Comme vous l’avez peut-être noté grâce à l’extension .md
, Hugo vous permet d’utiliser Markdown pour écrire le contenu de billets (pas de code HTML, pas de langage compliqué à apprendre; en général, je trouve Markdown facile à apprendre, lire et écrire). Cela m’a permis d’être très efficace dans l’écriture de mes premiers billets de blog.
Hugo s’appuie sur l’implémentation CommonMark du “standard” Markdown.
Pour bien démarrer avec Markdown, voici quelques liens utiles (en anglais):
- Un aide-mémoire très basique
- Une référence basique plus complète de Markdown
- Un éditeur CommonMark en ligne avec visualisation directe du résultat
- La spécification complète de CommonMark
- Quelques extension Markdown utiles disponibles dans Hugo
Premier contenu
Il était enfin temps d’écrire mon premier billet! Ce fut un simple “À propos de moi”, en français (je rappelle que mon intention était de créer un site bilingue, avec des billets en français, en anglais ou les deux).
Avant cela, il me fallait définir où (dans quelle catégorie) le placer. J’ai décidé de créer une catégorie “home
” pout tous les contenus “généraux” de mon site web, typiquement la page “À propos” et aussi les mentions légales.
Dans Hugo, vous créez un sous-répertoire de content/
pour chaque catégorie de votre site, puis vous ajoutez des billets à une catégorie donnée.
J’ai donc créé le billet “À propos de moi”, en utilisant la 1ère des 2 commandes hugo new content...
mentionnées ci-dessus:
$ hugo new content home/about/index.fr.md
Cette commande a créé:
- le répertoire
content/home/about
- le fichier
index.fr.md
dans le nouveau répertoire
Notez le “fr
” just avant l’extension “.md
”: cela indique à Hugo que le contenu est en français, cela autorise plusieurs langues pour le même billet. Plus de détail sur l’internationalisation un peu plus loin dans ce billet.
Hugo génère le fichier pour ce billet avec un peu de “contenu” au début (appelé “front matter”) qui constitue en fait des métadonnées pour ce billet:
---
title: "About"
date: 2024-07-09T13:55:23+02:00
tags: []
featured_image: ""
description: ""
---
Cette section, délimitée par les lignes ---
, utilise YAML pour définir les métadonnées de votre contenu. Le véritable contenu doit être ajouté après cette section.
title
: ceci sera utilisé à plusieurs endroits de votre blog; le titre généré par défaut utilise le nom du répertoire (about
dans cet exemple), capitalisé; vous pouvez le changer pour un meilleur titre.date
: la date de création, initialisée à la date courantetags
: une liste vide d’étiquettes que vous pouvez modifier pour étiqueter votre billet afin de facilement le rechercherfeatured_image
: une chaîne vide que vous pouvez remplacer par le chemin d’une image qui sera utilisée à plusieurs endroits de votre blogdescription
: une chaîne vide que vous pouvez remplacer, qui sera affichée dans l’entête de votre billet
Il existe d’autres métadonnées, et vous pouvez même y ajouter les vôtres si c’est nécessaire.
En particulier, il est bon de connaître les attributs suivants:
draft
: valeur logique (true
oufalse
) pour marquer le billet comme “brouillon”, c’est-à-dire qu’il ne sera pas publié au moment de déployer votre site avec Hugo; cependant, il est possible de le voir avec le serveur local Hugo si vous ajoutez l’argument--buildDrafts
(ou-D
). Un bon principe de base consiste à toujours ajouterdraft: true
pour chaque nouveau billet et changer àfalse
lorsque que vous estimez qu’il est “prêt pour le grand jour”.publishDate
: cette page ne sera pas publiée avant cette date lorsque le site est déployé avec Hugo; cependant, il est possible de la voir avec le serveur local Hugo si vous ajoutez l’argument--buildFuture
(ou-F
).categories
: liste des catégories auxquelles le billet appartient
Vous devriez immédiatement remplir cette section:
---
title: "À propos de moi"
date: 2024-07-09T13:55:23+02:00
categories: ["famille"]
tags: ["vie-privée"]
featured_image: "images/IMG_1846.JPG"
description: ""
draft: false
---
Remarquez la propriété “featured_image
”: elle contient le chemin relatif vers une image que j’ai placée dans “content/home/about/images
”; le chemin relatif commence à partir du répertoire racine du billet courant. Après plusieurs semaines à travailler avec Hugo, je trouve que c’est une bonne habitude de créer un répertoire “images/
” pour chaque billet (s’il contient des images bien sûr), et je m’y tiens autant que possible. Cette pratique s’appuie sur les “Page Bundles” que je décris un peu plus tard dans ce billet.
Maintenant vous pourriez vous demander: “d’où vient ce contenu initial dans mon nouveau billet?” La réponse se trouve dans le concept Hugo d’"archétypes" qui sont des modèles (templates) utilisés pour créer du nouveau contenu.
Typiquement, chaque thème fournit un (ou plusieurs) de ces archétypes, mais vous pouvez aussi ajouter les vôtres, selon vos besoins, par exemple si vous aller créer une série de billets qui vont tous avoir une structure similaire et des métadonnées spécifiques.
Finalement, le plus difficile arrive: écrire le contenu du premier billet! Heureusement, la page “À propos de moi” est assez courte car je ne voulais pas non plus “raconter ma vie” mais insister sur les quelques faits les plus importants.
Tout le contenu est écrit en Markdown qui ressemble à du texte avec quelques améliorations:
- entêtes (titres et sous-titres)
- listes à puces ou numérotées
- caractères italiques, gras, barrés…
- liens
- images
- …
Voici quelques exemples concrets de style avec Markdown dans du contenu:
Entêtes
Titre de 1er niveau
===================
Sous-titre (2e niveau)
----------------------
# Titre de 1er niveau
## Sous-titre (2e niveau)
### Sous-titre (3e niveau)
Listes
- liste à puces élément 1
- liste à puces élément 2
- liste à puces élément 3
1. liste numérotée élément 1
2. liste numérotée élément 2
3. liste numérotée élément 3
Styles de caractères
**italique**
*gras*
~~barré~~
Liens
[Nom du lien](URL du lien)
Images

Dans les liens et les images ci-dessus, “URL” peut en fait être un chemin relatif vers une ressource (autre billet ou image stockée localement) plutôt qu’une véritable URL Internet.
Petites améliorations de configuration
Après juste quelques jours à travailler avec Hugo, j’ai dû rapidement faire quelques améliorations au niveau de la configuration globale.
La configuration de votre site Hugo est stockée sur le répertoire racine de votre projet sous forme d’un fichier unique: “hugo.toml
”. Ce fichier peut avoir l’un des trois formats suivants:
- TOML: c’est le format par défaut lors de la création d’un nouveau site avec Hugo
- YAML: ce format est devenu assez répandu depuis quelques années
- JSON: format assez ancien, un peu trop verbeux selon moi
Je préfère naturellement YAML, dont j’ai l’habitude, que je trouve plus concis et lisible que les deux autres.
C’est pour cela que j’ai rapidement transformé “hugo.toml
” en “hugo.yaml
”:
Avant: hugo.toml
title = "JF Poilpret: mon blog"
baseURL = "https://www.poilpret.ch/"
languageCode = "fr-ch"
theme = "ananke"
Après: hugo.yaml
title: "JF Poilpret: mon blog"
baseURL: https://www.poilpret.ch/blog
languageCode: fr-ch
theme: ananke
Plus tard, j’ai encore ajouté quelques éléments de configuration à hugo.yaml
:
title: "JF Poilprêt: mon blog"
copyright: "JF Poilprêt"
baseURL: https://www.poilpret.ch/blog
languageCode: fr-ch
theme: ananke
defaultContentLanguage: fr
paginate: 6
enableRobotsTXT: true
enableEmoji: true
params:
author: JF Poilprêt
date_format: 2 January 2006
favicon: "images/jfpoilpret3.jpg"
recent_posts_number: 5
ananke_socials:
- name: rss
- name: mastodon
url: https://mamot.fr/@jfpoilpret
rel: me noopener
- name: github
url: https://github.com/jfpoilpret
- name: linkedin
url: https://www.linkedin.com/in/jean-fran%C3%A7ois-poilpret-b0245320/
- name: stackoverflow
url: https://stackexchange.com/users/15857/jfpoilpret
- name: facebook
follow: false
- name: twitter
follow: false
markup:
goldmark:
extensions:
extras:
delete:
enable: true
insert:
enable: true
mark:
enable: true
subscript:
enable: true
superscript:
enable: true
Certains de ces nouveau attributs sont:
- spécifiques au thème Ananke:
paginate
,recent_posts_number
,ananke_socials
- pour une configuration avancée de Hugo:
enableEmoji
: permet d’utiliser des emoji graphiques à l’intérieur du contenu en markdownmarkup.goldmark.extensions
: active des extensions Markdown spéciales que j’ai utilisées dans certains des billets réalisés plus tard
Aujourd’hui, vous pouvez trouver la toute dernière version de hugo.yaml
pour mon site ici.
Taxonomie & Structure de Site
Brève Introduction
Un point très important pour la création d’un site web avec Hugo (et avec n’importe quel outil en fait) est la définition d’une taxomomie, ainsi que la structure adéquate pour ce site, cette dernière dépendant de la taxonomie dans une certaine mesure.
Les taxonomies définissent les moyens de classifier du contenu. Par défaut, Hugo (et beaucoup de thèmes pour Hugo) supportent deux taxonomies très communes dans les blogs:
- catégories
- étiquettes (tags)
Pour chaque contenu (billet, page) de votre site, vous spécifiez les “termes” pour chaque taxonomie, dans sa section front-matter, comme dans les exemples exposés auparavant:
title: "À propos de moi"
categories: ["famille"]
tags: ["vie-privée"]
En outre, Hugo définit les “sections” qui sont aussi un moyen de classifier du contenu. Contrairement aux taxonomies, avec lesquelles un billet peut être classifié avec de multiples valeurs (un billet peut être classé dans plusieurs catégories et avoir plusieurs étiquettes), les sections imposent une structure en forme d’arbre, avec trois niveaux ou plus:
racine (pas vraiment une section)
section
[sous-section niveau 1]
[sous-section niveau 2]
...
billets (feuilles de l'arbre)
Les sections se reflètent à travers les sous-répertoires du répertoire “content/
” (le niveau racine). Les sous-sections, lorsque définies, sont simplement des sous-répertoires des répertoires de sections, on les appelle “sections imbriquées” (nested sections) selon le vocabulaire utilisé par Hugo.
Pour des raisons de simplicité, je conseille de suivre la règle “1 section = 1 catégorie”, car je ne vois pas de valeur ajoutée à faire autrement.
Généralement, les taxonomies pour votre site auront un impact sur:
- l’organisation (répertoires) de votre contenu
- les URL pour accéder au contenu spécifique du site déployé
- les URL pour accéder aux listes de contenus du site déployé (par taxonomie: liste des catégories et étiquettes, et billets pour chacune)
Je n’ai pas pris le temps de creuser plus en détails les fonctionnalités de Hugo concernant les taxonomies (beaucoup de configuration est possible), et j’ai juste utilisé la configuration par défaut.
Pour plus d’informations utiles sur les sections dans Hugo, je suggère la lecture (en anglais) du “Ultimate Guide to Hugo Sections” mais c’est d’un niveau assez avancé car il décrit notamment la personnalisation.
Conventions
L’important, quand on construit un nouveau site, c’est:
- d’avoir une vision claire des sections qu’on va utiliser
- d’avoir une vision claire des catégories utilisées; comme mentionné plus tôt, pour mon site, j’ai décidé qu’elles coïncideront aux sections et donc, reprendront les noms de sous-répertoires de
content/
, et tout le contenu pour une catégorie devra être placé en dessous. - d’avoir une bonne vision des étiquettes (toutefois, ce peut être raffiné au fur et à mesure de l’écriture de nouveaux contenus) afin de s’assurer de la cohérence des noms attribués et de l’utilisation pour tout le contenu relatif
En général, je suggère de définir des conventions “minimales” (pour les catégories et les étiquettes) et ne jamais y déroger:
- conventions de nommage: caractères utilisés, capitalisation, abréviations
- possibilité ou non d’utiliser plusieurs étiquettes avec la même signification
- conventions spécialisées par langue si cela fait sens
Pour mon blog j’utilise les conventions suivantes:
- pour les catégories
- lettres minuscules uniquement
- chiffres autorisés
- caractères accentués autorisés en français
- utilisation du trait d’union
-
pour isoler les mots (ex. “vie-privée”) - utiliser uniquement des noms, éventuellement avec des adjectifs; les verbes sont autorisés uniquement au participe présent (finissant par “-ant”) en français ou en “-ing” en anglais
- abréviations interdites, utiliser uniquement les termes complets
- pour les étiquettes
- lettres minuscules uniquement (même pour les noms de marques, comme “Hugo” qui devient “hugo”)
- chiffres autorisés (par exemple,“2024” pour les randonnées de 2024)
- caractères accentués autorisés en français (ex. “vie-privée”)
- utilisation du trait d’union
-
pour isoler les mots - utiliser uniquement des noms, éventuellement avec des adjectifs; les verbes sont autorisés uniquement au participe présent (finissant par “-ant”) en français ou en “-ing” en anglais
- éviter les abréviations, préférer les termes complets; les utiliser uniquement quand ça fait sens et qu’elles sont comprises par votre audience
- utiliser des étiquettes synonymes uniquement si cela apporte quelque chose et dans ce cas, les utiliser de manière uniforme, c’est-à-dire, si vous utilisez des synonymes “tag1” et “tag2”, alors tous les billets avec l’étiquette “tag1” doivent aussi avoir l’étiquette “tag2”, et réciproquement
Structure

Hiérarchie du répertoire de contenus de mon site Hugo
Dans le répertoire source de contenus du site, on peut voir un sous-répertoire (section) par catégorie:
- electronics,
- hiking,
- home,
- information-technology,
- life
À noter ici que les sections sont en anglais alors que les catégories elles-mêmes sont en anglais et/ou en français.
Sous chaque répertoire, on peut trouver:
- un répertoire de contenu pour chaque billet
- d’autres sous-répertoires (sous-sections) par exemple les années de randonnées
La structure de publication est similaire:

Hiérarchie du répertoire public de mon site
Le répertoire public/
est généré par Hugo et peut directement être publié vers un serveur Web. En plus des répertoires par catégorie (sections), il contient aussi:
- un répertoire
categories/
, listant toutes les catégories en français, et à l’intérieur de chaque, un fichierhtml
listant tous les billets dans cette catégorie - un répertoire
tags/
, listant toutes les étiquettes en français, et à l’intérieur de chaque, un fichierhtml
listant tous les billets avec cette étiquette - un répertoire
en/
, contient la même structure qu’à la racine, mais seulement pour le contenu en anglais
Concepts Hugo utiles liés
Avec Hugo, chaque section peut avoir une sorte de page d’entête, par exemple pour introduire le type de contenu trouvé dans cette section.
Pour ce faire, il suffit d’ajouter un fichier “_index.md
” (et “_index.en.md
” si c’est une section multilingue) directement dans le répertoire de la section.
Ce fichier Markdown vous permet de:
- définir des métadonnées par défaut (grâce à sa partie front matter) pour tout le contenu dans cette section, grâce à l’attribut “
cascade
” - ajouter du contenu (en Markdown) d’introduction de la section
Par exemple, pour la section “hiking” (randonnée), j’ai un “_index.md
” avec le front matter suivant:
front matter
---
title: "Randonnées"
date: 2024-07-18T12:00:00-05:00
cascade:
featured_image: "background-haut-de-caux.jpg"
---
Ici on voit que, pour tout billet sans “featured_image
” définie, l’image par défaut sera utilisée.
contenu markdown
Je décris ici la plupart des randonnées que j'ai effectuées depuis 2022.
Chaque billet contient un synopsis résumant les caractéristiques de
la randonnée.
Les niveaux de difficulté et la durée sont prises pour des
"randonneurs moyens" comme moi (pas chevronnés).
Pour un résumé, année par année, des randonnées que j'ai effectuées,
allez voir [ici](/hiking/all-hikes).
Il s’agit de Markdown tout-à-fait standard, qui sera transformé par Hugo pour générer une “page d’accueil” propre à la section, incluant le contenu ci-dessus, ainsi que la liste des billets (résumés) dans cette section.
Un aspect utile des sections dans Hugo est la possibilité de définir des sections “headless” (sans affichage). C’est utile lorsque, par exemple, vous avez du contenu, sans page d’accueil nécessaire, que vous voulez juste lier depuis d’autres parties de votre site.
Dans ma situation, j’ai créé une section headless “home
”, qui contient le contenu suivant (en français et anglais):
- à propos
- mentions légales du site
La page “à propos” est directement accessible depuis la page d’accueil de mon blog, alors que les “mentions légales” sont liées depuis le pied de page de toutes les pages de mon blog.
Rendre une section headless se fait via le front matter de son “_index.md
”:
---
title: "Home"
date: 2024-07-18T12:00:00-05:00
headless: true
---
Ressources & Page Bundles
Lorsqu’on crée des billets avec Hugo, il existe plusieurs options pour placer du contenu relatif, comme des images ou des documents, affichés ou liés depuis le billet:
- les placer dans le répertoire “
static/
” ou un de ses sous-répertoires - les placer à côté du fichier Markdown du billet lui-même, cela s’appelle “Page Bundles”
Après avoir écrit plusieurs billets, avec chacun un grand nombre d’images associées, vous trouverez que l’approche “static/” n’est pas vraiment satisfaisante.
Rapidement, j’ai donc opté pour l’approche “Page Bundle” parce qu’elle me permet de rassembler tout le contenu d’un billet à un seul endroit, ce qui est juste du bon sens!
Cette approche vous devez utiliser la ligne de commande suivante pour créer un nouveau billet: hugo new content hiking/second-ride/index.md
ce qui crée un répertoire pour votre billet, que vous utiliserez alors comme lieu de stockage de votre page bundle.
Cela étant dit, je n’aime pas trop mélanger fichiers markdown d’un billet (avec l’extension .md
) avec tous les documents et images, c’est pour cela que je crée des sous-répertoires pour chaque page bundle, par exemple:

Page Bundle d'un billet de randonnée
Il est également possible de placer des ressources communes en dehors de page bundles, par exemple dans la copie d’écran ci-dessus, il y a un répertoire “gpx/
” directement dans la section “hiking
”: j’y pose les fichiers GPX de toutes mes randonnées. Chaque GPX peut être référencé depuis deux billets:
- le billet de cette randonnée en question (qui n’existe pas nécessairement pour toutes les randonnées que j’ai faites)
- le billet énumérant le résumé succinct de toutes les randonnées que j’ai faites
Finalement, si vous avez des ressources (typiquement des images) qui sont vraiment communes à tout votre site, vous pouvez les placer dans le répertoire “static/”.

Contenu du répertoire 'static'
Ici j’utilise “static/
” pour:
- des images de drapeaux, utilisées pour choisir la langue d’affichage (visibles dans toutes les pages de mon blog)
- ma photo personnelle en guise de favicon
Internationalisation
J’ai créé mon site Web en ayant à l’esprit l’objectif qu’il soit multilingue, je voulais:
- créer des billets à la fois en français et en anglais
- créer des billets en français uniquement
- créer des billets en anglais uniquement
Le support multilingue fut l’une des raisons pour lesquelles j’ai choisi Hugo en premier: ce support est “pensé” et intégré dans Hugo (ce n’est pas un ajout bancal de dernière minute) et il avait l’air simple à utiliser. Aussi, la plupart des thèmes disponibles pour Hugo intégrait également ce support multilingue, y compris avec des traductions de tous les termes utilisés, pour de multiples langues.
L’activation du mode multilingue d’un site créé avec Hugo commence par la configuration:
languageCode: fr-ch
defaultContentLanguage: fr
languages:
fr:
languageName: Français
title: "JF Poilprêt: mon blog"
en:
languageName: English
title: "JF Poilprêt: my blog"
Voici une brève explication de chaque attribut:
languageCode
: cela est utilisé pour la génération RSS et pour le tag<html lang="xxx">
dans le HTML générédefaultContentLanguage
: la langue par défaut du site Weblanguages
: la liste des langues (code officiel sur 2 lettres) supportées par le site Web; chaque langue contient alors une liste de propriétés spécifiques:languageName
: le nom complet de la langue, utilisé dans le menu de sélection de la languetitle
: le titre du site dans cette languecontentDir
(pas montré): voir ci-aprèsparams
(pas montré): permet de définir ses propres paramètres, avec des valeurs spécifiques à chaque langue, pour les utiliser dans des Templates Hugo; les templates (“modèles”) seront décrits dans le prochain billet.
Hugo fournit 2 manières de définir du contenu multilingue:
- traduction par répertoire: ici on définit un répertoire racine par langue supportée, comme
content/fr/
etcontent/en/
si on veut supporter le français et l’anglais; cela implique que l’on peut définir des organisations (structures) de contenu totalement différentes d’une langue à l’autre, un peu comme si on avait deux sites Web indépendants (bien que Hugo sera normalement capable de “lier” les billets écrits en 2 langues). - traduction par nom de fichier (je préfère cette manière): ici on a une seule structure de contenu pour tout le site, la langue d’une page est déterminée par le nom des fichiers de contenu (
.md
ou autres fichiers de ressources); par exemple, un billet en anglais pourrait êtremy-post.en.md
, alors que le même billet en français seraitmy-post.fr.md
; l’avantage est que tout le contenu pour un même billet, quelle que soit la langue, se trouve au même endroit, ce qui fait sens pour moi. À noter que, pour du contenu dans la langue par défaut, on peut omettre la langue dans le nom du fichier, par exemplemy-post.md
est équivalent àmy-post.fr.md
sifr
est la langue par défaut du site.
La sélection de la manière utilisée est déterminée par l’existence de l’attribut contentDir
dans la configuration.
En ce qui concerne la structure du site généré par, Hugo va:
- générer des sous-répertoires pour chaque langue supportée
- pour toutes les langues sauf celle par défaut, générer la structure du site avec tout le contenu pour cette langue
- pour la langue par défaut, générer
index.html
dans le répertoire correspondant à cette langue, redirigeant simplement vers le l’URL racine - à la racine, générer la structure du site avec tout le contenu pour la langue par défaut

Site Hugo public avec sous-répertoires par langues
Optionnellement, on peut aussi demander à Hugo de générer, pour toutes les langues y compris celle par défaut, des sous-répertoires avec toute la structure du site. Pour ce faire, il faut activer l’option defaultContentLanguageInSubdir
. Bien que cela apporte un certain équilibre au site publié, je préfère conserver la valeur false
par défaut, mais ne me demandez pas pourquoi!
Mise en garde: si vous publiez un billet dans n’importe quelle langue sauf celle par défaut, alors les ressources du page bundle doivent aussi inclure le suffixe de langue, comme mypicture.en.jpg
sinon ces ressources ne seront pas publiées!
Jusqu’à présent, nous avons vu comment traduire du contenu, mais il est également utile de savoir comment les thèmes pour Hugo gèrent leurs propres traductions dans leurs modèles.
Tout le texte utilisé par un thème est normalement placé dans des fichiers (un par langue supportée par le thème) dans le répertoire i18n/
du thème:

Fichiers de traduction du thème Ananke
Voici un extrait de en.toml
pour le thème Ananke:
[more]
other = "More"
[allTitle]
other = "All {{.Title }}"
[recentTitle]
other = "Recent {{.Title }}"
[readMore]
other = "read more"
Il est possible de surcharger (modifier) n’importe laquelle de ces entrées (ou même ajouter une nouvelle langue non supportée par le thème), en ajoutant simplement un tel fichier dans le répertoire i18n de votre projet Hugo (pas celui du thème):

Fichiers surchargeant les traductions
Voici un extrait de fr.toml
pour mon site Web:
[builtWithHugo]
other = 'Ce site a été construit avec'
[builtWithAnanke]
other = 'et utilise le thème'
[lastModified]
other = 'Modifié le '
[pageTitle]
other = "Page {{ .Name }}"
Dans cet exemple, j’ai:
- modifié la traduction française de
pageTitle
car l’originale du thème Ananke ne me convenait pas - ajouté de nouveaux libellés, pas utilisés par Ananke, mais utilisés par mes propres modèles de mise en page, ce que je détaillerai dans le prochain billet
Prochains billets
Nous voici arrivés à la fin de ce premier billet sur l’utilisation de Hugo pour construire mon site Web.
Dans le prochain billet “Configuration Avancée et Améliorations”:
- je montrerai comment modifier la manière dont Hugo génère le code HTML des images se trouvant dans les fichiers Markdown
- je décrirai comment comprimer les images avec Hugo afin d’optimiser les temps de chargements de pages
- je démontrerai comment définir du “short code” (“code court”) pour des besoins spécifiques
- j’expliquerai comment modifier et améliorer la mise en page produite par le thème Ananke
- je donnerai quelques trucs et astuces que j’ai collectés pendant mon apprentissage de Hugo
- j’indiquerai les futures tâches d’améliorations prévues pour mon site
Le 3e et dernier billet “Déploiement” couvrira:
- la problématique de l’usage de thèmes multiples et la solution que j’ai mise en place
- la configuration d’un serveur Web pour héberger mon site
- les scripts de déploiement que j’ai écrits pour simplifier les tâches de mise à jour