La documentation de SmartTab Organizer est en ligne sur docs.esprit-vorace.fr. Elle est construite avec Astro Starlight, hébergée sur Cloudflare, et disponible en français, anglais et espagnol.
Trois langues, des dizaines de pages, des tableaux de référence, des captures d’écran sur chaque guide. Pour un développeur solo, maintenir tout cela à la main serait intenable. La réponse tient en un principe simple : tout ce qui peut être dérivé du code est généré depuis le code. Une documentation générée ne ment jamais, et quand elle dérive, la CI le signale.
Cet article détaille les trois pipelines qui font vivre cette documentation : les licences open source, les raccourcis clavier et les captures d’écran.
Le principe : une seule source de vérité
Chaque page générée suit le même schéma :
- Une source de vérité unique vit dans le code (un registre TypeScript, le contenu réel du bundle, des scénarios Playwright).
- Un script
pnpmtransforme cette source en pages MDX Starlight, dans les trois langues d’un coup. - Un garde-fou (test Vitest ou
git diffen CI) échoue si la page committée n’est plus synchronisée avec sa source.
Les pages générées portent toutes un commentaire d’avertissement en tête de fichier, du type : « Cette page est générée depuis src/shortcuts/registry.ts. Lancez pnpm shortcuts:doc pour la mettre à jour. » Personne n’est tenté de les éditer à la main.
Les licences open source : attribuer ce qui est réellement embarqué
SmartTab Organizer embarque React, Radix, Zod, CodeMirror et bien d’autres composants open source. Les licences permissives (MIT, BSD, ISC, Apache) exigent de conserver les mentions de copyright lors de la redistribution. Mais attribuer quoi, exactement ? Le package.json liste des dizaines de dépendances, dont beaucoup ne finissent jamais dans l’extension.
La commande pnpm licenses:generate règle la question en deux temps :
- Un build de capture. Le hook
build:donede WXT, couplé àrollup-plugin-license, écrit un manifestebundled-dependencies.jsonqui liste le code tiers réellement présent dans chaque bundle. Pas ce qui est déclaré : ce qui est embarqué. - La génération des artefacts. Le script croise ce manifeste avec
license-checkeret produit d’un coup :- un JSON pour les puces « Construit avec » du dialogue À propos de l’extension,
- un fichier NOTICE complet (
THIRD-PARTY-LICENSES.txt), avec les textes de licence intégraux, embarqué dans l’extension et visible à la racine du dépôt GitHub, - les trois pages MDX de la documentation (FR, EN, ES), avec un tableau paquet · version · licence · dépôt.
Les outils de développement (Vitest, Playwright, ESLint…) ne sont pas redistribués, donc pas attribués légalement. Ils ont droit à une section séparée, par reconnaissance pour le travail de leurs auteurs.
Le script est idempotent : ordre déterministe, aucun timestamp. Deux exécutions successives produisent exactement le même fichier, ce qui rend les diffs Git lisibles.
Les raccourcis clavier : un registre, deux consommateurs
L’extension propose beaucoup de raccourcis clavier : navigation dans les listes, actions sur les cartes de session, commandes globales du navigateur. C’est un point central pour l’accessibilité, et donc un point où la documentation n’a pas le droit de mentir.
Tous les raccourcis sont déclarés dans un registre TypeScript unique, src/shortcuts/registry.ts. Ce registre alimente deux consommateurs :
- Le panneau intégré. Presser
?dans l’extension ouvre un panneau de référence, dérivé du registre. Il affiche même la touche réellement assignée par l’utilisateur pour les commandes globales, plutôt qu’une valeur par défaut. - La page de référence de la documentation. La commande
pnpm shortcuts:docgénère les trois pages MDX (reference/keyboard-shortcuts), avec un tableau par surface : popup, page d’options, listes, cartes. Les libellés viennent des fichiersmessages.jsonde l’extension, donc la page parle exactement la même langue que l’interface.
Le garde-fou est double. Un test Vitest lit les fichiers MDX committés et vérifie des invariants structurels (chaque groupe du registre a son titre, le nombre de lignes de tableau correspond). Et le workflow CI relance le générateur puis fait un git diff --exit-code : si un contributeur ajoute un raccourci sans régénérer la page, le build échoue avec un message explicite.
Les captures d’écran : une matrice 3 langues × 2 thèmes
C’est le pipeline le plus ambitieux. Toutes les captures utilisées par la documentation Starlight, le README GitHub et la fiche Chrome Web Store sortent d’une source unique : e2e-doc-scenarios/, un pipeline Playwright dédié, distinct des tests E2E fonctionnels.
| Pipeline | Question à laquelle il répond |
|---|---|
tests/e2e/ | La fonctionnalité marche-t-elle dans tous les cas ? |
e2e-doc-scenarios/ | Les écrans documentés s’affichent-ils correctement dans chaque langue et chaque thème ? |
Le pipeline rejoue des scénarios narratifs : de vrais parcours utilisateur (créer une règle, sauvegarder une session, importer un pack), pas des écrans isolés posés artificiellement. Pour que les onglets aient l’air vrais sans dépendre du web, des sites mimétiques statiques (un faux GitHub, un faux YouTube…) sont servis localement. Chaque étape intéressante appelle un helper captureStep() qui numérote et enregistre la capture.
Le tout tourne sur une matrice complète : 3 langues × 2 thèmes (clair et sombre), soit 6 exécutions séquentielles du même scénario. Chaque combinaison produit son jeu de PNG.
Reste à router ces centaines d’images vers leurs destinations. Chaque scénario embarque un manifeste de routage typé qui déclare, capture par capture, où elle doit atterrir : la documentation Starlight, le README ou la fiche Chrome Web Store, avec un filtrage possible par langue et par thème.
Deux commandes complètent l’outillage :
pnpm doc:scenarios:auditproduit un rapport qui repère les captures orphelines, les références qui ne pointent plus vers rien et les fichiers de destination que plus personne ne produit.pnpm doc:scenarios:syncrecopie les captures en cache vers les destinations sans relancer Playwright.
La matrice complète prenant plusieurs minutes, elle n’est pas branchée sur les pull requests. La CI la lance sur les tags de version (les captures restent synchrones avec l’interface livrée), sur un cron hebdomadaire (pour attraper la dérive entre deux versions) et à la demande, avec une option qui ouvre automatiquement une PR contenant les captures rafraîchies.
Bénéfice concret : quand l’interface évolue, refaire la totalité des captures de la documentation, du README et du store, dans les six combinaisons, coûte une seule commande.
En coulisses, quelques générateurs de plus
Le même réflexe s’applique aux à-côtés. Le fichier _redirects de Cloudflare, qui gère la migration des anciennes URL francophones vers le schéma de slugs anglophone, est lui aussi généré par script (pnpm docs:redirects), avec le même en-tête « ne pas éditer à la main ». Et l’extension elle-même referme la boucle : la touche F1 ouvre directement la page de documentation correspondant à l’onglet courant, dans la langue de l’interface.
Ce que ça change pour un développeur solo
Une documentation trilingue avec captures d’écran à jour, c’est normalement le genre de chantier qu’un projet solo abandonne au bout de trois versions. Ici, le coût marginal d’une nouvelle version se résume à : lancer trois commandes, relire les diffs, committer.
C’est aussi cohérent avec la philosophie de l’extension elle-même : du déterminisme plutôt que de la magie. Un raccourci documenté existe forcément, une capture montre forcément l’interface réellement livrée, une licence attribuée correspond forcément à du code réellement embarqué. La documentation ne promet rien que le code ne tienne.
La documentation est en ligne : docs.esprit-vorace.fr. Et l’extension, sur le Chrome Web Store et Firefox Add-ons.