Comment Créer Un Site Avec Hugo Partie 8 : créer des shortcodes
Aldok
| 8 minutes

Mise à jour — Mai 2026
Ce tutoriel a été intégralement révisé pour rester à jour avec Hugo 0.161 et les outils modernes de l'écosystème (Bulma 1.x, vanilla JS, Netlify Forms, OpenStreetMap, Giscus...). Les anciennes syntaxes dépréciées sont signalées quand c'est utile pour comprendre l'évolution.
Créer un site avec Hugo partie 8 : créer des shortcodes personnalisés
Quand on développe un thème en HTML/CSS de façon classique, le moindre élément redondant doit être copié-collé sur chaque page. Avec Hugo, on a vu qu’il était possible de faire des templates pour la partie haute (header) et basse (footer) du site, ainsi que la structure générale de chaque page de contenu.
Sachez que Hugo intègre une autre fonctionnalité très pratique pour intégrer ponctuellement des éléments redondants directement dans le contenu en markdown : les shortcodes (codes-courts).
Si vous venez de l’univers WordPress (ou tout autre CMS), ce mot doit vous être familier : on les utilise souvent pour intégrer des fonctions au sein même du contenu, sans toucher au template (par exemple pour insérer un formulaire de contact dans le contenu d’une page).
Sur WordPress, on utilise l’écriture entre crochets [ nom_du_shortcode ]. Sur Hugo, le principe est exactement le même, on utilise simplement une autre syntaxe (les accolades) pour intégrer des bouts de code dans le contenu.
Pré-requis : activer le mode unsafe
La gestion du HTML brut dans les fichiers markdown a été désactivée par défaut depuis la version 0.60.0 de Hugo (pour des raisons de sécurité), du coup il va falloir activer le mode unsafe dans hugo.toml en ajoutant ces lignes :
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
À noter : c’est nécessaire si vous voulez écrire du HTML directement dans vos fichiers markdown. Si vous vous contentez de markdown pur, vous n’en avez pas besoin.
Première chose à faire : nettoyer le layout index.html
La page themes/sandbox/layouts/index.html doit ressembler à ça à l’heure actuelle :
{{ define "main" }}
<div class="container">
<div class="section">
<div class="content">
{{ .Content }}
</div>
</div>
</div>
{{ end }}
Comme on a l’intention de gérer l’affichage avec des bouts de code, on va remettre ça à plat en ne laissant que ces lignes :
{{ define "main" }}
{{ .Content }}
{{ end }}
Ça permet de remettre à zéro la structure globale de la page d’accueil, pour pouvoir la modifier directement à partir du fichier markdown qui gère son contenu.
Comme vous l’avez sans doute deviné, les shortcodes vont pouvoir s’intégrer directement dans les fichiers de contenu en markdown.
Ajouter un hero header
À partir de maintenant, on va pouvoir taper directement dans le fichier content/_index.md pour bâtir la structure du contenu de notre page d’accueil.
Pour essayer, ajoutez ces quelques lignes qui permettent de construire un hero header en utilisant les classes de Bulma (ce contenu arrive donc directement après le frontmatter) :
<style>
.main-image {
background-position: center;
background-size: cover;
background-image: url(/images/hero-index.jpg);
}
</style>
<section class="hero is-large is-dark main-image">
<div class="hero-body">
<div class="container has-text-centered">
<h2 class="title is-1">Titre du site</h2>
<p>Baseline</p>
</div>
</div>
</section>
Je vous laisse choisir l’image de fond, sachant que si vous reprenez le même chemin que dans mon exemple elle doit se situer dans /static/images.
Côté front, vous devriez voir votre image, avec le titre et la baseline centrés au milieu :

Ça fonctionne très bien : comme nous avons “débloqué” la possibilité de gérer du HTML directement dans les fichiers markdown, on pourrait se contenter de ça pour créer une structure particulière pour la page d’accueil.
Néanmoins, on peut faire plus proprement en intégrant des shortcodes.
La création du premier shortcode
La création d’un shortcode s’effectue dans un dossier layouts/shortcodes du thème.
Créez le dossier themes/sandbox/layouts/shortcodes/ et ajoutez-y le fichier hero-index.html.
Dans ce fichier, coupez-collez le code HTML que vous avez écrit dans votre fichier _index.md (j’insiste bien sur le “coupez” : on l’enlève du fichier markdown pour l’intégrer dans le fichier du shortcode).
Votre fichier themes/sandbox/layouts/shortcodes/hero-index.html doit ressembler à ça :
<style>
.main-image {
background-position: center;
background-size: cover;
background-image: url(/images/hero-index.jpg);
}
</style>
<section class="hero is-large is-dark main-image">
<div class="hero-body">
<div class="container has-text-centered">
<h2 class="title is-1">
< Bout<span class="has-text-primary">2</span>Code >
</h2>
<p>Vous en reprendrez bien un morceau ?</p>
</div>
</div>
</section>
Maintenant, revenez dans _index.md qui doit être vide à l’intérieur (frontmatter mis à part), et ajoutez le shortcode à la première ligne, puis enregistrez :
{{< hero-index >}}
Normalement, vous devriez voir votre hero header et son contenu s’afficher : le shortcode a pris le relais, et affiche le contenu du template hero-index.html !
On va donc pouvoir bâtir cette page un peu particulière à partir de son fichier markdown et de quelques shortcodes.
En résumé : tous les fichiers shortcodes que vous créerez dans layouts/shortcodes pourront s’intégrer dans n’importe quelle page de contenu en les appelant par leur nom. Par exemple, si votre shortcode s’appelle toto.html, il suffira de l’appeler avec la syntaxe {{< toto >}}.
Les shortcodes “wrappers”
Il est possible de créer plusieurs types de shortcodes : je vous ai montré une version “basique” qui n’affiche que des bouts de code ponctuels.
Sachez qu’on peut également créer des shortcodes qui permettent d’englober votre contenu. Pas simple à expliquer comme ça, alors je vous fais un exemple.
Admettons que vous vouliez que votre contenu soit positionné entre 2 balises <section> :
<section class="section">
<div class="container">
<div class="content">
<h2>Titre de la page</h2>
<p>Mon super article de blog</p>
</div>
</div>
</section>
Le contenu du fichier markdown ne contiendrait alors que la phrase entre les balises <p>, à savoir “Mon super article de blog”.
Créons le shortcode qui va formater automatiquement le contenu avec toutes les balises HTML nécessaires :
- Créez un fichier
themes/sandbox/layouts/shortcodes/section.html:
<section class="section">
<div class="container">
<div class="content">
{{ .Inner | markdownify }}
</div>
</div>
</section>
La variable {{ .Inner | markdownify }} permet de récupérer dynamiquement le contenu placé entre l’ouverture et la fermeture du shortcode, et de le traiter comme du markdown.
- Ensuite, dans votre fichier
_index.md, ajoutez :
{{< section >}}
## Titre de la page
Mon super article de blog.
{{< /section >}}
Lorsque Hugo compilera les fichiers, il formatera automatiquement le contenu présent entre {{< section >}} et {{< /section >}}.
Créer des shortcodes avec arguments
On peut aussi créer des shortcodes plus complexes, qui prennent des arguments.
Admettons que vous vouliez créer une liste des derniers articles de votre blog sur votre page d’accueil. On va créer un shortcode qui permet ça.
Commencez par créer le fichier themes/sandbox/layouts/shortcodes/blogposts.html :
{{ $count := .Get "count" | default 6 }}
{{ $pages := where .Site.RegularPages "Type" "in" site.Params.mainSections }}
<section class="section">
<div class="container">
<h2 class="title has-text-centered">Blog</h2>
<div class="columns is-multiline">
{{ range first $count $pages }}
<div class="column is-one-third">
{{ partial "widgets/post-card.html" . }}
</div>
{{ end }}
</div>
</div>
</section>
Le premier paramètre $count définit le nombre d’articles qu’on veut afficher. Par défaut, la valeur sera de 6 si rien d’autre n’est précisé dans le shortcode.
La deuxième ligne est un peu plus complexe : c’est la requête qui va récupérer les différents articles des rubriques principales du site. Par défaut, Hugo se contente d’afficher l’ensemble des articles de la rubrique contenant le plus de posts. Pour lui indiquer d’aller chercher dans plusieurs rubriques, il faut déclarer les rubriques principales dans hugo.toml :
[params]
mainSections = ["blog", "tutos"]
Ainsi, la boucle {{ $pages := where .Site.RegularPages "Type" "in" site.Params.mainSections }} ira chercher l’ensemble des pages contenues dans les rubriques blog et tutos du dossier /content.
Le reste du fichier blogposts.html affiche les contenus selon une structure en cartes telle que celle créée dans la partie 6.
L’appel du shortcode dans _index.md se fera de cette façon :
{{< blogposts >}}
Si vous voulez changer le nombre d’articles à afficher, vous pouvez ajouter un paramètre au shortcode :
{{< blogposts count=9 >}}
En mettant count=9, on affichera 9 posts au lieu des 6 par défaut !
Les shortcodes embarqués prêts à l’emploi
Hugo fournit nativement plusieurs shortcodes très utiles, sans configuration. À connaître :
{{< figure >}}: insère une image avec légende. Très utile pour le SEO et l’accessibilité.{{< figure src="/images/photo.jpg" alt="Description" caption="Légende de la photo" >}}{{< youtube >}}: intègre une vidéo YouTube en lazy-loading natif.{{< youtube ID_DE_LA_VIDEO >}}{{< vimeo >}}: pareil pour Vimeo.{{< gist >}}: embed un Gist GitHub.{{< gist nom-utilisateur ID-DU-GIST >}}{{< highlight >}}: coloration syntaxique avec options avancées (numérotation, surlignage de lignes spécifiques).{{< highlight python "linenos=table,hl_lines=2-3" >}} def hello(): print("Hello") print("World") {{< /highlight >}}
La liste complète : https://gohugo.io/shortcodes/
Alternative moderne : les render hooks
Depuis Hugo 0.62, il existe une autre façon de customiser le rendu du markdown : les render hooks. Plutôt que de demander aux rédacteurs d’écrire un shortcode pour chaque image, vous pouvez intercepter automatiquement chaque image ou chaque lien et lui appliquer un traitement particulier.
Exemple : créez le fichier themes/sandbox/layouts/_default/_markup/render-link.html :
<a href="{{ .Destination | safeURL }}"{{ with .Title }} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"{{ end }}>{{ .Text | safeHTML }}</a>
Avec ce hook, tous les liens externes dans votre markdown s’ouvriront automatiquement dans un nouvel onglet, sans que vous ayez à ajouter target="_blank" à la main. Bien plus propre que d’écrire un shortcode external-link !
Les render hooks disponibles : render-link.html, render-image.html, render-heading.html, render-codeblock.html. Documentation : https://gohugo.io/render-hooks/introduction/
Conclusion
Les shortcodes (et leurs alternatives modernes que sont les render hooks) sont une fonctionnalité très puissante d’Hugo. Combinés aux partials, ils permettent de garder vos contenus markdown propres et lisibles, sans HTML soup, tout en autorisant des présentations riches.
J’espère que cette partie ne vous a pas trop causé de soucis, en cas d’incompréhension n’hésitez pas à m’envoyer un petit message (vous trouverez mon email dans la page “à propos”) et j’essaierai d’éclaircir mes propos !
Pour en savoir plus sur les shortcodes, je vous recommande de consulter la documentation officielle : https://gohugo.io/templates/shortcode-templates/