[ Article ]
DevOps Experience Conf' 2026 : 6 enseignements clés sur la maîtrise des infrastructures

Marie-Pierre Goetz

Lukka Blois
Publié le 13 octobre 2025
La démocratisation des CMS headless comme Strapi permet une approche plus modulaire sur la construction de nos projets.
À la différence des CMS monolithiques (WordPress, Drupal), ils proposent une plus grande flexibilité et liberté dans l’architecture et les solutions employées sur un projet (SPA, SSR, ISR, application mobile etc…) tout en conservant une centralisation du contenu. Un problème majeur subsiste cependant : comment créer des liens internes efficaces entre les différents contenus ? Si tous les CMS headless gèrent des relations entre contenus, ils ne peuvent pas créer automatiquement des liens au sein des textes riches. Dans cet article, nous allons voir comment résoudre ce problème pour Strapi, mais la logique reste applicable à d’autres CMS headless.
Dans le cas de Strapi, l’éditeur rich-text par défaut est un éditeur markdown qui n’est pas prévu pour être étendu. La première étape sera donc de le remplacer par un éditeur basé sur CKEditor qui sera plus facilement extensible.
De par son approche modulaire, il n’y a qu’à installer ce plugin pour Strapi.
L’idée générale est d’ajouter la possibilité de créer des custom tags via CKEditor, pour qu’ils puissent être exploités par le client qui rend notre contenu.
Maintenant que CKEditor est installé, il est possible de l’étendre pour rajouter les fonctionnalités dont nous avons besoin. Pour ce faire, nous allons créer notre propre plugin Strapi. Bouton de toolbar
La première étape est de définir un bouton qui servira d’interface aux éditeurs pour créer les liens internes :
STRAPI\_SVG est une chaîne de caractère qui correspond au SVG qui sera rendu dans la toolbar de l’éditeur.
Il faut ensuite enregistrer une commande dans l’éditeur (elle sera exécutée par la logique côté Strapi) et sert à appliquer notre custom tag à l’édition. Elles permettent d’ajouter un comportement à CKEditor et de l’appliquer via différents vecteurs (bouton, state de l’éditeur…).
Les attributes sont les arguments qui seront passés à la commande, dans notre cas un content type et un identifiant de contenu choisi par l’utilisateur via Strapi.
La première partie : lignes 6 à 11, permet de retirer notre custom tag s’il est déjà appliqué sur la sélection de l’utilisateur.
La seconde partie : lignes 13 et 14, permet d’appliquer notre custom tag à la sélection de l’utilisateur, en appliquant les attributes reçu en paramètre comme data-attribute HTML.
Pour l’appliquer, il suffit d’exposer notre plugin CKEditor dans la partie bootstrap de notre plugin Strapi pour être consommé par la librairie de rich-text.

Maintenant que le bouton est présent dans la toolbar, il faut y associer l’action. Comme CKEditor est un rich-text indépendant, il faut créer un lien entre ce dernier et notre Strapi : nous utilisons un CustomEvent javascript émit globalement, qui pourra être écouter par un composant côté CMS, tout en partageant l’état interne de notre éditeur.

Pour appliquer ce comportement, un listener est ajouté sur le bouton de la toolbar pour émettre ce CustomEvent :
Le code entier du plugin CKEditor peut être trouvé sur ce gist.
À noter qu’il comprend la logique de CKEditor pour identifier les liens customs.
Maintenant que notre événement est émit globalement, on peut gérer le reste de la procédure dans un contexte Strapi.
La subtilité de ce plugin vient du fait que l’on va :
Utiliser les zones d’injection de Strapi pour enregistrer une modale (dans le register de notre plugin)
Définir la condition d’affichage de notre modal comme étant liée à notre CustomEvent émit par notre bouton côté CKEditor
Ainsi, dès que le contributeur cliquera sur le bouton de la toolbar, une modale apparaît pour qu’il puisse choisir le contenu à lier.
Le code entier de la modale peut être trouvé sur ce gist.
À partir de là, la liberté est totale pour présenter ça de la manière la plus ergonomique et pratique possible aux contributeurs. De notre côté, nous avons fait un simple formulaire en 2 étapes : l’utilisateur choisi un content-type, puis un contenu de ce même content-type.

Une fois le choix fait, il ne nous reste plus qu’à appeler la commande CKEditor pour créer notre custom tag avec les données en provenances de Strapi :
À partir de ce point, la modal peut appliquer notre custom tag dans l’éditeur, ce qui permet de persister notre lien interne dans notre texte riche.
Côté serveur, il faut exposer autant d’endpoint que notre interface nécessite. Dans notre cas :
Le code du service utilisé est disponible sur ce gist.
Avec le remplacement de l’éditeur de texte de Strapi, nos champs rich-text sont maintenant du HTML (à la différence du markdown par défaut).
Comme nous utilisons Vue.js, nous n’avons pas besoin de librairie pour transformer le HTML de nos champs en composants pour qu’ils puissent être rendus, et ce grâce à la directive v-html.
Avant de pouvoir rendre le contenu saisi dans Strapi, il faut en extraire les liens internes saisis et les remplacer par des liens valides HTML, plusieurs solutions sont possibles.
Comme la partie édition génère des <span> avec des attributes bien précis, nous pouvons utiliser différentes regex pour extraire les contenus liés facilement :
Cette première regex nous permet de sélectionner tous les <span> qui possède des data-attribute
Après quoi, les deux regex suivantes permettent d’extraire le content-type et l’identifiant du contenu, et ce pour chacun des <span> identifiés par la regex précédente.
Suite à cette opération, les contenus associés sont identifiés et peuvent être récupérés dans Strapi.
Une fois les contenus récupérés, on répète les étapes précédentes, mais au lieux d’extraire les contenus, on génère les liens vers ces contenus avant de pouvoir rendre le contenu HTML à l’utilisateur.
L’ensemble de cette logique est portée par ce hook vuejs.
Pour conclure, même si la fonctionnalité n’est pas native sur tous les CMS headless, ils offrent suffisamment d’extensibilité pour répondre à ce besoin.
Néanmoins, ce genre de solution vient avec son lot de points négatifs :
[ Article ]

Marie-Pierre Goetz