Featured image of post Refonte de la page Conférences : data-driven avec Hugo

Refonte de la page Conférences : data-driven avec Hugo

Ecrit par ~ zwindler ~

Grosse refonte de ma page “Conférences” qui était un bazar sans nom, dans lequel j’avais aussi mélangé les podcasts, les publications écrites, etc. Maintenant tout est présenté avec des “cartes”, et bien séparé en 3 pages distinctes.

Tous les fichiers sources (YAML, layouts Hugo, CSS) sont disponibles dans /2026/03/conferences-refonte/ si vous voulez reproduire ou vous en inspirer.

Le problème

Ma page Conférences était un gros fichier Markdown monolithique. Talks, podcasts, publications, orga : tout mélangé dans des listes à puces, avec des doublons, et de plus en plus pénible à maintenir (surtout depuis le passage en multi-langue FR/EN).

La page Conférences avant la refonte - un long fichier Markdown avec des listes à puces

L’approche : données + layouts + CSS

Plutôt que de continuer à maintenir du Markdown, je suis passé en data-driven, comme je l’ai fait pour mon side project “101 ways to deploy Kubernetes” :

  1. Données dans des fichiers YAML (data/)
  2. Présentation dans des layouts Hugo custom (layouts/page/)
  3. Style dans des CSS dédiés (static/css/)
  4. Pages Markdown réduites au strict minimum (front matter uniquement)

Et au passage, j’ai découpé une page fourre-tout en trois : Conférences, Podcasts & Lives, Publications.

Les données YAML

data/conferences.yaml

Le plus gros fichier. L’idée clé : un talk (sujet unique) peut être présenté à plusieurs events. Fini la duplication.

talks:
  - id: k8s-scheduling
    title:
      fr: "Limits, Requests, QoS, PriorityClasses, ..."
      en: "Limits, Requests, QoS, PriorityClasses: ..."
    cospeaker: "Quentin Joly"
    slides: "/talks/2025-lrqppobcqvpsslsdk/..."

events:
  - talk: k8s-scheduling       # référence l'id du talk
    event: "DevoxxFR 2026"
    date: 2026-03-22
    type: conference
  - talk: k8s-scheduling
    event: "TNT 26"
    date: 2026-02-12
    type: conference
    video: "https://www.youtube.com/watch?v=..."

organizer:
  - description:
      fr: "Membre de l'équipe d'organisation du Meetup CNCF Bordeaux"
    current: true

Les titres sont bilingues (FR/EN), Hugo sélectionne la bonne langue automatiquement. Les fichiers data/podcasts.yaml et data/publications.yaml suivent le même principe (voir les fichiers sources).

Les pages Markdown minimalistes

L’ancienne page content/page/conferences.md faisait 100+ lignes avec le contenu complet. Voici la nouvelle :

---
title: 'Conférences'
authors:
  - zwindler
type: page
layout: conferences
date: 2022-03-14T18:00:00+00:00
menu:
    main:
        weight: -40
        params: 
            icon: messages
toc: false
---

Le point important, c’est layout: conferences dit à Hugo d’utiliser layouts/page/conferences.html au lieu du layout par défaut. Même chose pour podcasts et publications.

Le layout Hugo (l’essentiel)

Le layout charge les données YAML, calcule des stats, et génère du HTML. Si vous avez déjà manipulé du GoTemplate (helm notamment), ça vous semblera facile à comprendre.

Chargement et indexation des talks :

{{- $data := .Site.Data.conferences -}}
{{- $talks := dict -}}
{{- range $data.talks -}}
  {{- $talks = merge $talks (dict .id .) -}}
{{- end -}}

Compteur dynamique - combien de fois un talk a été présenté :

{{- $count := 0 -}}
{{- $talkId := .id -}}
{{- range $data.events -}}
  {{- if eq .talk $talkId -}}
    {{- $count = add $count 1 -}}
  {{- end -}}
{{- end -}}
<p class="talk-card-count">Présenté {{ $count }}x</p>

Événements groupés par année, les 2 plus récentes dépliées, le reste en archive pliable via <details> :

{{- range $i, $year := $sortedYears -}}
  {{- if lt $i 2 -}}
    <details class="year-group" open>
  {{- else -}}
    <details class="year-group">
  {{- end -}}

Les événements à venir (date dans le futur) reçoivent automatiquement un badge “à venir”. Les layouts complets sont dans les fichiers sources.

Le CSS : des cartes partout

Le design repose sur des cartes CSS grid, avec des badges colorés par type (conf, meetup, BBL), du responsive, et un support dark mode. L’essentiel :

.talks-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.2rem;
}

.talk-card {
  background: var(--card-background);
  border-radius: 10px;
  padding: 1.2rem;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.type-conference { background: #dbeafe; color: #1e40af; }
.type-meetup     { background: #dcfce7; color: #166534; }
.type-bbl        { background: #fef9c3; color: #854d0e; }
.type-upcoming   { background: #fee2e2; color: #991b1b; }

Les CSS complets (585 + 266 + 274 lignes) gèrent aussi le dark mode et les breakpoints mobile. Ils sont dans les fichiers sources.

Bilan

AspectAvantAprès
Pages1 fourre-tout3 spécialisées
DonnéesMarkdown libreYAML structuré
DuplicationOuiNon (relation talk → events)
StatsAucuneAutomatiques
DesignListes à pucesCartes + badges
Multi-langueCopier-collerTitres FR/EN dans le YAML
ArchivesTout d’un blocAnnées pliables

Le commit fait 19 fichiers et ~2400 lignes (une grosse partie du taf, en particulier la traduction markdown => YAML, a été faite par un LLM), mais la logique est simple : données dans YAML, présentation dans les layouts, style dans le CSS. Hugo fait le lien au build, sans JavaScript.

Pour ajouter un nouveau talk maintenant, il me suffit d’ajouter une entrée dans data/conferences.yaml et les stats se mettent à jour toutes seules. C’est quand même plus propre qu’un copier-coller dans plusieurs fichiers Markdown :).

Licensed under CC BY-SA 4.0

Vous aimez ce blog ou cet article ? Partagez-le avec vos amis !   Twitter Linkedin email Facebook

Vous pouvez également vous abonner à la mailing list des articles ici

L'intégralité du contenu appartenant à Denis Germain (alias zwindler) présent sur ce blog, incluant les textes, le code, les images, les schémas et les supports de talks de conf, sont distribués sous la licence CC BY-SA 4.0.

Les autres contenus (thème du blog, police de caractères, logos d'entreprises, articles invités...) restent soumis à leur propre licence ou à défaut, au droit d'auteur. Plus d'informations dans les Mentions Légales

Généré avec Hugo
Thème Stack conçu par Jimmy