No description
  • CSS 76.5%
  • HTML 23.5%
Find a file
2026-04-16 09:57:06 +02:00
assets/icons/lucide Add initial files 2026-03-20 12:42:07 +01:00
exampleSite Add credit managment 2026-04-16 09:57:06 +02:00
layouts Add credit managment 2026-04-16 09:57:06 +02:00
static/css Add credit managment 2026-04-16 09:57:06 +02:00
LICENSE Add initial files 2026-03-20 12:42:07 +01:00
README.md Add credit managment 2026-04-16 09:57:06 +02:00
theme.toml Add initial files 2026-03-20 12:42:07 +01:00

Ecomin

Thème Hugo éco-conçu minimal.

Principes

  • Zéro JavaScript -- aucun script, jamais
  • Zéro dépendance externe -- pas de CDN, webfont, analytics
  • CSS unique -- une seule feuille de style, polices système, palettes de couleurs interchangeables
  • Accessibilité -- WCAG 2.1 AA, HTML sémantique, navigation clavier
  • Dark mode -- automatique via prefers-color-scheme
  • Impression -- styles print intégrés

Installation

Ajouter le thème comme sous-module Git :

git submodule add <url-du-repo> themes/hugo-ecomin

Dans hugo.toml :

theme = "hugo-ecomin"

Site de démonstration

Le thème inclut un site d'exemple dans exampleSite/ :

cd exampleSite
hugo server

Configuration

Paramètres du site

[params]
  author = "Nom"                   # meta author
  subtitle = "Sous-titre"          # affiché sous le titre sur la home
  copyright = "CeCILL v2.1"        # texte dans le footer
  copyrightURL = "https://..."     # lien optionnel sur le texte copyright
  favicon = "/favicon.png"         # chemin du favicon
  paletteLight = "default-light"   # palette mode clair (défaut)
  paletteDark  = "default-dark"    # palette mode sombre (défaut)

Menu de navigation

La navigation principale utilise des icônes SVG colorées. Elle est alimentée par le menu main de Hugo et lit les paramètres icon et color depuis le frontmatter de chaque section cible.

[[menus.main]]
  name = "Recettes"
  url = "/recipes/"
  weight = 10

[[menus.main]]
  name = "Journal"
  url = "/journal/"
  weight = 20

Sections

Chaque section peut déclarer dans son _index.md :

Paramètre Type Description
title string Titre de la section
description string Description affichée sous le titre
icon string Chemin de l'icône SVG (ex : lucide/package)
color string Couleur hexadécimale (bordures, fond, icône)
sort string Tri des pages enfants
ressources list Ressources associées (téléchargements, liens)
related list Chemins de pages liées (ex : /modules/module-1)

Exemple :

---
title: Journal
description: Carnet de bord des réalisations.
icon: lucide/notebook-pen
color: "#4a6885"
sort: date-reverse
---

Tri des pages

Le paramètre sort dans le frontmatter d'une section contrôle l'ordre d'affichage de ses pages enfants :

Valeur Comportement
(absent) Tri Hugo par défaut (weight, puis date)
date Par date croissante
date-reverse Par date décroissante
title Alphabétique par titre
weight Par poids

Héritage icon/color

Les pages enfants qui n'ont pas d'icon ou de color héritent automatiquement de ceux de leur section parente. Cela fonctionne dans les listes (page-card) et les en-têtes (page-header).

Ressources

Fichiers téléchargeables affichés sous forme de badges dans le header :

ressources:
  - label: "Support de cours"
    target: /support.pdf
    icon: lucide/file-text        # optionnel, défaut : lucide/download
  - label: "Exercices"
    target: /exercices.pdf
    color: "#6a4c93"              # optionnel
Champ Type Défaut Description
label string -- Texte du lien
target string -- URL du fichier
icon string lucide/download Icône du badge
color string -- Couleur personnalisée du badge

Liens

Liens externes ou internes affichés en bas de page sous forme de page-cards :

links:
  - label: "Documentation"
    target: https://docs.example.com
    description: "Guide complet du module"
  - label: "Voir les exercices"
    target: /exercices/
    description: "Exercices associés"
Champ Type Défaut Description
label string -- Titre du lien
target string -- URL cible
description string -- Description affichée sous le titre
icon string (auto) lucide/external-link si https://, sinon lucide/arrow-right
color string -- Couleur personnalisée

Les liens https:// s'ouvrent automatiquement dans un nouvel onglet.

Pages liées

Pages liées affichées en bas de page sous forme de page-cards, précédées du titre "Voir aussi" :

related:
  - /scenarios/scenario-1
  - /modules/module-2

Les chemins invalides sont ignorés silencieusement.

Convention des partials

Les trois partials resources.html, links.html et related-pages.html suivent la même convention : ils reçoivent la page en contexte et gèrent eux-mêmes la condition d'affichage.

{{ partial "resources.html" . }}
{{ partial "links.html" . }}
{{ partial "related-pages.html" . }}

Templates

Structure des fichiers

layouts/
├── _default/
│   ├── baseof.html        # Structure HTML : head, header/nav, breadcrumb, main, footer
│   ├── single.html        # Page de contenu
│   ├── list.html          # Liste de pages (avec tri configurable)
│   ├── taxonomy.html      # Index de taxonomie / page de terme
│   └── terms.html         # Liste des termes d'une taxonomie
├── partials/
│   ├── page-header.html       # En-tête de page (panel coloré)
│   ├── page-header-body.html  # Contenu commun du header (description, ressources, hook)
│   ├── page-card.html         # Carte cliquable dans une liste
│   ├── page-cards.html        # Liste de page-cards
│   ├── resources.html         # Ressources téléchargeables (badges)
│   ├── links.html             # Liens externes/internes (page-cards)
│   ├── hook.html              # Dispatcher de hooks par section
│   ├── related-pages.html      # Pages liées (bas de page)
│   ├── icon.html              # Injection SVG inline
│   └── breadcrumb.html        # Fil d'Ariane
├── index.html             # Page d'accueil
├── shortcodes/
│   ├── callout.html       # Bloc note/tip/warning/danger
│   ├── details.html       # Accordéon HTML natif
│   ├── columns.html       # Conteneur multi-colonnes
│   ├── column.html        # Colonne individuelle
│   ├── badge.html         # Badge inline coloré
│   ├── icon.html          # Icône inline dans le texte
│   ├── mark.html          # Surligneur coloré
│   ├── kbd.html           # Raccourci clavier
│   ├── quote.html         # Citation avec auteur/source
│   └── figure.html        # Image avec légende et crédit
static/
└── css/
    ├── style.css              # Feuille de style principale
    └── palettes/              # Palettes de couleurs
        ├── default-light.css
        ├── default-dark.css
        ├── nord-light.css
        ├── catppuccin-latte.css
        └── ...

baseof.html

Template de base avec blocks surchargeables :

Block Rôle
head-extra Ajouter des balises dans <head> (feed Atom, meta, etc.)
main Contenu principal (surchargé par chaque template)

Sur la page d'accueil, le titre du site est rendu en <h1> dans le header. Sur les autres pages, c'est un lien <a> vers la home.

single.html

Utilise le partial page-header (panel coloré). Le contenu est rendu dans un <div class="post-content">.

list.html

Affiche un page-header suivi de la liste des pages enfants via le partial page-cards. Le tri est configurable via le paramètre sort du frontmatter.

Partials

page-header.html

Rendu de l'en-tête de page sous forme de panel (bordure gauche, fond teinté). Si la page a une color, le panel prend cette couleur. Sinon, il utilise --color-border (gris discret).

Délègue le contenu commun (description, ressources, hook meta) au partial page-header-body.html.

page-cards.html

Liste de page-cards. Deux variantes d'appel :

{{ partial "page-cards.html" (dict "pages" .Pages.ByTitle) }}
{{ partial "page-cards.html" (dict "terms" .Terms.Alphabetical) }}

resources.html

Liste de ressources (téléchargements, liens externes, liens internes). Reçoit une slice de ressources depuis le frontmatter :

{{ with .Params.ressources }}{{ partial "resources.html" . }}{{ end }}

page-card.html

Carte cliquable représentant une page dans une liste. Paramètres :

{{ partial "page-card.html" (dict "page" . "count" 42) }}
{{ partial "page-card.html" (dict "page" .) }}
Paramètre Type Description
page Page Requis -- la page à afficher
count int Optionnel -- nombre affiché en badge

Affiche : icône, titre, count, description. Hérite icon/color du parent.

Hooks

Deux zones extensibles dans chaque carte. Le mécanisme de résolution (hook.html) cherche un partial par section, puis un fallback générique :

Zone Partial par section Fallback générique
Aside page-card-aside-{section}.html page-card-aside-default.html
Footer page-card-footer-{section}.html page-card-footer-default.html

La résolution :

  1. Si page-card-aside-recipes.html existe, il est utilisé pour les pages de la section recipes
  2. Sinon, si page-card-aside-default.html existe, il est utilisé
  3. Sinon, rien n'est rendu

Chaque hook reçoit la page en contexte.

Exemples d'override dans le site :

{{/* layouts/partials/page-card-aside-recipes.html */}}
{{/* Affiché à droite du titre, uniquement pour la section recipes */}}
{{ with .Params.rating }}<span class="rating">{{ . }}/5</span>{{ end }}
{{/* layouts/partials/page-card-footer-recipes.html */}}
{{/* Affiché sous la description, uniquement pour la section recipes */}}
{{ with .Params.allergens }}
<div class="tags">
  {{ range . }}<span class="badge badge-allergen">{{ . }}</span>{{ end }}
</div>
{{ end }}
{{/* layouts/partials/page-card-footer-default.html */}}
{{/* Fallback pour toutes les sections sans partial spécifique */}}
{{ with .Params.tags }}
<div class="tags">
  {{ range . }}<span class="badge">{{ . }}</span>{{ end }}
</div>
{{ end }}

breadcrumb.html

Fil d'Ariane automatique. Affiché sur toutes les pages sauf la home. Remonte jusqu'à 10 niveaux de profondeur.

icon.html

Charge un SVG inline depuis assets/icons/. Reçoit un chemin relatif :

{{ partial "icon.html" "lucide/house" }}
{{ partial "icon.html" "allergen/gluten" }}

Le chemin correspond à assets/icons/<chemin>.svg.

Les attributs aria-hidden="true" et focusable="false" sont ajoutés automatiquement à l'injection.

Icônes

Le thème embarque la bibliothèque Lucide complète (1700+ icônes) dans assets/icons/lucide/.

Les sites peuvent ajouter d'autres sets d'icônes en créant des sous-dossiers dans leur assets/icons/ (ex : assets/icons/allergen/, assets/icons/diet/).

CSS

Palettes de couleurs

Le thème propose des palettes de couleurs interchangeables. Chaque palette est un fichier CSS dans static/css/palettes/ qui définit les variables --color-* du thème.

Configuration dans hugo.toml :

[params]
  paletteLight = "catppuccin-latte"
  paletteDark  = "catppuccin-mocha"

Sans configuration, le thème utilise default-light et default-dark. Un nom de palette invalide provoque une erreur de build explicite.

Palettes disponibles

Palette Clair Sombre Source
Default default-light default-dark Palette originale du thème
Nord nord-light nord-dark nordtheme.com
Gruvbox gruvbox-light gruvbox-dark github.com/morhetz/gruvbox
Solarized solarized-light solarized-dark ethanschoonover.com/solarized
Rosé Pine rose-pine-dawn rose-pine-moon rosepinetheme.com
Catppuccin catppuccin-latte catppuccin-frappe / catppuccin-macchiato / catppuccin-mocha catppuccin.com
Tango tango-light tango-dark Tango Desktop Project
Adwaita adwaita-light adwaita-dark GNOME HIG

Les palettes paletteLight et paletteDark peuvent être mixées librement (ex : nord-light en clair + catppuccin-mocha en sombre). Pour forcer un seul mode, utiliser la même palette pour les deux.

Couleurs nommées

Chaque palette expose ses couleurs d'origine sous forme de variables CSS --palette-*. Les sites peuvent les utiliser dans leur CSS custom :

:root {
  --color-accent: var(--palette-mauve);  /* Catppuccin */
  --color-accent: var(--palette-frost-1); /* Nord */
  --color-accent: var(--palette-aqua);    /* Gruvbox */
}

Créer une palette custom

Créer un fichier static/css/palettes/mon-theme.css :

:root {
  --color-text:       #...;
  --color-bg:         #...;
  --color-link:       #...;
  --color-link-hover: #...;
  --color-muted:      #...;
  --color-border:     #...;
  --color-accent:     #...;
}

Puis dans hugo.toml :

[params]
  paletteLight = "mon-theme"

Variables

Le thème utilise des variables CSS dans :root. Les couleurs sont fournies par la palette active. Les variables de mise en page et typographie sont dans style.css :

:root {
  /* Typographie */
  --font-body: Georgia, "Times New Roman", serif;
  --font-ui:   system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, "Courier New", monospace;

  /* Mise en page */
  --max-width: 88ch;
  --spacing:   1.5rem;
  --radius:    6px;
}

Variables dynamiques

Définies en inline par les templates :

Variable Source Usage
--level-color color du frontmatter Bordures, fond des cards et panels
--nav-color color de la section cible Icônes de navigation
--badge-color color de la ressource Badges de ressources

Dark mode

Le mode sombre est géré par le système de palettes : paletteLight est chargée avec media="(prefers-color-scheme: light)" et paletteDark avec media="(prefers-color-scheme: dark)".

Impression

Les styles @media print masquent la navigation, le footer, le fil d'Ariane, les badges et les ressources. Le texte est noir sur fond blanc.

Animation

Toutes les transitions sont désactivées si l'utilisateur a activé prefers-reduced-motion: reduce.

Shortcodes

Composants réutilisables dans le contenu Markdown, zéro JavaScript.

callout

Bloc d'information coloré avec icône. 4 types disponibles :

{{</* callout type="note" */>}}
Ceci est une note informative.
{{</* /callout */>}}

{{</* callout type="tip" title="Conseil" */>}}
Contenu du conseil.
{{</* /callout */>}}

{{</* callout type="warning" */>}}
Message d'avertissement.
{{</* /callout */>}}

{{</* callout type="danger" title="Important" */>}}
Message critique.
{{</* /callout */>}}
Paramètre Type Défaut Description
type string note Type : note, tip, warning, danger
title string (auto) Titre personnalisé (défaut : Note/Astuce/Attention/Danger)

details

Accordéon HTML natif (<details>/<summary>), sans JavaScript :

{{</* details summary="En savoir plus" */>}}
Contenu masqué par défaut.
{{</* /details */>}}

{{</* details summary="Ouvert par défaut" open="true" */>}}
Contenu visible au chargement.
{{</* /details */>}}
Paramètre Type Défaut Description
summary string Détails Texte du bouton
open string -- Si présent, le bloc est ouvert par défaut

columns / column

Mise en page multi-colonnes, empilées automatiquement sur mobile :

{{</* columns */>}}
{{</* column */>}}
**Première colonne**

Contenu à gauche.
{{</* /column */>}}
{{</* column */>}}
**Deuxième colonne**

Contenu à droite.
{{</* /column */>}}
{{</* /columns */>}}

badge

Badge inline coloré :

Statut : {{</* badge */>}}stable{{</* /badge */>}} {{</* badge color="#b16286" */>}}v2.0{{</* /badge */>}}
Paramètre Type Défaut Description
color string -- Couleur personnalisée (--badge-color)

icon

Icône SVG inline dans le texte :

Le thème utilise {{</* icon "lucide/heart" */>}} Lucide.

Le paramètre est le chemin de l'icône (identique au partial icon.html).

mark

Surligneur inline coloré :

Texte avec un {{</* mark */>}}passage surligné{{</* /mark */>}}.
En {{</* mark color="#94e2d5" */>}}couleur personnalisée{{</* /mark */>}}.
Paramètre Type Défaut Description
color string #f9e2af Couleur de surlignage

kbd

Raccourci clavier stylé. Les touches sont séparées par + :

Sauvegarder : {{</* kbd "Ctrl+S" */>}}

quote

Citation avec attribution :

{{</* quote author="Saint-Exupéry" title="Terre des hommes" */>}}
La perfection est atteinte, non pas lorsqu'il n'y a plus rien à ajouter,
mais lorsqu'il n'y a plus rien à retirer.
{{</* /quote */>}}
Paramètre Type Défaut Description
author string -- Nom de l'auteur
title string -- Titre de l'œuvre (rendu en <cite>)
source string -- URL de la source

figure

Image avec légende et gestion des crédits. Le crédit est affiché en overlay discret en bas à droite de l'image.

{{</* figure src="photo.jpg" alt="Description" caption="Légende" */>}}
Paramètre Type Défaut Description
src string -- Nom du fichier (page resource) ou URL
alt string -- Texte alternatif
caption string -- Légende sous l'image
credit string -- Crédit (override manuel)
credit-url string -- Lien sur le crédit
nocredit string -- Si présent, désactive l'exigence de crédit

Résolution des crédits

Le shortcode impose un crédit pour chaque image. Le build échoue si aucune source de crédit n'est trouvée. La résolution suit cette chaîne de priorité :

  1. Paramètres du shortcode : credit et credit-url
  2. EXIF/IPTC embarqué dans l'image (champs Artist, Copyright, Credit, Byline)
  3. Sidecar YAML : fichier image.jpg.credit.yaml à côté de l'image
  4. Fichier nocredit : image.jpg.nocredit (crédit non requis)
  5. Erreur de build si aucune source trouvée

Les étapes 2 à 4 ne s'appliquent qu'aux page resources (images dans le page bundle).

Sidecar .credit.yaml

Fichier YAML placé à côté de l'image dans le page bundle :

content/article/
├── index.md
├── photo.jpg
└── photo.jpg.credit.yaml

Format :

author: Photographe
url: https://source.com
license: CC BY 4.0
Champ Type Description
author string Nom de l'auteur/photographe
url string Lien vers la source
license string Licence (affiché après l'auteur)

Fichier .nocredit

Pour les images qui n'ont pas besoin de crédit (captures d'écran, images propres, domaine public), créer un fichier vide image.jpg.nocredit :

content/article/
├── index.md
├── screenshot.png
└── screenshot.png.nocredit

Pour les URLs externes, utiliser le paramètre nocredit=true du shortcode.

Accessibilité

  • Lien d'évitement <a href="#main"> en premier élément du body
  • <h1> unique par page (dans le header sur la home, dans le contenu ailleurs)
  • Fil d'Ariane avec <nav aria-label="Fil d'Ariane">
  • Navigation avec aria-label, aria-current="page", title sur les icônes
  • Focus visible : outline explicite sur :focus-visible
  • SVG décoratifs : aria-hidden="true" focusable="false" injectés automatiquement
  • Polices en rem, base 16px minimum
  • Contraste minimum 4.5:1 (texte normal), 3:1 (grands textes)
  • Largeur de lecture limitée à --max-width

Licence

CeCILL v2.1 -- licence libre compatible GPL, de droit français.