Architecture de la couche de contenu : analyse approfondie de l'ingénierie Sanity.io
Pourquoi nous avons choisi Sanity plutôt que Contentful. Un guide technique sur le contenu structuré, les projections GROQ, le texte portable et les pipelines d'images.
Dans l’écosystème Headless Commerce, Shopify est la Base de données produits (PIM). Il excelle dans la gestion des SKU, des prix et des stocks. Il s’agit sans doute du pire système de gestion de contenu (CMS) au monde. Les modèles JSON « Boutique en ligne 2.0 » de Shopify sont rigides. Les champs méta sont essentiellement des chaînes non typées. Pour créer une vitrine de luxe véritablement dynamique, vous avez besoin d’un Content Lake dédié.
Chez Maison Code Paris, nous avons évalué tous les CMS Headless (Contentful, Strapi, Prismic). Nous avons choisi Sanity.io. Cet article explique le raisonnement technique, l’architecture et les détails d’implémentation qui nous permettent de créer des « constructeurs de pages » qui ne cassent pas le code.
Pourquoi Maison Code en parle
Chez Maison Code Paris, nous agissons comme la conscience architecturale de nos clients. Nous héritons souvent de stacks “modernes” construites sans compréhension fondamentale de l’échelle.
Nous abordons ce sujet car il représente un point de pivot critique dans la maturité de l’ingénierie. Une mise en œuvre correcte différencie un MVP fragile d’une plateforme résiliente de niveau entreprise.
La philosophie : le contenu en tant que données, pas HTML
Dans WordPress ou de simples CMS, l’éditeur écrit « Pages ». Ils disposent d’un éditeur WYSIWYG dans lequel ils mettent le texte en gras, ajoutent des images et écrivent essentiellement des blobs HTML. Il s’agit de Présentation couplée. Si vous souhaitez réutiliser ce contenu sur une application iOS ou une notification WatchOS, vous êtes bloqué dans l’analyse des chaînes HTML.
Sanity traite le contenu comme des données structurées.
Une “Hero Section” n’est pas un <div>. Il s’agit d’un objet JSON :
{
"_type": "héros",
"heading": "Collection été",
"cta": { "label": "Acheter maintenant", "link": "/collections/summer" },
"thème": "sombre"
}
Le Frontend (React) décide comment rendre cela. L’éditeur saisit simplement l’intention.
La couche de requête : GROQ vs GraphQL
La plupart des CMS Headless proposent une API GraphQL. C’est bon. Sanity propose GROQ (requêtes d’objets graph-relationnels). C’est exceptionnel. Pourquoi? Parce que GROQ autorise les Projections (remodelage côté client sur le serveur).
Scénario : Vous disposez d’un document Auteur référencé par une publication. Dans GraphQL, le schéma dicte la forme. Dans GROQ, vous pouvez le remodeler à la volée :
// Récupère tous les messages, mais renomme 'author.name' en 'writingBy'
*[_type == "post"] {
titre,
"writeBy": auteur->nom,
"estimatedReadingTime": round(length(body) / 5 / 60) + " min"
}
Notez les calculs (« rond ). Notez le déréférencement du pointeur (->).
Nous pouvons calculer le « Temps de lecture » sur la couche de base de données. Nous pouvons joindre des ensembles de données. Nous pouvons projeter d’énormes objets dans de minces DTO (Data Transfer Objects) parfaitement adaptés à nos composants React.
Cela réduit la taille de la charge utile de 40 à 70 % par rapport aux requêtes GraphQL standard qui effectuent une récupération excessive.
Architecture : le lac de contenu
Sanity est un magasin de documents en temps réel (hébergé sur Google Cloud). Lorsque “Alex” saisit un caractère dans le Studio, il est synchronisé via WebSocket avec la banque de données en millisecondes. “Chloé” voit le curseur se déplacer instantanément (style Google Docs).
Cela résout le plus gros problème dans Headless : Aperçu. Le Headless traditionnel nécessite un « Build » (Next.js SSG) pour voir les modifications. Cela prend 2 minutes. Les éditeurs détestent ça. Avec Sanity + Hydrogen (Remix), on s’abonne au flux de contenu. L’aperçu est instantané.
Le crochet de réaction
importer { useQuery } depuis '@sanity/react-loader' ;
fonction d'exportation useSanityQuery (requête, paramètres) {
// Si vous êtes à l'intérieur de l'Iframe, utilisez des données en direct. Sinon, utilisez les données construites.
const { data } = useQuery(query, params);
renvoyer des données ;
}
Texte portable : résoudre le problème “dangerouslySetInnerHTML”
Si vous laissez les éditeurs écrire du HTML, ils briseront votre site. Ils colleront une balise script. Ils utiliseront 5 balises h1 (destructrices du SEO).
Sanity utilise Portable Text. Il s’agit d’une spécification basée sur JSON pour le texte enrichi.
[
{
"_type": "bloc",
"style": "normal",
"enfants": [
{ "text": "Bonjour " },
{ "text": "Monde", "marks": ["strong"] }
]
}
]
Nous rendons cela avec un composant Serializer. Cela nous donne un contrôle total.
importer {PortableText} depuis '@portabletext/react' ;
composants const = {
// Remplace le rendu de H1
bloquer : {
h1 : ({enfants}) => <h1 className="text-4xl font-bold tracking-tight">{enfants}</h1>,
},
// Intégrations personnalisées
types : {
instagramPost : ({value}) => <InstagramEmbed id={value.url} />,
productCard : ({value}) => <ProductCard id={value.productId} />
}
} ;
export const RichText = ({ contenu }) => (
<PortableText value={content} composants={components} />
);
Sécurité : Aucun XSS (Cross Site Scripting) n’est possible. La structure est strictement typée.
Le pipeline d’images
Les images constituent la partie la plus lourde de tout site de commerce électronique. Sanity dispose d’un Image CDN intégré. Lorsqu’un éditeur télécharge un fichier TIFF de 50 Mo, Sanity le stocke. L’API nous permet de demander sa transformation à la volée.
https://cdn.sanity.io/images/.../my-image.jpg?w=800&h=600&fit=crop&auto=format
Nous construisons un composant Image réutilisable qui exploite ceci :
- Hotspot & Crop : L’éditeur définit le “Focus Point” sur le visage du modèle. Si nous recadrons en carré, le visage est automatiquement centré.
- Format automatique : sert AVIF vers Chrome, WebP vers Safari, JPEG vers Legacy.
- LQIP (Low Quality Image Placeholder) : les métadonnées incluent une chaîne de flou codée en base64. Nous le montrons instantanément pendant le chargement de l’image principale.
// urlBuilder.ts
importer imageUrlBuilder depuis '@sanity/image-url' ;
const builder = imageUrlBuilder(client);
fonction d'exportation urlFor(source) {
return builder.image(source).auto('format').fit('max');
}
Ingénierie de schéma : validations
Nous traitons les modèles de contenu comme des schémas de base de données. Nous appliquons les règles. “Un avis produit doit avoir une note comprise entre 1 et 5.”
// schémas/review.ts
définirField({
nom : 'note',
tapez : 'numéro',
validation : (Règle) => Rule.required().min(1).max(5).error("La note doit être de 1 à 5")
})
Cette validation s’exécute dans le Studio. L’éditeur ne peut physiquement pas publier de mauvaises données. Le code frontend n’a jamais à gérer la « note : 200 ».
Internationalisation (i18n)
Les marques de luxe sont mondiales. Il existe deux stratégies dans Sanity :
- Niveau terrain :
{ title : { fr : "Bonjour", fr : "Bonjour" } }- Pro : conserve tout dans un seul document. Idéal pour des mises en page solides et cohérentes.
- Inconvénient : le document devient énorme.
- Niveau du document :
Document
Titre_ENet documentTitre_FR.- Pro : Liberté totale par marché. La page française peut avoir des sections différentes de la page américaine.
- Inconvénient : plus difficile à gérer la synchronisation.
Nous recommandons généralement Field Level pour le « Contenu global » (descriptions de produits) et Document Level pour les « Pages marketing » (les campagnes diffèrent souvent selon les régions).
10. Sanity Connect pour Shopify (Synchronisation)
Vous ne voulez pas copier-coller les titres de produits de Shopify vers Sanity. Nous utilisons Sanity Connect. Il écoute les Webhooks Shopify. Lorsque les prix sont mis à jour dans Shopify -> Synchronisations avec Sanity. Mais nous le faisons en Lecture seule dans Sanity. L’Editeur voit les données du produit, peut les référencer dans un Lookbook, mais ne peut pas en modifier le prix. Cela maintient la « Source unique de vérité » (Shopify) tout en enrichissant la « Couche de présentation » (Sanity).
11. Tableaux de bord Studio personnalisés
Le CMS est la maison destinée à l’équipe marketing. Nous construisons des widgets de tableau de bord personnalisés dans le Studio.
- Widget Google Analytics : “Top 5 des articles de blog cette semaine”.
- Shopify Widget : “Ticker de ventes en direct”.
- Vercel Build Status : “Le site est-il en cours de déploiement ?”. Cela transforme le CMS en centre de commande, réduisant ainsi le besoin de se connecter à 5 outils différents.
13. Stratégies de migration : WordPress vers Sanity
Migrer 5 000 articles de blog depuis WordPress fait peur. Nous n’utilisons pas de “plugins d’importation”. Nous écrivons des scripts.
- Extraire : Connectez-vous à l’API WP REST. Retirez tous les messages.
- Transformer : Convertir le corps HTML -> Texte portable (en utilisant
@portabletext/to-portabletext).- Ceci convertit les balises
<b>enmarks. - Il télécharge les images, les télécharge sur Sanity Asset Pipeline et remplace le
<img>src par la nouvelle référence d’actif.
- Ceci convertit les balises
- Charger : écriture transactionnelle (100 documents par transaction). Résultat : un ensemble de données propre et structuré à partir d’une soupe HTML désordonnée.
14. Le concept « Content Lake »
Pourquoi l’appeler un « Lac » ? Parce que tu y jettes tout. Produits. Profils du personnel. Emplacements des magasins. Politiques juridiques. Dans un CMS traditionnel, ceux-ci sont cloisonnés. Dans Sanity, ce ne sont que des documents. Vous pouvez lier un « Emplacement du magasin » à un « Profil du personnel » à un « Produit ». “Ce produit est disponible à la boutique parisienne, gérée par Chloé.” Cette fonctionnalité Graph permet des expériences frontales incroyablement riches que WordPress ne peut pas modéliser.
15. Conclusion
La raison nous permet de découpler le « Quoi » (Contenu) du « Comment » (Présentation). Il transforme le CMS d’un goulot d’étranglement en une API. Pour un développeur, interroger du contenu avec GROQ ressemble à un super pouvoir. Pour un éditeur, voir ses modifications en direct sans appuyer sur « Actualiser » semble magique.
Vous n’êtes pas satisfait de votre CMS ?
Si votre équipe marketing brise la mise en page à chaque fois qu’elle publie un article de blog. Engagez nos Architectes.