
Intégrer votre Design System dans Jahia
Gautier Ben Aïm
Un design system est un ensemble de composants qui implémentent un langage visuel, et les guidelines qui en cadrent l’usage. En pratique, il se compose généralement de ressources visuelles (Figma, Sketch, etc.), d’une bibliothèque de composants (React, HTML/CSS, etc.) et d’une documentation. Il sert de source de vérité pour garantir l'unité graphique d'une marque sur plusieurs produits, du CMS aux applications, y compris entre différentes équipes sur technologies différentes.
Construire un design system est un investissement rentable à long terme quand plusieurs projets aux technologies différentes doivent offrir la même apparence aux utilisateurs finaux. Les grands groupes ont généralement un mélange de portails, d’outils internes, de sites CMS, d’applications mobiles, et d’autres choses encore. Vos sites Jahia font partie de cet écosystème, et un design system fait que passer de Jahia à vos autres produits se fait de façon transparente pour les utilisateurs.
S’il ne faut retenir qu’une chose de cet article, c’est celle-ci : l’équipe design system et l’équipe d’intégration doivent se coordonner souvent pour que le design system réussisse.
Un design system n’est pas un projet qui se construit en isolation. Il doit être bâti en collaboration étroite avec tous ses utilisateurs finaux : les intégrateurs (l’équipe qui construit le site web par-dessus le CMS) et les éditeurs (celles et ceux qui vont assembler des pages avec ces composants au quotidien). Il n'est pas envisageable d’avoir les éditeurs dans la boucle, c’est donc aux intégrateurs de porter leurs besoins techniques et les besoins fonctionnels des éditeurs. Il est rare qu’un design system soit conçu en tenant compte des contraintes d’un CMS, comme l’édition en glisser-déposer ou les composants de layout et de découpage en sections, et les intégrateurs sont les mieux placés pour anticiper les besoins de l’expérience de contribution.
Le manque de coordination se révèle généralement tard dans le projet : le design system est construit, l’intégration est presque terminée, et les contributeurs commencent à évaluer le résultat.
L’objectif de cet article est de vous éviter cette situation. Intégrer un design system dans un CMS pose des questions précises : les voici toutes, à chaque étape du projet, avec les réponses anticipées. Nous avons aussi couvert le sujet en vidéo, dans le replay Intégrez votre design system dans Jahia.
HTML/CSS ou React ?
Jahia supporte les design systems HTML/CSS comme React : le choix vous appartient. Les deux ont leurs avantages et leurs inconvénients ; si vous n’avez pas encore tranché, voici vos options.
| HTML/CSS | React | |
|---|---|---|
| Avantages |
|
|
| Inconvénients |
|
|
Si tous les projets consommateurs supportent React, nous recommandons un design system React. Si vous devez supporter d’autres technologies que React, un design system HTML/CSS est la seule option.
Les deux fonctionnent dans Jahia, avec cette nuance :
- Les JavaScript Modules sont compatibles avec les design systems HTML/CSS et React.
- Les JSP ne sont compatibles qu’avec les design systems HTML/CSS.
Jahia est le seul CMS Java traditionnel (non headless) capable de rendre des composants React sur le serveur. Votre design system React tourne dans le CMS, pas dans une application frontend séparée : c’est peu courant parmi les CMS Java traditionnels, non headless. Nous avons détaillé le mécanisme dans Sous le capot : l’hydratation des composants React en Java.
Ce qu’il faut cadrer avec l’équipe design system
Trois décisions doivent être prises avec l’équipe design system : quels composants elle fournit, comment leur CSS est produit, et si les organismes s’exposent par composition ou par configuration. Ces trois conversations méritent d’avoir lieu tôt : elles ne coûtent presque rien avant que le design system soit construit, et assez cher après.
Quels composants le design system doit-il fournir ?
Des organismes, et les composants de layout et de découpage en sections. C’est la réponse courte, et elle se comprend mieux avec le vocabulaire de la méthodologie Atomic Design, qui distingue trois niveaux de composants :
- Les atomes sont les plus petites briques d’un design system : un tag, un bouton, un champ de saisie.
- Les molécules assemblent des atomes en une unité fonctionnelle : une liste de tags, un champ de recherche.
- Les organismes assemblent des molécules en une interface qui résout un problème métier : un article de blog, un footer, un en-tête de page.
Les intégrateurs finiront toujours par créer des organismes pour construire des interfaces utiles. Si vous voulez garantir la cohérence et réduire la duplication, fournissez et documentez des organismes dans votre design system.
Il est également fréquent que les équipes design system oublient les composants de layout et de découpage en sections. Ils sont indispensables pour construire des pages web : si l’équipe design system ne les fournit pas, les intégrateurs devront les construire eux-mêmes, ce qui risque de créer des incohérences.
Comment styler les composants ?
Deux options, et une seule fonctionne dans tous les cas : le design system compile son CSS au build et livre un fichier prêt à importer, ou il laisse chaque consommateur le compiler. La première marche toujours. C’est le point le plus technique de cet article, et il vaut mieux le traiter tout au début de l’implémentation du design system.
React est volontairement agnostique sur le CSS : c’est donc au design system de choisir. Voici ce que chaque option implique pour les intégrateurs :
-
Produire le CSS au build. Le design system compile tous les styles en un seul fichier
.cssdepuis le code de ses composants, puis l'expose. Les consommateurs importent ce fichier, et c’est tout, zéro configuration :// Une seule fois dans le projet, par exemple dans le layout racine import '@my/design-system/dist.css';Le gain va plus loin que la simple commodité : la technologie de style devient un détail d’implémentation. Le design system peut passer de Sass aux CSS modules, puis à autre chose, sans qu’aucun consommateur ne s’en aperçoive.
-
Produire le CSS à la consommation. Tailwind, le CSS-in-JS et les approches similaires doivent tourner dans le build du consommateur. Les choix technologiques du design system deviennent alors les contraintes du consommateur : si les composants sont stylés avec Tailwind, chaque consommateur a besoin d’une installation Tailwind fonctionnelle. C’est aussi là que ça peut casser dans Jahia : une approche qui exige d’injecter des styles dans le runtime serveur n’est pas compatible avec les JavaScript Modules.
Le CSS produit au build est toujours une option valable. Le CSS produit à la consommation fonctionne mieux quand les mêmes personnes écrivent le design system et font l’intégration, comme nous le faisons sur Luxe, notre site de démonstration : son design system et son template set vivent dans le même dépôt, donc ses composants exposent des CSS modules bruts, et c’est le build Vite du template set qui les compile.
Les deux approches, côte à côte :
| CSS produit au build | CSS produit à la consommation | |
|---|---|---|
| Qui compile les styles | Le design system | Chaque consommateur |
| Mise en place chez le consommateur | Importer un fichier | Reproduire la toolchain du design system |
| Avec les JavaScript Modules | Fonctionne toujours | Seulement si pas d'injection dans le runtime serveur |
| À choisir quand | Le design system est livré à d'autres équipes | Les mêmes personnes écrivent le design system et font l’intégration |
Composition ou configuration ?
La composition, dans la quasi-totalité des cas : elle laisse l’équipe d’intégration adapter les organismes aux besoins réels des contributeurs, sans repasser par l’équipe design system. C’est la décision la plus lourde de conséquences et, parce qu’elle n’est pas jugée "technique", elle est souvent négligée. Prenons un article de blog, défini dans Jahia comme ce type de contenu :
[example:blogPost] > jnt:content, mix:title
- body (string, richtext) i18n
- tags (string) multiple i18n
- publishedAt (date)
Un organisme configuré expose des props, et se remplit à partir d’elles :
<BlogPost
title={title}
body={body}
publishedAt={publishedAt}
tags={[...]}
/>
Un organisme composé expose un seul point d’entrée, la prop children, et fait confiance au développeur pour s’en servir correctement :
<BlogPost>
<h2>{title}</h2>
<div>{body}</div>
<Date ... />
<TagList ... />
</BlogPost>
La différence a l’air stylistique, mais elle change réellement qui maîtrise les évolutions du design system :
- Avec la configuration, l’équipe design system contrôle entièrement l’apparence de tout ce que le CMS affiche. Les intégrateurs doivent revenir vers cette équipe, et plaider les besoins de leurs contributeurs, chaque fois que la réalité ne correspond pas aux besoins.
- Avec la composition, l’équipe d’intégration peut adapter les organismes à ce dont les contributeurs ont réellement besoin.
Concrètement, voici un footer à deux colonnes, en configuration :
[example:footer] > jnt:content
+ leftCol (example:footerColumn)
+ rightCol (example:footerColumn)
<Footer
leftCol={<RenderChild name="leftCol" />}
rightCol={<RenderChild name="rightCol" />}
/>
Ça marche, et les contributeurs peuvent s’en servir.
Maintenant le même footer, en composition :
[example:footer] > jnt:content orderable
+ * (example:footerColumn)
<Footer>
<RenderChildren />
</Footer>
Ça marche mieux : les contributeurs peuvent réordonner les colonnes en les glissant, et une troisième colonne ne coûte rien côté CMS : pas de nouvelle propriété, pas de mise à jour du CND.
Les composants configurables sont difficiles à maintenir et à faire évoluer dans le temps. En revanche, la composition permet aux consommateurs d’implémenter de nouveaux comportements (par exemple le drag and drop dans l’interface d’édition) sans toucher au design system.
Deux remarques en marge, qui sont en fait les deux faces d’une même pièce :
- Le pattern de configuration se construit facilement par-dessus le pattern de composition, un design system composé ne perd donc rien. L’inverse est faux.
- Les design systems HTML/CSS sont toujours basés sur la composition : c’est tout ce que du HTML peut faire.
Rien de tout cela ne veut dire que le design system doit être un libre-service. Un design system trop strict rend les interfaces d’édition impossibles ; trop permissif, il les rend brouillonnes. Les intégrateurs sont généralement les mieux placés pour trouver l’équilibre parce qu’ils sont les seuls à voir à la fois les composants et les contributeurs.
Utiliser un design system dans un CMS Java : le cas Jahia
L’intégration elle-même est courte : quelques imports dans votre template set, et le design system est consommable dans vos vues. Nous nous efforçons d’offrir une Expérience Développeur (Developer Experience) optimale dans Jahia, et nous avons montré la mécanique complète dans le webinaire Modules JavaScript, JSX et React.
Consommer un design system HTML/CSS
C’est la voie à suivre pour les design systems qui livrent des classes CSS (par exemple Bootstrap ou le DSFR), et pour les projets en JSP. À noter : le DSFR a aussi des bindings React, il peut donc tout aussi bien passer par la voie React décrite juste après.
D’abord, référencez les ressources CSS et JS dans votre template set. Les imports d’URL explicites de Vite vous donnent l’URL de l’asset, et AddResources insère la balise dans la page :
import '@gouvfr/dsfr/dist/dsfr.min.css'; // yarn add @gouvfr/dsfr
import js from '@gouvfr/dsfr/dist/dsfr.module.min.js?url'; // ?url est une feature de Vite
<AddResources
type="inline"
targetTag="body"
inlineResource={<script type="module" src="${buildModuleFileUrl(js)}"></script>}
/>
Ensuite, utilisez les classes CSS dans vos vues :
import { jahiaComponent } from '@jahia/javascript-modules-library';
jahiaComponent(
{
componentType: 'view',
nodeType: 'dsfr:callout',
},
({ title, body }) => (
<div className="fr-callout">
<h3 className="fr-callout__title">{title}</h3>
<p className="fr-callout__text">{body}</p>
</div>
),
);
C’est tout ! La même approche fonctionne en JSP, avec une syntaxe légèrement différente pour la balise AddResources.
Consommer un design system React
C’est plus difficile à anticiper, parce que cela dépend des détails d’implémentation du design system. Cela devrait tenir en deux étapes. D’abord, installez le design system avec un gestionnaire de paquets.
Puis importez les composants et affichez-les depuis une vue :
// Footer/default.server.tsx
import { jahiaComponent, RenderChildren } from '@jahia/javascript-modules-library';
import { Footer } from '@my/design-system';
jahiaComponent({ componentType: 'view', nodeType: 'example:footer' }, () => (
<Footer>
<RenderChildren />
</Footer>
));
Si le design system livre un seul fichier CSS, importez-le une fois dans le projet, dans le layout racine par exemple. Sinon, suivez les instructions du design system lui-même : cela peut fonctionner d’office grâce à Vite (CSS modules, @emotion/styled v10+), ou nécessiter un plugin Vite (Tailwind).
Si le design system ne livre pas d’instructions d’utilisation, demandez-les à l’équipe design system : c’est à elle de les fournir.
Composants interactifs
React est le choix à privilégier pour les composants interactifs. Mais Jahia utilise React comme moteur de template pour du Rendu Côté Serveur, ce qui veut dire que par défaut, Jahia envoie 0 octet de JavaScript au navigateur. Un composant interactif de votre design system a donc besoin d’un pont explicite : le composant <Island>, que nous avons présenté dans Exploiter l’architecture des îles dans le CMS Jahia.
Enveloppez le composant du design system dans un composant client (fichier terminant par .client.tsx) :
// Accordion.client.tsx
import { Accordion } from '@my/design-system';
export default function AccordionClient({ title, body }) {
return <Accordion title={title}>{body}</Accordion>;
}
Puis hydratez-le depuis la vue serveur (fichier terminant par .server.tsx) :
// default.server.tsx
import { Island, jahiaComponent } from '@jahia/javascript-modules-library';
import AccordionClient from './Accordion.client.tsx';
jahiaComponent(
{
componentType: 'view',
nodeType: 'example:accordion',
},
({ title, body }) => <Island component={AccordionClient} props={{ title, body }} />,
);
L’accordéon est rendu sur le serveur, puis hydraté dans le navigateur. Le reste de la page reste du HTML statique.
Exposer un design system aux contributeurs
Exposez les organismes, jamais les atomes, et les molécules seulement dans leur contexte. C’est la dernière question, et celle qui décide si les contributeurs apprécieront le résultat : quels composants deviennent droppables dans Jahia ?
Un design system est conçu pour les développeurs, pas pour les contributeurs. Tout exposer, c’est-à-dire rendre chaque composant droppable et considérer le travail fini, noie les contributeurs sous des choix qu’ils ne peuvent pas exploiter. Notre règle empirique, par niveau Atomic Design :
- N’exposez jamais les atomes. Isolés, ils n’ont pas de sens, et les contributeurs ne sauront pas quoi en faire.
- N’exposez les molécules que dans le contexte où elles ont du sens. Une
<FooterColumn>se crée dans le footer de la page, et nulle part ailleurs. - Exposez les organismes que les contributeurs peuvent réellement placer. Ils résolvent un problème métier, exactement ce que le contributeur cherche à faire, mais certains n’ont de sens que dans un contexte précis, et d’autres sont générés plutôt que saisis.
Concrètement :
| Composant | Catégorie | Exposer ? | Pourquoi |
|---|---|---|---|
<Button> |
Atome | Non | Aucun sens isolé. |
<FooterColumn> |
Molécule | En contexte seulement | Créable dans le footer de la page, nulle part ailleurs. |
<TagList> |
Molécule | Probablement pas | Rempli automatiquement, depuis une édition hors contexte. |
<PageSection> |
Organisme | En contexte seulement | À exposer à la racine des pages, pour la structure visuelle. |
<BlogPostCard> |
Organisme | Oui | Il résout un problème que le contributeur a réellement. |
<PageHeader> |
Organisme | Non | Généré depuis le titre de la page et l’arborescence du site. |
Tous les organismes ne sont pas utiles aux contributeurs : un en-tête de page, par exemple, peut être entièrement généré à partir du titre de la page et de l’arborescence du site, et les contributeurs ne devraient donc pas pouvoir le créer.
Et si le design system n’a aucun organisme ? Construisez-les dans Jahia, et n’exposez que ceux-là. Ils auraient été mieux dans le design system, mais au moins les contributeurs auront une interface utilisable. C’est tout le sujet de Comment les intégrateurs peuvent-ils offrir une expérience optimale aux auteurs de contenu dans un CMS ?
Essayez Jahia !
Jahia CMS est open source et gratuit à essayer. Créer un nouveau module tient en une seule commande :
npm init @jahia/module@latest
La CLI vous guide pour démarrer une instance Jahia en local et y déployer votre module. Notre introduction pour les développeurs frontend (en anglais) prend la suite, et l’espace développeurs de Jahia rassemble le reste.
Conclusion
Amener un design system dans un CMS est avant tout un problème de coordination, et la partie technique est la moitié facile. L’équipe design system et l’équipe d’intégration doivent se coordonner souvent pour que le design system réussisse. Le design system est un produit destiné aux développeurs, et ce sont les intégrateurs qui savent ce dont les contributeurs ont besoin. Réunissez ces deux équipes tôt, dans la même pièce.
Si vous voulez en discuter pour votre propre projet, réservez une session gratuite de 30 minutes avec moi.
FAQ
Peut-on utiliser un design system Tailwind dans un CMS ?
Oui, à condition que le CMS accepte de faire tourner la toolchain Tailwind dans son propre build. Tailwind produit son CSS au moment de la consommation : chaque projet qui consomme le design system a besoin d’une installation Tailwind fonctionnelle. Dans Jahia, cela fonctionne avec un plugin Vite, sauf si l’approche exige d’injecter des styles dans le runtime serveur.
Faut-il un design system React ou HTML/CSS pour un CMS ?
React si tous les projets qui consomment le design system supportent React : les composants sont réutilisés tels quels, avec type-safety et autocomplétion. HTML/CSS dès qu’il faut aussi servir du JSP, du PHP, de l’Angular ou du Vue, car c’est alors la seule option compatible. Dans Jahia, les JavaScript Modules acceptent les deux, les JSP uniquement HTML/CSS.
Quels composants d’un design system faut-il rendre disponibles aux contributeurs ?
Les organismes qui résolvent un problème métier réel, comme une carte d’article ou une section de page. Jamais les atomes : isolés, un bouton ou un tag n’ont aucun sens pour un contributeur. Les molécules seulement dans leur contexte, par exemple une colonne de footer créable dans le footer et nulle part ailleurs. Un composant généré automatiquement ne s’expose pas.
Composition ou configuration : quel pattern choisir pour un organisme ?
La composition. Un organisme composé n’expose qu’un point d’entrée, la prop children, ce qui laisse l’équipe d’intégration adapter le rendu aux besoins réels des contributeurs sans repasser par l’équipe design system. Le pattern de configuration se reconstruit facilement par-dessus la composition, alors que l’inverse est faux. Un design system HTML/CSS est de toute façon toujours composé.
Un design system apporte-t-il un intérêt sur un seul site ?
L’investissement se justifie surtout quand plusieurs projets aux technologies différentes doivent offrir la même apparence : portails, outils internes, sites CMS, applications mobiles. Sur un site unique et une seule équipe, le coût de construction et de documentation dépasse souvent le gain. Le critère de décision est le nombre de projets consommateurs, pas la taille du site.
À découvrir






