Aller au contenu
← Tous les articles
Article

Créer un portfolio avec Hugo (semaine 1)

Écouter en version balado

Semaine 1 d'un portfolio Hugo · 2:10 · voix synthétiques, script rédigé avec l’IA

Transcription

Sylvie : Quatre chaînes d'outils, et une seule se déployait toute seule. Voilà l'état de l'ancien dépôt d'Antoine juste avant son passage à Hugo, en janvier 2024.

Thierry : Quatre ? Pour un site personnel ?

Sylvie : Oui. Un CV web construit avec npm, un CV PDF en LaTeX, une page de liens en Hugo, et un blogue dans un sous-module git. Seul le CV web avait un workflow GitHub Actions. Le dernier commit, une semaine avant le billet, supprimait l'ancien dossier du site.

Thierry : Donc la semaine 1, c'était une page blanche.

Sylvie : Exactement. Il a choisi Hugo parce que c'est statique : hébergement peu coûteux, pas de base de données à corriger. Et les articles sont en Markdown dans git, donc le dépôt est la source de vérité. Une interface d'admin à la WordPress, dit-il, il l'aurait ignorée dès la deuxième semaine.

Thierry : Qu'est-ce que cette première page de liens lui a appris ?

Sylvie : Plusieurs choses. Il avait copié le thème Lynx dans le site au lieu de l'importer comme module, et l'échafaudage de démo a suivi, avec des fichiers qui pointaient vers un dossier inexistant.

Thierry : Aïe. Rien de plus vicieux ?

Sylvie : Le Docker lançait le serveur de développement de Hugo, pas un build statique. Et le fichier Compose montait le projet dans un répertoire alors que l'image avait copié le site dans un autre : ses modifications n'atteignaient jamais le conteneur.

Thierry : Le grand classique. Et le thème qu'il a retenu ?

Sylvie : HBTheme. Il apportait les commentaires et les modules Hugo, donc pas de gabarits à refaire de zéro. Le compromis, c'est une structure imposée, qui coince quand on veut des types de contenu sur mesure.

Thierry : Et Substack, dans tout ça ?

Sylvie : En parallèle, pour les textes longs et l'envoi par courriel. Hugo reste la maison professionnelle de référence.

Thierry : Alors, qu'est-ce qu'il referait autrement ?

Sylvie : Importer les thèmes comme modules, construire du HTML statique en CI pour chaque pièce, et garder les fichiers de traduction complets. L'article complet détaille tout ça, avec le shortcode iframe.

Aperçu du site après premier déploiement
Table des matières

Semaine 1 de la migration de mon site vers Hugo (janvier 2024) : choisir un thème, livrer vite et prouver que le dépôt pouvait porter plus qu’un CV en PDF. Ce billet est le journal : d’où je partais, HBTheme, l’intégration d’une étude de données, Substack en parallèle et un shortcode iframe réutilisable.

1. Pourquoi Hugo et pas un CMS

ChoixRaison
Génération statiqueHébergement peu coûteux, builds rapides, aucune base de données à corriger
Source en MarkdownArticles et projets versionnés dans git, avec des diffs relisibles
ModulesRécupérer thème et partials sans tout copier dans le dépôt

En tant qu’ingénieur, je voulais le dépôt comme source de vérité : Markdown en entrée, HTML en sortie, déploiement sur GitHub Pages ou équivalent. Une interface d’administration à la WordPress, je l’aurais ignorée dès la deuxième semaine.

2. D’où je partais

Avant la semaine 1, le dépôt de mon ancien site était un ensemble de pièces séparées, chacune avec sa propre chaîne d’outils :

PièceConstructionMise en ligne
CV webresume.json (JSON Resume) exporté avec resume-cli et le thème elegant, plus une variante sombre avec kendallLe seul workflow GitHub Actions : à chaque push, npm ci, npm run build, copie de index.html dans dist/, publication avec JamesIves/github-pages-deploy-action. Un Dockerfile pouvait aussi le servir depuis nginx:alpine
CV PDFLaTeX sur la classe RussellPDF versionné à côté de la source, sans build en CI
Articles de rechercheDeux PDF dans un dossierFichiers statiques
Page de liensHugo, à partir du thème Lynx avec Tailwind CSSUn Dockerfile qui lançait hugo server, sans build en CI
BlogueUn sous-module git vers un thème Hugo tiers (blist)Le contenu du blogue n’était plus dans le dépôt

Le dernier commit, une semaine avant ce billet, supprimait l’ancien dossier du site. La semaine 1 est partie de ce terrain dégagé : quatre chaînes d’outils (npm, LaTeX, Hugo, Docker), et une seule déployait automatiquement.

3. La première pièce Hugo : une page de liens

La page de liens a été mon premier vrai site Hugo, et elle explique beaucoup des choix faits ensuite.

Mise en place du thème. J’avais copié le thème Lynx dans le site au lieu de l’utiliser comme thème : theme.toml, layouts/ et assets/ étaient à la racine. L’échafaudage du thème a suivi : un netlify.toml et une configuration Lighthouse CI pointaient tous les deux vers un dossier exampleSite qui n’existait pas dans ma copie. C’est la raison principale de la ligne Modules du tableau plus haut : je voulais que le thème suivant soit importé, pas collé.

Configuration. Tout ce qui s’affichait venait de config.toml : enableEmoji = true, disableKinds = ["taxonomy", "term"] (pas de pages d’étiquettes pour un site d’une page) et un bloc [module.hugoVersion] avec extended = false et min = "0.86.1". Les liens sont une liste de tables à une seule clé, et la clé sert deux fois :

[author]
  name = "Antoine Boucher"
  image = "profile.jpg"   # dans static/
  links = [
    { github = "https://github.com/<user>" },
    { linkedin = "https://linkedin.com/in/<user>" },
    { email = "mailto:<user>@example.com" },
  ]

Le gabarit d’accueil parcourt cette liste. La clé (github) choisit l’icône assets/icons/github.svg et le libellé link.github dans les fichiers i18n. Une valeur peut aussi être une table avec href, icon, text, target ou title pour remplacer les valeurs par défaut. L’avatar est redimensionné en 288×288 quand Hugo le trouve comme ressource.

Du CSS sans Hugo extended. Tailwind tourne depuis un script npm et écrit assets/css/compiled/main.css, qui est versionné. Hugo n’a qu’à regrouper des fichiers, donc le binaire standard (non extended) suffit. Le partial head enchaîne les étapes :

{{ $bundleCSS := $assets.Get "css" | resources.Concat "css/main.bundle.css" | resources.Minify | resources.Fingerprint "sha512" }}

L’empreinte fournit aussi un attribut integrity sur la balise <link>. Un assets/css/custom.css facultatif est ajouté au paquet quand il existe.

Structure du contenu et i18n. Ni articles ni sections : une page d’accueil, un gabarit single.html avec un lien de retour et deux fichiers de traduction (en.yaml, fr.yaml) pour les libellés des liens, le lien « Home » et le pied de page (« Powered by » / « Propulsé par »). C’était mon premier fichier Hugo bilingue, bien avant les articles bilingues.

Shortcodes. Deux petits. {{< icon "github" >}} insère un SVG de assets/icons/ dans le texte. {{< lead >}}…{{< /lead >}} met un paragraphe d’introduction en texte plus grand et atténué. Le shortcode d’icône se rabat sur la clé i18n shortcode.icon_none quand le SVG manque, mais aucun des deux fichiers de traduction ne définit cette clé : une faute de frappe dans un nom d’icône donnait un <em> vide. Détail, mais ça m’a appris à vérifier les clés i18n avant de faire confiance au repli d’un thème.

Déploiement. Le Dockerfile utilisait klakegg/hugo:0.101.0 et lançait server, c’est-à-dire le serveur de développement de Hugo, pas un build statique. Le fichier Compose montait le projet dans /app alors que l’image avait copié le site dans un autre répertoire de travail : les modifications faites sur la machine n’atteignaient jamais le conteneur. Du HTML statique produit par hugo --minify, construit en CI comme le CV web, aurait été plus simple et plus rapide.

4. HBTheme en semaine 1

HBTheme apportait les commentaires, des assets compatibles npm et les modules Hugo, ce qui m’évitait de reconstruire les gabarits de zéro.

Les compromis sont apparus tout de suite :

  • Structure imposée : démarrage rapide, frictions plus tard quand on veut des types de contenu sur mesure
  • Chaîne d’assets : les étapes npm ajoutent du temps de CI, mais gardent SCSS et JS propres
  • Profondeur de la doc : en semaine 1, la doc du thème compte plus que celle de Hugo

Je choisirais encore un thème « tout compris » pour un site personnel ; je prévoirais du temps pour retirer des modules une fois que le site dépasse les réglages par défaut.

5. Des données dans la page (pas seulement des billets)

Premier essai : intégrer une analyse des vols de voitures à Montréal (projet Substack d’un ami) dans des pages Hugo, pour prouver que la pile pouvait porter graphiques et textes longs, pas seulement des billets courts comme celui-ci.

Étude des vols de voitures à Montréal[1]

Leçon : iframe ou lien sortant, ça suffit pour du contenu invité qu’on ne veut pas dupliquer ; les graphiques natifs dans Hugo viendraient plus tard avec les page bundles et les fichiers statiques.

6. Substack en parallèle

Substack pour les essais longs et un public de type infolettre. Hugo pour la vitrine du portfolio et l’index des projets ; Substack quand un texte a besoin de commentaires ou d’envoi par courriel sans que je gère un serveur de courriel.

Ce partage tient toujours : Hugo, c’est la maison professionnelle de référence ; Substack, un canal facultatif pour les textes longs.

7. Shortcode iframe

Les articles peuvent intégrer des pages HTTPS avec le shortcode iframe du site (src obligatoire ; title, height, loading, etc. facultatifs) :

{{< iframe src="https://example.com/" title="Exemple" height="480" >}}

Exemple : l’ancienne démo FlashGames, toujours hébergée sur GitHub Pages :

À utiliser avec parcimonie : accessibilité, hauteur sur mobile et règles sur les cookies tiers cassent plus souvent qu’un build Hugo.

La raison en une ligne : les vieilles démos (jeux de l’époque Flash) vivent encore sur GitHub Pages ; Hugo les enveloppe avec une URL stable et ma typographie, sans maintenir deux front-ends complets.

8. Ce que je ferais autrement

En regardant ce dépôt avec ce que le site est devenu :

  • Importer les thèmes comme modules. Un thème copié apporte son échafaudage de démo et transforme chaque correctif en amont en fusion manuelle.
  • Construire du HTML statique en CI pour chaque pièce. Un seul workflow qui lance hugo --minify et l’export du CV, au lieu d’un serveur de développement dans un conteneur pour une pièce et d’un workflow pour une autre.
  • Garder les fichiers de traduction complets. Chaque clé i18n appelée par un gabarit doit exister dans chaque langue, replis compris.
  • Ne versionner le CSS généré que s’il rapporte quelque chose. Ici, oui : il permettait à Hugo standard de construire sans Node. Avec Hugo Pipes et une étape Node en CI, il devient du bruit dans les diffs.

9. Depuis la semaine 1

Le site actuel a gagné des modules, des articles bilingues, des notes de conférence et des billets sur l’outillage de l’ère MCP. Journal complet : Refonte du site avec Hugo (partie 2). Voir aussi CV professionnel et JSON Resume et l’index du blogue.

10. Articles liés

Références

  1. Étude des vols de voitures à Montréal. (). [Web page] mohamedilias.substack.com.

Les références utilisent la date de publication de cet article.