Contenu éditable (JSON)
Système de gestion de contenu qui permet aux clients de modifier les textes, liens, images et listes sans toucher au HTML, en éditant un simple fichier JSON.
Principe
- Le HTML contient le texte par défaut (visible par les moteurs de recherche, fonctionne sans JS)
- Un fichier JSON contient les valeurs modifiables
- Au premier déploiement, le build génère automatiquement le JSON avec les textes par défaut
- Le client modifie le JSON sur GitHub → le site se met à jour
Le dev n'a rien d'autre à faire. Pas de JSON à écrire, pas de dossier à créer, pas de clé à inventer.
Mise en place
1. Écrire du HTML normal
Le build (build-content.py) ajoute automatiquement data-editable sur les balises <main> sans classe de chaque page. Vous n'avez rien à faire — tout le contenu dans <main> est éditable par défaut. Si votre <main> porte une classe (ex : <main class="docs-content">), il est ignoré par le build.
Pour exclure un élément spécifique, ajoutez data-content-skip. Pour exclure une page entière du système de contenu, ajoutez data-content-skip-page sur <main> :
<main>
<h1>Bienvenue chez nous</h1>
<p>Votre partenaire digital depuis 2015.</p>
<a href="/contact">Nous contacter</a>
<img src="/assets/images/hero.jpg" alt="Photo hero">
<ul>
<li>Design</li>
<li>Développement</li>
</ul>
<p data-content-skip>Ce texte ne sera PAS éditable.</p>
</main>
2. Déployer
./deploy.sh prod
Au premier déploiement, le build ajoute automatiquement data-content sur chaque élément, crée le dossier content/ et génère le JSON.
Convention : pages/entreprise/equipe.html → content/entreprise/equipe.json
3. C'est fait
Le JSON généré ressemble à ça :
{
"bienvenue-chez-nous": "Bienvenue chez nous",
"votre-partenaire-digital-depuis-2015": "Votre partenaire digital depuis 2015.",
"nous-contacter": { "text": "Nous contacter", "href": "/contact" },
"photo-hero": { "src": "/assets/images/hero.jpg", "alt": "Photo hero" },
"design": "Design",
"developpement": "Développement",
"seo": "SEO"
}
Le client n'a plus qu'à modifier les valeurs entre guillemets sur GitHub.
Priorité : le JSON prime toujours sur le HTML. Le client a le dernier mot.
Fusion intelligente : si le dev ajoute un élément dans le HTML, la clé est ajoutée au JSON. Si le dev supprime un élément, la clé est retirée. Les valeurs du client ne sont jamais écrasées.
Mode explicite (optionnel)
Pour contrôler les clés vous-même, ajoutez data-content="ma-clé" directement :
<h1 data-content="hero_titre">Bienvenue chez nous</h1>
Types de contenu
| Type | Valeur JSON | Élément HTML | Comportement |
|---|---|---|---|
| Texte | "string" | Tout élément | Remplace le contenu avec formatage inline |
| Lien | { "text": "...", "href": "..." } | <a> | Met à jour le texte ET le href |
| Image | "/chemin/image.jpg" | <img> | Met à jour le src |
| Image objet | { "src": "...", "alt": "..." } | <img> | Met à jour src et alt |
| Image fond | "/chemin/bg.jpg" | Tout + data-content-bg | Met à jour le background-image |
| Liste | ["item1", "item2"] | <ul> ou <ol> | Génère les <li> |
Formatage inline
| Syntaxe | Rendu |
|---|---|
**gras** | gras |
*italique* | italique |
[texte](url) | lien cliquable |
\n | saut de ligne |
Exemple :
{
"description": "Nous sommes **experts** en *design web*.\nContactez-nous [ici](/contact)."
}
Guide de formatage pour le client
| Ce que le client tape dans le JSON | Ce qui s'affiche sur le site |
|---|---|
"Notre **expertise** à votre service" | Notre expertise à votre service |
"Des sites *modernes* et *performants*" | Des sites modernes et performants |
"Contactez-nous par [email](mailto:contact@monsite.fr)" | Contactez‑nous par email |
"Ligne 1\nLigne 2" | Ligne 1 Ligne 2 |
"Prix : 50 €" | Prix : 50 € |
Règles importantes pour le client :
- Modifier uniquement le texte entre les guillemets
"..." - Ne jamais toucher aux
{,},:ni aux noms avant les: - Ne jamais supprimer de lignes entières
- Si vous faites une erreur, cliquez History (en haut du fichier sur GitHub) pour revenir à la version précédente
Clés imbriquées
Notation pointée pour les objets imbriqués :
{
"hero": {
"titre": "Bienvenue",
"texte": "Notre entreprise..."
},
"contact": {
"tel": "01 23 45 67 89",
"email": "contact@example.com"
}
}
<h1 data-content="hero.titre">Bienvenue</h1>
<p data-content="hero.texte">Notre entreprise...</p>
<span data-content="contact.tel">01 23 45 67 89</span>
Éléments responsive dupliqués
Si un même texte apparaît à plusieurs endroits (version mobile et desktop par exemple), utilisez le même data-content sur tous les éléments. Ils seront tous mis à jour :
<!-- Version desktop -->
<h1 class="desktop-only" data-content="hero_titre">Titre</h1>
<!-- Version mobile -->
<h2 class="mobile-only" data-content="hero_titre">Titre</h2>
Les deux éléments afficheront la même valeur du JSON.
Image de fond
Pour les éléments avec un background-image en CSS, ajoutez data-content-bg :
<section data-content="hero_bg" data-content-bg style="background-image: url(default.jpg)">
{
"hero_bg": "/assets/images/nouveau-fond.jpg"
}
Compilation au déploiement
Le contenu JSON est compilé directement dans le HTML au moment du déploiement. Le script build-content.py (appelé automatiquement par deploy.sh) remplace les éléments data-content par les valeurs du JSON avant le rsync.
Ce script Python s'exécute automatiquement avant chaque mise en ligne. Il lit vos fichiers JSON et écrit le contenu directement dans vos pages HTML — pour que les moteurs de recherche (Google) voient le vrai texte, pas des emplacements vides.
- Le code source HTML (Ctrl+U) contient le bon texte
- Pas de flash de contenu par défaut
- SEO parfait — les moteurs de recherche voient le contenu réel
- Pas de JS requis en production
- Le build est idempotent — rejouable sans risque
En développement local, content.js reste utile pour la preview en temps réel. Si la page ne contient aucun élément data-content, le script se termine silencieusement sans afficher d'erreur.
Gardes-fous et alertes
3 niveaux de protection pour éviter qu'une erreur JSON ne casse le site :
1. Bandeau d'erreur (front-end, rouge)
Si le JSON est introuvable ou contient une erreur de syntaxe : bandeau rouge fixe avec le type d'erreur, la position exacte, et le nom du fichier. Le HTML par défaut reste affiché.
2. Bandeau d'avertissement (front-end, jaune)
Si le JSON est valide mais contient des incohérences (clés manquantes, valeurs vides, types incompatibles) : bandeau jaune informatif. Le contenu est quand même appliqué.
3. Validation pré-déploiement (deploy.sh)
deploy.sh valide tous les fichiers JSON de manière récursive (content/**/*.json, pas seulement content/*.json) avant le déploiement. Si un fichier est invalide, le déploiement est bloqué avec la ligne et colonne de l'erreur.
✗ JSON invalide : content/accueil.json
Ligne 12, colonne 5 : Expecting property name enclosed in double quotes
1 fichier(s) JSON invalide(s). Déploiement annulé.
API JavaScript
| Fonction | Description |
|---|---|
initContent(root) | Charge le JSON et applique. Appelé automatiquement. |
applyContent(data, root) | Applique un objet directement (sans fetch). |
Workflow client
Inviter le client sur GitHub (une seule fois)
Le client a besoin d'un compte GitHub gratuit (github.com → Sign up). Ensuite :
- Aller sur le repo GitHub du projet (ex :
github.com/MonClient/monsite) - Cliquer l'onglet Settings (en haut à droite)
- Dans le menu de gauche, cliquer Collaborators
- Cliquer le bouton vert Add people
- Taper l'email ou le pseudo GitHub du client
- Cliquer Send invitation
- Le client recevra un email d'invitation — il doit cliquer Accept invitation
Comment le client modifie le contenu
Une fois invité, le client peut modifier les textes du site directement depuis GitHub :
- Ouvrir le lien du repo que vous lui avez donné (ex :
github.com/MonClient/monsite) - Cliquer sur le dossier content/
- Cliquer sur le fichier à modifier (ex :
accueil.json) - Cliquer le crayon ✎️ (bouton en haut à droite du fichier, à côté de la poubelle)
- Modifier les textes entre les guillemets uniquement — ne pas toucher aux
{,},:ou aux noms de clés - Cliquer le bouton vert Commit changes... (en haut à droite)
- Dans la popup, laisser le message par défaut et cliquer Commit changes
- Le site se met à jour automatiquement en ~15 secondes
Formatage disponible : le client peut utiliser **gras**, *italique* et [texte du lien](url) directement dans les valeurs JSON.
Le déploiement est automatique via GitHub Actions : à chaque commit sur main, le workflow valide le JSON, compile le contenu dans le HTML, et déploie via SSH/rsync. En cas de connexion instable, le déploiement retente automatiquement jusqu'à 3 fois.
Configuration initiale (une seule fois, par le développeur)
Les informations de connexion SSH se trouvent dans le fichier .deploy.env du projet (créé lors du setup).
Étape 1 — Récupérer les valeurs :
Ouvrir le fichier .deploy.env à la racine du projet et noter les 5 valeurs : PROD_HOST, PROD_PORT, PROD_USER, PROD_PATH, et la clé SSH privée (obtenue via cat ~/.ssh/id_ed25519 dans le terminal — copier tout le contenu, y compris les lignes -----BEGIN et -----END).
Étape 2 — Ouvrir les settings du repo GitHub :
- Aller sur le repo GitHub du projet (ex :
github.com/MonClient/monsite) - Cliquer l'onglet Settings (en haut à droite, à côté de « Insights »)
- Dans le menu de gauche, cliquer Secrets and variables
- Cliquer Actions (dans le sous-menu qui s'ouvre)
Étape 3 — Créer les 5 secrets :
Pour chaque secret du tableau ci-dessous, répéter ces 3 clics :
- Cliquer le bouton vert New repository secret
- Dans Name : taper le nom exactement comme dans le tableau
- Dans Secret : coller la valeur
- Cliquer Add secret
| Name (à taper) | Secret (à coller) | Où trouver la valeur |
|---|---|---|
SSH_PRIVATE_KEY | Le contenu complet de la clé SSH | Terminal : cat ~/.ssh/id_ed25519 |
PROD_HOST | L'adresse IP du serveur | .deploy.env → ligne PROD_HOST= |
PROD_PORT | Le port SSH (souvent 65002 sur Hostinger) | .deploy.env → ligne PROD_PORT= |
PROD_USER | Le nom d'utilisateur SSH | .deploy.env → ligne PROD_USER= |
PROD_PATH | Le chemin absolu sur le serveur | .deploy.env → ligne PROD_PATH= |
C'est fait. À partir de maintenant, chaque commit sur main déclenche le déploiement automatiquement (~15 secondes).
Sécurité
- La clé SSH est stockée dans les GitHub Secrets — jamais visible, même par les admins du repo
- Le client n'a accès qu'au repo de son site — pas aux autres projets ni au serveur
- La clé SSH est restreinte au rsync vers un seul répertoire — pas d'accès shell au serveur
- Isolation des clients — chaque projet a ses propres secrets, un client ne peut pas accéder au site d'un autre
Exemple complet
{
"hero_titre": "Votre **agence digitale** à Lyon",
"hero_texte": "Nous créons des sites web *modernes* et *performants*\npour les entreprises qui veulent se démarquer.",
"hero_cta": { "text": "Demander un devis", "href": "/contact" },
"hero_image": { "src": "/assets/images/hero.jpg", "alt": "Équipe au travail" },
"services_titre": "Nos services",
"services": [
"**Design UI/UX** — Interfaces modernes et intuitives",
"**Développement** — Sites rapides et accessibles",
"**SEO** — Visibilité sur Google",
"**Maintenance** — Suivi et mises à jour"
],
"contact": {
"tel": "04 12 34 56 78",
"email": "contact@monagence.fr",
"adresse": "12 rue de la République, 69001 Lyon"
}
}
Sécurité du contenu
- Le HTML brut est échappé avant le parsing (anti-XSS)
- Les liens
javascript:,vbscript:etdata:sont bloqués - Seules les balises
<strong>,<em>,<a>et<br>sont générées