Bienvenue dans la documentation technique de QuietCMS, un système de gestion de contenu écrit en PHP moderne, pensé pour être rapide, sécurisé et entièrement dépourvu de base de données. Cette page rassemble tout ce qu'il faut savoir pour comprendre l'architecture du moteur, configurer une instance, créer des thèmes, développer des plugins et exploiter les fonctionnalités SEO et de sécurité avancées. Que vous soyez intégrateur, développeur ou administrateur, vous trouverez ici une référence complète et progressive, de la première installation jusqu'aux personnalisations les plus poussées.

Philosophie : un CMS sans base de données

La plupart des systèmes de gestion de contenu reposent sur un serveur de base de données — MySQL, MariaDB ou PostgreSQL — qui complexifie l'installation, la sauvegarde, la migration et le déploiement. QuietCMS prend délibérément le parti inverse : l'intégralité du contenu est stockée dans des fichiers JSON plats, lisibles par un humain, versionnables et triviaux à sauvegarder. Cette approche dite « flat-file » présente des avantages très concrets au quotidien.

  • Déploiement trivial — un simple rsync, une archive zip ou un commit Git suffit à mettre en ligne. Aucun dump SQL, aucune procédure d'import/export, aucune variable de connexion à configurer.
  • Sauvegarde intégrale — copier le dossier content/ revient à sauvegarder l'intégralité du site. La restauration se résume à recopier les fichiers à leur place.
  • Versioning natif — placez votre contenu sous Git et vous obtenez un historique complet, la possibilité de revenir à n'importe quelle version en quelques secondes, et des revues de modifications lisibles ligne à ligne.
  • Empreinte minimale — pas de service de base de données à maintenir, à sécuriser ni à optimiser. L'hébergement mutualisé le plus modeste suffit largement.
  • Portabilité totale — migrer d'un hébergeur à un autre se résume à transférer des fichiers, sans souci de version de moteur SQL ou d'encodage.

En contrepartie, le modèle flat-file est optimisé pour les sites à forte proportion de lecture : vitrines, blogs, sites de documentation, sites institutionnels et pages produits. Pour les charges d'écriture très intensives, un backend SQLite optionnel — conservant la compatibilité avec le format JSON — est prévu sur la feuille de route du projet.

Table des matières

Architecture & cycle de vie d'une requête

QuietCMS suit le motif du contrôleur frontal (front controller). Toutes les requêtes HTTP sont redirigées par le fichier .htaccess vers un point d'entrée unique, index.php, qui orchestre l'ensemble du traitement. Cette centralisation garantit un comportement cohérent et un seul endroit où brancher la sécurité et le routage.

Voici le déroulé complet d'une requête, étape par étape :

  1. Réécriture d'URL — le .htaccess force le HTTPS et le préfixe www, ajoute le slash final pour la canonicalisation, bloque l'accès direct aux dossiers sensibles (content/, core/, config.php) puis renvoie toute requête non-fichier vers index.php.
  2. Amorçageindex.php charge la configuration, définit la constante BASE_URL à partir du protocole et de l'hôte, puis inclut les classes du cœur (ContentManager, Security, Router, ThemeManager, etc.).
  3. Routage — le Router compare le chemin demandé aux routes enregistrées (accueil, page, blog, catégorie, article, 404) et sélectionne le gestionnaire approprié, en gérant au passage les redirections 301/302 configurées.
  4. Chargement du contenu — le ContentManager lit le fichier JSON correspondant à la page ou à l'article et le décode en tableau PHP exploitable.
  5. Préparation des métadonnées — génération des données structurées JSON-LD, du fil d'ariane, des balises Open Graph et du lien canonical absolu.
  6. Rendu — la fonction render() inclut le layout.php du thème actif, lequel inclut à son tour le gabarit correspondant au type de contenu (home.php, page.php, post.php...).
  7. Post-traitement — injection éventuelle de la barre d'administration si un administrateur est connecté, traitement des shortcodes et des dimensions d'images dans le contenu, puis envoi de la réponse au navigateur.

Ce pipeline reste volontairement linéaire et lisible : aucune couche d'abstraction superflue, aucun conteneur d'injection de dépendances. On peut suivre une requête de bout en bout en lisant seulement quelques fichiers, ce qui rend le débogage et la contribution particulièrement accessibles.

Structure des répertoires

L'organisation des fichiers reflète cette simplicité. Le contenu est strictement séparé du code applicatif et des thèmes :

cms/
├── content/
│   ├── categories/     # Catégories de blog (JSON)
│   ├── pages/          # Pages statiques (JSON)
│   ├── posts/          # Articles de blog (JSON)
│   ├── media/          # Médias uploadés
│   ├── forms/          # Définitions de formulaires (JSON)
│   └── settings.json   # Configuration globale
├── core/
│   ├── ContentManager.php
│   ├── AdminManager.php
│   ├── Security.php
│   ├── Mailer.php
│   ├── MediaManager.php
│   ├── ThumbHelper.php
│   ├── AssetHelper.php
│   └── Router.php
├── themes/
│   ├── showcase/       # Thème vitrine
│   ├── default/        # Thème polyvalent
│   └── juridique/      # Thème professions réglementées
├── plugins/            # Plugins installés
├── uploads/            # Médias et caches publics
└── index.php           # Point d'entrée unique

Le dossier content/ est le seul à contenir des données mutables : c'est lui, et lui seul, qu'il faut sauvegarder régulièrement. Les dossiers core/, themes/ et plugins/ constituent le code applicatif, mis à jour lors des montées de version.

Le stockage JSON en détail

Chaque page, article ou catégorie est un fichier JSON autonome. Une page type contient des champs comme title, slug, h1, meta_description, content (le corps HTML), canonical, featured_image et updated_at. Cette structure plate et explicite rend le contenu auto-documenté.

Les écritures sont réalisées de façon atomique, avec un verrou exclusif (LOCK_EX), afin d'éviter toute corruption en cas d'accès concurrent. Les caractères Unicode sont préservés grâce à l'option JSON_UNESCAPED_UNICODE, et le rendu est indenté pour rester lisible et facilement comparable sous Git.

Les relations entre entités — un article appartient à une catégorie, une catégorie peut posséder un parent — sont exprimées par de simples références de slug. Le ContentManager résout ces relations à la lecture, par exemple pour reconstruire l'URL complète d'une catégorie imbriquée ou la liste des articles associés. Aucune jointure, aucun schéma rigide : la souplesse du JSON autorise l'ajout de champs personnalisés sans migration.

Installation & prérequis

QuietCMS requiert PHP 8.1 ou supérieur et un serveur web supportant la réécriture d'URL — Apache avec mod_rewrite, ou Nginx avec une configuration équivalente. Les extensions recommandées sont mbstring (chaînes multioctets), json (incluse au cœur de PHP), openssl (pour le chiffrement AES) et gd (pour la génération automatique de vignettes et d'images responsives).

L'installation se déroule en quelques étapes simples :

  1. Transférez l'ensemble des fichiers sur votre hébergement, à la racine du domaine ou dans un sous-dossier.
  2. Vérifiez que les dossiers content/, uploads/ et fonts/ sont accessibles en écriture par le serveur.
  3. Ouvrez install.php dans votre navigateur et suivez l'assistant : nom du site, URL canonique, langue et création du compte administrateur.
  4. L'installeur génère automatiquement une clé de chiffrement unique, un slug d'administration aléatoire (pour masquer l'URL du back-office) et un .htaccess durci.
  5. Supprimez ou renommez install.php une fois l'installation terminée, par mesure de sécurité.

Constantes de configuration

Le fichier config.php expose les constantes principales du moteur :

  • ADMIN_SLUG — segment d'URL aléatoire donnant accès au back-office (par exemple a7f3k9), inconnu des robots et scanners.
  • ADMIN_LOGIN_FILE — chemin du fichier JSON stockant les comptes utilisateurs chiffrés.
  • ENCRYPTION_KEY — clé AES-256 dérivée lors de l'installation, idéalement stockée hors de la racine web.
  • DISABLE_TEMPLATE_EDIT — à passer à true pour désactiver l'éditeur de templates PHP en production.
  • SITE_URL — URL de base du site, utilisée pour les liens canoniques, le sitemap et les données structurées.
  • DEFAULT_LANG — langue de l'interface d'administration (fr, en...).

Ces constantes sont définies une fois pour toutes lors de l'installation ; il est rarement nécessaire de les modifier manuellement par la suite, la plupart des réglages étant pilotables depuis le back-office.

Bibliothèque de classes du cœur

Le moteur s'articule autour d'un petit nombre de classes statiques, chacune dotée d'une responsabilité unique et clairement délimitée :

  • ContentManager — lecture, écriture et suppression des entités JSON (pages, articles, catégories), résolution des URLs et des relations.
  • AdminManager — authentification, gestion des sessions, des rôles (administrateur, auteur) et des permissions.
  • Security — génération et validation des tokens CSRF, chiffrement et déchiffrement AES-256-GCM, sanitisation des entrées et nettoyage du HTML.
  • Mailer — envoi d'e-mails via la fonction mail() native ou un serveur SMTP configurable.
  • MediaManager — upload, conversion WebP, redimensionnement et suppression des médias.
  • ThumbHelper — génération et mise en cache de vignettes, et production des attributs d'images responsives (srcset/sizes) adaptés à la taille d'affichage.
  • AssetHelper — minification et intégration en cache des feuilles de styles afin de supprimer les requêtes bloquant le rendu.
  • Router — résolution des routes depuis l'URL et dispatch vers les contrôleurs de pages ou de blog.
  • ThemeManager & FontManager — gestion des réglages de thème (logo, favicon) et auto-hébergement des polices Google Fonts.
  • JsonLD & SitemapBuilder — génération des données structurées Schema.org et du sitemap XML à partir du contenu.

Le système de thèmes

Un thème est un dossier placé sous themes/ contenant un layout.php (gabarit englobant) et des gabarits spécialisés : home.php, page.php, post.php, category.php, blog.php et 404.php. Le layout.php définit la structure HTML commune — en-tête, navigation, pied de page — et inclut dynamiquement le gabarit correspondant au type de contenu demandé.

Les gabarits disposent de variables prêtes à l'emploi : $page (le contenu courant), $settings (les réglages globaux), BASE_URL, $blogSlug et $catPrefix. Les classes utilitaires sont accessibles directement, par exemple ThumbHelper::responsiveAttr() pour des images adaptatives, ThemeManager::getLogoUrl() pour récupérer le logo, ou AssetHelper::inlineCss() pour intégrer et minifier la feuille de styles du thème.

Chaque thème embarque ses propres réglages — logo, favicon, typographie par niveau de titre, options responsive — pilotés depuis le back-office, ainsi qu'un éditeur CSS intégré pour les ajustements fins. Trois thèmes sont fournis en standard : Showcase, une vitrine au style documentation technique ; Default, polyvalent et doté d'une sidebar optionnelle ; et Juridique, pensé pour les cabinets et professions réglementées.

Plugins & système de hooks

Le système d'extensions repose sur un mécanisme d'actions et de filtres, inspiré des grands CMS. Un plugin est un dossier sous plugins/ contenant un fichier index.php qui enregistre ses points d'accroche auprès du PluginManager. Les actions exécutent du code à des moments précis du cycle de vie, tandis que les filtres transforment une valeur avant son utilisation.

Exemple minimal d'un plugin injectant une balise dans le <head> :

// plugins/mon-plugin/index.php
PluginManager::addAction('head_extra', function () {
    echo '<meta name="author" content="Mon Equipe">';
});

Parmi les points d'extension disponibles figurent head_extra, footer_extra et le filtrage du contenu avant rendu. Des plugins sont fournis prêts à l'emploi, comme le bandeau de consentement aux cookies (conforme RGPD) et l'assistant de génération de contenu assisté par intelligence artificielle. La feuille de route prévoit l'ajout de hooks supplémentaires tels que before_save, after_delete et on_media_upload pour un contrôle encore plus fin.

Sécurité

La sécurité est traitée en profondeur, à plusieurs niveaux. Les comptes utilisateurs et les données sensibles sont chiffrés en AES-256-GCM, un algorithme authentifié qui garantit à la fois la confidentialité et l'intégrité. Le back-office est protégé par un slug d'administration aléatoire impossible à deviner, par une protection CSRF sur tous les formulaires, et par un rate limiting contre les attaques par force brute.

Le moteur assainit systématiquement les entrées et nettoie le HTML ; les fichiers SVG uploadés sont passés par un filtre de sanitisation pour neutraliser tout script embarqué. Un module de contrôle du trafic permet de bloquer des adresses IP, des sous-réseaux /24 ou des pays entiers directement depuis le back-office, avec une liste blanche pour les administrateurs.

Côté serveur, le .htaccess envoie un ensemble d'en-têtes HTTP de sécurité : Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Cross-Origin-Opener-Policy (COOP) et Strict-Transport-Security (HSTS) pour forcer le HTTPS. L'accès direct aux dossiers de contenu et de code est interdit.

SEO & performance

QuietCMS intègre nativement tout ce qu'attend un moteur de recherche moderne. Le sitemap XML est généré dynamiquement et tenu à jour à chaque publication. Chaque page expose un lien canonical absolu, des balises Open Graph pour le partage social, et des données structurées JSON-LD : la page d'accueil publie notamment un graphe WebSite + Organization (avec logo et profils sociaux), tandis que les articles déclarent le type BlogPosting avec auteur et éditeur.

Le fil d'ariane (breadcrumbs) est balisé pour les résultats enrichis, et un gestionnaire de redirections 301/302 avec journal des erreurs 404 facilite la maintenance des liens.

Côté performance, plusieurs optimisations sont appliquées d'office : la feuille de styles du thème est intégrée et minifiée (suppression de la requête bloquant le rendu), les images sont servies en versions responsives via srcset/sizes calibrées sur la taille d'affichage, des dimensions explicites sont posées sur chaque image pour éliminer les décalages de mise en page (CLS), et le .htaccess définit un cache navigateur longue durée pour les ressources statiques. L'ensemble vise des scores élevés aux Core Web Vitals de Google.

Sauvegarde, migration & déploiement

Grâce au stockage flat-file, la sauvegarde se résume à archiver les dossiers content/ et uploads/. Pour une protection optimale, versionnez le dossier content/ avec Git : vous disposerez d'un historique complet et pourrez revenir à tout instant à une version antérieure.

Le déploiement d'un environnement de préproduction vers la production consiste à synchroniser les fichiers (par rsync, FTP ou pipeline Git). Aucune étape de migration de schéma n'est nécessaire. Pensez simplement à conserver votre clé de chiffrement et votre config.php propres à chaque environnement.

Dépannage (FAQ)

Le site renvoie une erreur 500 après un changement de .htaccess ? Vérifiez que les modules requis (mod_rewrite, mod_headers, mod_expires) sont actifs ; les directives sont enveloppées dans des balises <IfModule> pour éviter ce cas, mais une directive non supportée peut subsister.

Les images responsives ne se génèrent pas ? Assurez-vous que l'extension PHP gd est installée et que le dossier uploads/ est accessible en écriture ; à défaut, l'image d'origine est servie sans erreur.

J'ai perdu l'URL de mon back-office ? Elle correspond au ADMIN_SLUG défini dans config.php à l'installation.

Comment changer de thème ? Rendez-vous dans le back-office, à la section dédiée à l'apparence, puis sélectionnez le thème souhaité parmi ceux installés sous themes/. Le changement est instantané et n'affecte ni votre contenu ni vos médias, puisque le thème et le contenu sont totalement découplés.

Un article publié n'apparaît pas en ligne ? Vérifiez d'abord son statut : un article en brouillon n'est visible qu'une fois connecté au back-office. Publiez-le pour le rendre accessible à tous et l'inclure automatiquement dans le sitemap. Vérifiez ensuite qu'il est bien rattaché à une catégorie existante.

Contribuer à QuietCMS

QuietCMS est un projet ouvert, façonné par sa communauté. Si vous avez besoin d'une fonctionnalité spécifique, souhaitez signaler un bug ou contribuer au code, consultez la page Contribuer pour découvrir comment participer au développement du projet, ainsi que la feuille de route pour suivre les évolutions à venir.