FR EN

Chapitre 02Comprendre

Comment ça marche

Deux flux, deux points de couplage, onze règles qui ne se discutent pas. De quoi lire le code sans se perdre, et savoir tout de suite où une modification a sa place.

6 min de lecture12 sectionsChapitre 2 / 22

Le flux de lecture

C'est le flux du visiteur, et il est volontairement court : tout se passe au build, rien à l'exécution.

JSON de contenu Astro (build) HTML statique CDN Visiteur

Un visiteur reçoit un fichier HTML déjà complet. Aucun appel réseau ne va chercher le contenu, aucune base de données n'est interrogée, et le JavaScript n'est nécessaire à aucun mot affiché. Une page publique embarque environ 175 octets de script en ligne, qui lisent un cookie et ne font rien d'autre — voir « l'amorce d'édition » plus bas.

Le flux d'écriture

C'est le flux du client qui modifie sa page. Il est plus long, et chaque étape a un rôle.

Overlay POST /api/save débit taille identité schéma Zod verrou commit reconstruction
  1. L'overlay envoie le contenu complet de la page

    Pas un champ, pas un diff : le fichier JSON entier, tel qu'il devrait être après modification, accompagné de la version lue à l'ouverture.

  2. La fonction refuse dans un ordre précis

    Débit, puis taille annoncée, puis identité, puis taille reçue, puis forme, chemin, schéma, verrou, écriture. L'ordre n'est pas cosmétique : un plafond de taille placé après la lecture du corps ne protège de rien, et refuser un appelant qui insiste ne demande pas de savoir qui il est.

  3. Le même schéma Zod qu'au build valide le contenu

    Pas une copie du schéma : le même objet, importé du même fichier. Un contenu qui ferait échouer le build n'entre jamais dans le dépôt.

  4. Le verrou optimiste compare les versions

    Si le fichier a changé dans le dépôt depuis l'ouverture de la page, l'écriture est refusée avec un conflit explicite — jamais un écrasement silencieux.

  5. Un commit, puis une reconstruction

    Le commit est attribué à EDITOR_NAME / EDITOR_EMAIL. L'hébergeur détecte la poussée et reconstruit le site : trente à soixante secondes.

Le dépôt est séparé en deux

C'est la décision qui rend l'exploitation tenable au-delà de trois clients. Ce qui est identique d'un site à l'autre est partagé et versionné ; ce qui appartient au site est copié puis adapté.

Par site
Overlay, modèle de contenu, composants, routes serveur, sécurité packages/inline-core dépendance versionnée
Contenu, charte, mise en page, langues, adaptateurs de routes le projet du site créé une fois, puis adapté
Règle

Ce qui est dans inline-core ne se recopie jamais dans un site. Une règle métier qui apparaît dans /functions/api est une règle au mauvais endroit : le jour d'un correctif, il faudra la retrouver dans dix dépôts.

Les deux points de couplage

Deux choses, et deux seulement, dépendent d'un fournisseur extérieur. Elles sont isolées derrière une interface, dans deux fichiers :

les deux seuls points de couplage text
packages/inline-core/src/server/git-provider.ts   readFile / writeFile        (GitHub | GitLab)
packages/inline-core/src/server/auth.ts           verifyAuth / createSession  (clé de site | délégué)

Aucune vérification d'identité et aucun appel à une API Git n'existe ailleurs dans le code. C'est ce qui permet de changer d'hébergeur en quelques heures, de passer de GitHub à GitLab en écrivant une implémentation, ou de basculer vers une authentification multi-utilisateurs sans toucher au reste.

Les onze règles absolues

Elles priment sur toute autre considération. Elles sont reprises ici parce qu'on les enfreint rarement par conviction, et souvent par réflexe.

#RèglePourquoi
1output: 'static' — jamais SSR, jamais hybrideC'est ce qui garantit que tout le contenu est dans le HTML servi.
2Aucune zone éditable dans un composant hydratéclient:only sort le contenu de l'index ; client:load le réaffiche au chargement et efface les modifications en cours.
3Le jeton Git ne quitte jamais le serveurIl appartient à l'agence, pas au client. Jamais dans une réponse, un fichier servi ou un stockage du navigateur.
3 bisLa clé de site est vérifiée exclusivement côté serveurUn hash servi au navigateur est attaquable hors ligne.
4Aucun secret dans le dépôtUniquement en variables d'environnement de la fonction serveur.
5Aucun style libreLes styles passent par les enums Zod. Pas d'hexadécimal, pas de pixels dans le contenu.
6Ne pas utiliser src/pages/api/*En sortie statique, ces routes s'exécutent au build, pas à la requête. Tout va dans /functions.
7Toute écriture est validée côté serveurIdentité, schéma, chemin, taille, assainissement. La validation client ne compte pour rien.
8Aucun jargon technique dans l'interface« Publier » et non « Commit ». Le client ne verra jamais le code.
9Aucune arborescence de contenu dans l'overlayC'est le moment où l'outil redevient un CMS et où le client décroche.
10Les vidéos ne sont jamais téléverséesUn fichier lourd dans Git casse le dépôt et les builds. Fournisseur + identifiant, rien d'autre.
11Ne pas élargir le périmètreLes demandes hors périmètre se signalent, elles ne s'implémentent pas.

Quatre mécanismes qui méritent d'être connus

Le schéma vit dans un fichier neutre

La fonction d'écriture ne peut pas importer astro:content : elle s'exécute hors du contexte Astro. Le schéma Zod est donc isolé dans inline-core/src/schema.ts, qui n'importe rien d'Astro. Le build et l'écriture valident avec le même objet, pas avec deux copies qui finiraient par diverger.

L'amorce d'édition, et pourquoi elle ne donne aucun droit

Chaque page porte environ 175 octets de JavaScript en ligne : ils lisent le cookie inline_edit et, s'il est présent, ajoutent une balise <script> vers l'overlay. Une page publique ne télécharge donc jamais l'éditeur.

Le témoin est falsifiable, et c'est assumé

Le cookie inline_edit ne contient aucun secret. Le forger n'affiche qu'une interface dont toutes les écritures seront refusées côté serveur : les routes vérifient le cookie de session signé, jamais le témoin. Modifier le DOM sans clé n'a pas plus de conséquence qu'avec les outils de développement du navigateur.

Le verrou optimiste

À l'ouverture, l'overlay lit le fichier via /api/content et reçoit une version — chez GitHub, le SHA du blob. Cette version repart au moment de publier. Si elle ne correspond plus, la publication est refusée et un message invite à recharger. Rien n'est écrasé, et le brouillon local n'est pas perdu.

Vérifier une clé coûte volontairement cher

Environ 350 ms : c'est le prix d'argon2id aux paramètres recommandés, et c'est ce qui rend la force brute impraticable. Ce coût n'est payé qu'à la connexion, une fois par tranche de 8 heures. Sur un hébergement facturant le temps processeur, vérifiez que le forfait couvre cette durée sur /api/auth.

Les quatre routes

RouteRôleIdentitéDébit
POST /api/authOuvre une session à partir de la clé5 / 15 min
GET /api/contentLit l'état réel du dépôt et la versionoui60 / 5 min
POST /api/saveValide et publie une pageoui30 / 5 min
POST /api/uploadRange une image dans le dépôtoui30 / 15 min

Détail complet des requêtes, réponses et codes d'erreur : Référence des routes.

Ce qui n'existe pas

  • Pas de base de données. Le dépôt Git tient ce rôle.
  • Pas de serveur applicatif. Quatre fonctions sans état, appelées à l'écriture seulement.
  • Pas de session côté serveur. Le cookie est signé ; rien n'est stocké.
  • Pas de compte utilisateur. Une clé par site.
  • Pas de cache à invalider. Le HTML est reconstruit, donc remplacé.

La suite, concrètement : Démarrage local.