Aller au contenu

Comment Menestrel fonctionne

Menestrel sépare quatre choses que la plupart des CMS mélangent : le schéma, le contenu, la version publiée et le déploiement. Chacune vit à l’endroit qui la sert le mieux. Une fois ce découpage en tête, le CLI, le loader et l’admin se déduisent presque tout seuls.

l'éditeur toi (dev)
│ publie │ cms.config.ts + menestrel sync
▼ ▼
┌─────────────────────────────────────────────────┐
│ Menestrel │
│ contenu versionné + schéma reçu │
└──────────────┬───────────────────┬──────────────┘
│ matérialise │ déclenche et suit
▼ ▼
snapshot immuable cibles de déploiement
poussé sur le CDN (Vercel, Netlify...)
│ │
│ lu au build │ lancent le build
└─────────┬─────────┘
astro build
site statique en ligne
zéro requête vers Menestrel

Les collections, les singletons et leurs champs sont décrits dans cms.config.ts, en TypeScript, avec defineConfig de @menestrel/fields. Ce fichier est du code : versionné, relu en PR, typé. menestrel sync le pousse vers le serveur ; le CLI n’applique jamais une suppression destructive en silence : il demande confirmation pour chaque suppression, et exige --allow-deletions en mode non interactif.

Il n’y a pas de constructeur de schéma dans l’admin, et c’est voulu : la structure du site appartient au dev, pas à l’interface. L’éditeur remplit des champs, il ne les invente pas.

Les entrées, leurs brouillons et leurs versions vivent dans la base de Menestrel, jamais dans ton repo. Aucun commit de contenu : l’historique git reste propre, et l’éditeur final ne rencontre jamais un concept git. Rien n’est captif pour autant : menestrel export ressort à tout moment le Markdown, le JSON et les médias originaux, sur tous les plans.

  1. L’éditeur clique « Publier ».

  2. Menestrel matérialise un snapshot : un manifest, plus un fichier JSON par collection et par locale. Chaque fichier est nommé par son empreinte SHA-256 : deux contenus identiques partagent le même fichier, un fichier ne change jamais, le cache peut donc être infini.

  3. Le snapshot est poussé sur un stockage objet et servi par un CDN, à une URL de publication non devinable, propre au projet.

  4. Après un délai de regroupement (90 secondes par défaut, réglable par projet), Menestrel déclenche les cibles de déploiement actives.

Un snapshot ne change jamais après publication. Revenir en arrière ne « restaure » pas des données : Menestrel re-pointe un snapshot précédent et redéclenche les cibles. Pas de migration, pas de perte, pas de suspense.

Chaque collection déclare menestrelLoader dans src/content.config.ts. Pendant astro build, le loader résout le snapshot selon trois modes stricts, détaillés dans la référence du loader : hors-ligne (MENESTREL_OFFLINE), URL de contenu (MENESTREL_CONTENT_URL, le mode nominal en production), ou découverte par token (MENESTREL_TOKEN, à réserver au développement). Le loader compare les digests d’un build à l’autre : un rebuild sur le même snapshot ne recharge rien.

Le résultat du build est un site statique. En production, il ne fait aucune requête vers Menestrel : ni au chargement d’une page, ni en arrière-plan. Un pic de trafic sur ton site est l’affaire de ton hébergeur statique, jamais celle du CMS.

Un contenu publié n’apparaît en ligne qu’après un build. Plutôt que de laisser cette étape à ta charge, Menestrel la pilote : chaque projet déclare des cibles de déploiement, un deploy hook Vercel, Netlify ou Cloudflare, ou un repository_dispatch GitHub. À chaque publication, chaque cible suit une machine à états : queued, triggered, building, puis live ou failed. Les états au-delà de triggered viennent de l’API du fournisseur, quand son token est renseigné sur la cible ; un build encore en file, dépassé par une publication plus récente, passe en cancelled.

L’admin affiche cet état de bout en bout. L’éditeur voit « En ligne », jamais « build » ni « pipeline ».

Si Menestrel tombe, voici ce qui se passe :

  • Les sites restent en ligne. Ce sont des fichiers statiques chez ton hébergeur : rien dans le chemin de service d’une page ne dépend de Menestrel.
  • Les builds passent. MENESTREL_CONTENT_URL lit le snapshot sur le CDN, pas sur l’application. Un redéploiement pendant la panne aboutit.
  • Seule l’édition attend. Le pire cas réel est « l’édition est indisponible quelques heures », pas « le site du client est tombé ».

Cette promesse ne repose pas sur de la redondance héroïque : elle est structurelle. Au moment où un site a besoin de son contenu, ce contenu est déjà sorti de l’application.