← Tous les projets

yesid.dev : expliquer comment les morceaux s’assemblent

Mon site professionnel en trois langues, avec du contenu modifiable, des récits de projets et un guide interactif pour comprendre les parties d'un logiciel.

Mon site professionnel en français, en anglais et en espagnol. Un endroit pour présenter mon travail, montrer les projets qui l'appuient et ouvrir la conversation.

Partir des questions que les gens se posent#

Une personne qui cherche de l'aide avec son site web ou ses rapports n'arrive pas nécessairement avec une liste de logiciels. Elle sait peut-être qu'elle entre la même information deux fois, qu'un rapport demande trop de manipulations ou que son site ne représente plus son activité. Le choix des outils vient après la compréhension du problème.

yesid.dev réunit ces questions et mon travail de développeur de solutions numériques à la pige, à Montréal. On y trouve mes services, mes projets, des articles, une page pour comprendre les outils et plusieurs façons de me joindre. Construire le site m'a aussi amené à décider comment garder ces explications à jour.

C'est mon propre site professionnel. Je suis responsable des décisions sur ce qu'il raconte, sur la façon dont ses parties se relient et sur ce que je suis prêt à signer.

Plusieurs façons de découvrir le travail#

Les services sont regroupés autour des bases de données et de SQL, des pipelines et de l'automatisation, des tableaux de bord et de l'analytique, puis des sites web et du commerce électronique. Chaque groupe offre un point de départ. Il n'est pas nécessaire de savoir où classer son problème avant de m'écrire.

Les projets donnent une vue plus concrète : ce qui a été construit, les éléments utilisés et ce qu'on peut réellement montrer. Le blogue permet d'expliquer plus longuement le raisonnement derrière une décision. Cette distinction laisse au récit d'un projet son fil conducteur et à un article l'espace nécessaire pour approfondir une question.

La page consacrée aux outils joue un autre rôle. Elle présente les parties d'un logiciel dans des mots courants : l'interface qu'on utilise, la logique derrière, les renseignements qu'il garde et l'infrastructure qui le fait fonctionner. Ses plans interactifs permettent de choisir un type de projet et de voir une façon possible d'assembler ces éléments.

Ce sont des exemples à explorer. Un schéma aide à lancer la discussion, mais une recommandation dépend toujours des besoins réels.

Ce que j'ai construit et ce qu'il faut pour le garder à jour#

Le choix central consiste à séparer la rédaction de la mise en page. Les récits de projets, descriptions de services et traductions ont leur place dans Directus, l'outil d'édition. Le site SvelteKit transforme ce contenu structuré en pages à consulter. Je peux corriger une explication sans refaire sa disposition à la main, pendant que les mêmes règles d'affichage relient les pages entre elles.

Le site fonctionne en français, en anglais et en espagnol. Cela comprend des détails pratiques comme les libellés et les erreurs du formulaire, pas seulement trois versions d'un titre. Le formulaire inscrit aussi les valeurs saisies afin de pouvoir les transporter lors d'un changement de langue. C'est une fonction prévue pour cette transition, pas un stockage permanent des messages inachevés.

Le design inspiré du transport collectif donne au site un langage reconnaissable, mais l'interface conserve des tâches ordinaires. Un long texte a besoin de navigation. Une carte dépliable doit permettre de sélectionner une phrase sans se fermer. Un formulaire doit distinguer un champ vide, une requête en cours et un envoi échoué. C'est là que l'idée visuelle rencontre la personne qui utilise le site.

La publication comprend une étape volontaire. Enregistrer une correction dans l'éditeur ne change pas immédiatement le site public : il faut exporter le contenu, générer une nouvelle version et la mettre en ligne. Ce rythme convient à un site professionnel dont le contenu évolue de façon éditoriale. Il me rend aussi responsable de savoir quelle version est affichée lorsqu'une correction n'apparaît pas.

Des outils d'IA ont aidé à l'implémentation et à la révision. Je dirigeais l'architecture et j'examinais les résultats, y compris lorsqu'une page semblait correcte tout en utilisant du texte conservé au mauvais endroit. Assumer ce projet demande de suivre ces liens, plutôt que de considérer l'écran seul comme preuve que le travail est terminé.

Voilà le projet dans son ensemble : un endroit pour expliquer mon travail, soutenu par un processus d'édition et de publication que je dois entretenir. Les sections suivantes examinent des décisions précises. Chacune peut se lire seule, selon qu'on s'intéresse au contenu, aux langues, à l'interface ou aux opérations.

Le site se présente comme un seul produit, mais le travail se répartit entre quatre domaines : le site public, l'outil d'édition, le code qui transporte et vérifie le contenu, puis les ressources de design partagées. Savoir quel domaine est responsable d'un changement m'aide à éviter une correction au mauvais endroit.

L'application web, construite avec SvelteKit, prend en charge l'expérience du visiteur. Elle organise la page d'un projet, choisit la version linguistique, affiche le contenu, relie les éléments de navigation et gère les interactions, comme l'ouverture d'une section. Directus sert d'outil d'édition. Il est relié à une base de données PostgreSQL sur Neon et fonctionne sur Railway. On y trouve les projets, les services, les articles, les traductions et les contenus partagés.

Entre les deux, il y a des outils écrits pour ce projet. Des fonctions lisent les enregistrements du CMS. Des transformations leur donnent la forme attendue par le site. Des validations vérifient les données, puis l'export produit les modules de contenu utilisés par l'application. Une relation utile dans l'outil d'édition n'a pas besoin de devenir un objet compliqué que chaque page doit interpréter.

Un paquet partagé contient les types, les schémas de validation et les fonctions de traitement communes aux deux côtés. L'exporteur et l'application peuvent ainsi s'entendre sur le contenu d'une section de projet sans maintenir deux interprétations séparées de sa structure.

Le quatrième domaine vient de yesid.dev-design. Le site consomme des copies versionnées de paquets de design pour les composants de base, les valeurs visuelles, le mouvement, le routage linguistique, l'analytique et les métadonnées de recherche. Ce projet applique ces ressources à ses propres contenus et mises en page. Il ne constitue pas à lui seul tout le système de design.

Trois petits changements illustrent la distinction. Corriger la description d'un service se fait dans le CMS. Modifier le comportement d'une carte de projet se fait dans l'application web. Changer une règle de mouvement partagée se fait dans les ressources de design, puis cette version doit être adoptée par le site. Ces chemins distincts permettent de suivre l'origine d'une modification.

La description d'un service change. Un projet mérite une explication plus précise. Une traduction doit être corrigée. Je voulais que ces modifications aient leur place dans un outil d'édition, tout en gardant une présentation cohérente.

Un projet possède une identité, un titre, une courte phrase, une introduction, des sections ordonnées, des services associés, des technologies, des mots-clés, des liens et un état de présentation. Dans Directus, plusieurs de ces éléments sont des enregistrements liés. L'export les transforme en un objet plus simple pour le site. L'ordre des sections vient des valeurs de tri enregistrées; les technologies et les mots-clés sont résolus à partir de leurs relations.

Le schéma partagé d'une section est court :

code ts
export const ProjectSectionSchema = z.object({
	title: LocalizedStringSchema,
	content: LocalizedBlockEditorDocSchema,
});

Il indique qu'une section contient un titre traduit et un document de contenu riche traduit. Il ne demande ni bordure orange, ni disposition sur deux colonnes, ni animation. Ces choix appartiennent à l'interface.

Cette séparation est utile quand un projet doit offrir une courte présentation à la personne qui parcourt le portfolio, puis des explications plus poussées à celle qui évalue le travail. La phrase courte sert à la carte. L'introduction situe le problème. Les sections ordonnées peuvent détailler un modèle de données, un choix d'interface ou une contrainte d'exploitation sans tout faire entrer dans la carte.

Le modèle distingue aussi l'état de présentation du projet de la visibilité du dépôt. Un enregistrement associé à une page publique ne change pas les permissions de son code source. L'indication d'un dépôt privé et le lien vers un site accessible sont deux renseignements différents.

Prenons une correction concrète : une phrase de l'introduction française d'un projet doit être modifiée. Le changement attendu se trouve dans ce document français. L'identité du projet, sa version espagnole, les services associés et le composant de page n'ont pas à changer pour cette seule phrase. C'est l'intérêt pratique de la structure : une petite modification éditoriale a un emplacement précis.

Le corps d'une section utilise BlockEditorDoc, le document JSON produit par l'éditeur de blocs du CMS. Il contient une date technique, une version et un tableau ordonné nommé blocks. Chaque bloc a une identité, un type et les données correspondant à ce type.

Les types pris en charge couvrent les titres, les paragraphes, les listes imbriquées, le code, les citations, les images et les séparateurs. Un paragraphe contient du texte. Un bloc de code contient du code en texte brut. Une image contient une référence de fichier et une légende. Le moteur d'affichage parcourt le tableau et confie chaque type au composant correspondant.

Une explication peut donc prendre plusieurs formes sans tout traiter comme un paragraphe. Une section peut partir d'une question, montrer un court extrait du programme, l'expliquer dans des mots courants et se terminer par une image. L'ordre fait partie du contenu; les règles d'affichage sont partagées.

Les cartes dépliables se trouvent à un autre niveau. Elles entourent la section du projet. Ce ne sont pas des blocs « collapsible » inventés à l'intérieur du document. La page choisit le titre et le corps dans la bonne langue, puis place le document dans CollapsibleSection. La carte fournit le bouton et l'état ouvert ou fermé. BlockRenderer affiche le contenu.

La distinction sert la lecture. Une personne peut suivre le problème et la solution sans lire chaque détail d'implémentation. Une autre peut ouvrir une explication complète du chemin de publication. Chaque section doit donc se comprendre par elle-même, sans obliger le lecteur à reconstruire un raisonnement à partir de fragments dispersés.

La page distingue également les sections de galerie des sections d'article et construit sa navigation autour d'elles. Sur un écran large, la navigation, le texte et le résumé du projet peuvent se côtoyer. Sur un écran étroit, ils se suivent dans l'ordre de lecture, avec une commande de navigation compacte pour passer d'une section à l'autre.

Des fonctions extraient aussi le texte et les titres de ces documents. L'estimation du temps de lecture suit la règle ceil(words / 200), avec un minimum d'une minute. À titre d'exemple, 1 200 mots donnent six minutes; 1 201 sont arrondis à sept. C'est un repère calculé à partir de la longueur, pas une mesure du temps nécessaire pour comprendre du code ou un diagramme.

Le modèle impose certaines limites. Un nouveau type de contenu a besoin d'une structure définie et d'un composant d'affichage. Il n'apparaît pas simplement parce qu'on colle un format inconnu dans l'éditeur. Le modèle actuel n'a pas de bloc vidéo. Les légendes d'images et les textes alternatifs méritent aussi d'être mieux séparés dans le contrat de contenu.

Enregistrer une modification ne crée pas encore une nouvelle page publique. Dans le parcours normal de publication avec du contenu récent du CMS, il faut lire les données, les transformer, les vérifier, produire les modules de contenu, générer le site et déployer cette nouvelle version.

Le paquet web lance l'export de contenu avant la génération du site. L'exporteur rassemble l'ensemble des contenus requis, notamment les projets, les services, les articles, la navigation et le contenu des pages. Chaque fonction de lecture connaît les relations de sa collection. Elle produit des objets que le site peut utiliser sans demander à Directus de refaire ce travail à chaque visite.

La fonction des projets, par exemple, transforme les traductions des sections en correspondances par langue et trie les contenus répétés. Elle valide ensuite le tableau de projets avec le schéma partagé. La présence d'un champ dans la base ne suffit pas si sa forme exportée ne convient pas à l'application.

Avant de préparer les fichiers à écrire, le registre d'export vérifie que toutes les données requises sont présentes. L'export prépare également les variantes de médias dont il a besoin. Il produit des modules TypeScript et un manifeste qui indique les empreintes des fichiers ainsi que l'origine des données : une lecture du CMS ou une copie en cache.

La génération du site utilise ces modules. SvelteKit prépare les routes qui peuvent l'être à l'avance, puis Vercel sert le déploiement. Il reste aussi des traitements côté serveur et des interactions. Préparer le texte n'élimine ni les requêtes d'images, ni l'envoi du formulaire, ni toutes les connexions externes.

Un exemple permet de suivre les étapes. Je corrige un paragraphe français dans Directus et je l'enregistre. L'éditeur montre maintenant la correction, mais le site public contient encore la version exportée auparavant. Un export et une génération réussis préparent la nouvelle version. C'est sa mise en ligne qui la rend accessible aux visiteurs. Regarder seulement l'éditeur, ou seulement la réussite de l'export, ne permettrait pas de confirmer la publication.

Cette organisation convient à un site dont les récits de projets et les descriptions de services évoluent à un rythme éditorial. Elle accepte une étape de publication pour servir du contenu déjà préparé. Il faudrait réexaminer ce choix pour de l'information qui doit apparaître immédiatement après chaque écriture, comme un flux opérationnel en direct. La décision dépend ici du contenu du site, pas d'une règle à appliquer à tous les projets.

Plusieurs caches interviennent dans ce système, avec des rôles différents. Le cache d'export conserve localement une lecture précédente du CMS. Les modules générés constituent les données utilisées par une génération du site. Le cache de compilation peut réutiliser du travail déjà fait. Le cache de diffusion facilite l'envoi d'une réponse déployée. Les appeler tous « le cache » cacherait la question utile : quelle version est utilisée, et pourquoi?

L'export traite volontairement le travail local autrement qu'un déploiement autorisé à lire du contenu récent. Localement, si la lecture du CMS échoue, il peut reprendre une copie sauvegardée. S'il n'en trouve pas de valide, il peut laisser les modules existants intacts et signaler qu'il n'a rien produit. Cela permet de continuer à travailler sur l'interface, sans faire passer le résultat pour un nouvel export du CMS.

Lorsqu'un déploiement autorisé exige un export récent, un résultat provenant d'ailleurs doit être un échec. La décision s'écrit directement :

code ts
export function decideExit(outcome: RunOutcome, policy: FallbackPolicy): number {
	return policy === 'fail' && outcome.source !== 'live' ? 1 : 0;
}

Le nombre est un code de sortie : zéro permet à la commande de se terminer normalement, un signale un échec. Avec la politique stricte, une lecture récente du CMS, identifiée par live, donne zéro, une copie en cache donne un et l'absence de contenu produit donne un. Avec la politique locale souple, la commande peut se terminer avec zéro tout en annonçant clairement son recours au cache.

Imaginons que le CMS soit indisponible pendant que je règle l'espacement d'une carte. Le contenu de la veille peut encore servir au développement local. Maintenant, imaginons que je viens de corriger une description de service et que j'attends cette correction dans le déploiement. Remplacer discrètement le texte par celui de la veille ferait échouer mon objectif. Ce deuxième cas exige une génération interrompue que je peux examiner, plutôt qu'un résultat rassurant avec de vieux contenus.

Un réglage explicite permet aussi de sauter l'export. L'intégration continue et les aperçus ordinaires peuvent alors utiliser les modules déjà enregistrés dans le dépôt sans joindre le CMS. Ce choix est visible dans la configuration; il ne se déduit pas simplement de la réussite d'une commande.

L'exporteur prévoit une limite de temps pour les lectures bloquées. Il exige un ensemble complet de données avant de produire les fichiers, plutôt que de présenter une sélection partielle comme un export complet. L'écriture reste toutefois une suite d'opérations sur des fichiers, pas une transaction de base de données englobant tous les fichiers. Une interruption pendant l'écriture demande de vérifier et de régénérer le résultat avant de l'utiliser. La complétude des données ne constitue pas une garantie contre tous les problèmes de disque.

Le français, l'anglais et l'espagnol sont mes langues de travail. Dans le site, elles touchent bien plus que le titre d'accueil : navigation, explications de projets, libellés du formulaire, messages de validation et pages associées doivent tenir compte de la langue.

L'anglais utilise les adresses sans préfixe. Le français utilise /fr et l'espagnol /es. Dans le contrat de contenu, les valeurs traduites portent les clés en, fr et es. Une section a donc un ensemble de titres et un ensemble de documents par langue, plutôt que trois copies indépendantes du projet entier.

Le schéma exige l'anglais comme base. Le français et l'espagnol sont facultatifs dans la structure partagée, ce qui permet de les ajouter progressivement. Un objet valide ne prouve donc pas que les trois versions sont prêtes. Vérifier la structure et vérifier la complétude éditoriale sont deux tâches distinctes.

Pour les chaînes traduites ordinaires, une valeur anglaise obligatoire qui ne contient que du vide est refusée. L'export lit les enregistrements de traduction, retient les valeurs reconnues et forme la correspondance par langue. Le contenu riche possède son propre schéma. Une simple chaîne ne remplace pas un document lorsque le moteur d'affichage attend une liste ordonnée de blocs.

Prenons une section avec un titre et un corps dans les trois langues. Il y a six valeurs éditoriales à garder cohérentes : trois titres et trois corps. Corriger un fait dans le texte français ne met pas automatiquement les deux autres à jour. L'identité et l'ordre peuvent rester communs, mais le sens demande une révision dans chaque version.

Je veux que les textes se lisent naturellement pour leurs publics. Le français québécois, l'espagnol colombien et l'anglais canadien n'utilisent pas toujours les mêmes tournures ni les mêmes termes familiers. Ce qui doit rester équivalent, c'est le récit : mêmes fonctions, responsabilités, limites et exemples. Traduire un identifiant dans un extrait de code changerait en revanche le programme plutôt que son explication.

Cela mène à une question plus utile que « le bouton de langue existe-t-il? ». Une personne peut-elle lire le projet, comprendre une erreur, suivre un lien associé et me joindre dans la langue choisie? Le modèle soutient ce travail, sans effectuer à lui seul toute la révision éditoriale.

Imaginons qu'une personne commence un message en espagnol, puis passe l'interface en français. Les libellés devraient changer. Les mots qu'elle a écrits doivent rester les siens.

Le changement de langue modifie aussi l'adresse. Dans cette implémentation, la partie de l'interface correspondant à la page est recréée lorsque cette adresse change. Les valeurs conservées seulement dans l'ancien composant disparaîtraient avec lui. Le formulaire inscrit donc explicitement les trois valeurs à transporter :

code ts
const name = persisted<string>('contact-name', '');
const email = persisted<string>('contact-email', '');
const message = persisted<string>('contact-message', '');

Les identifiants stables sont importants. « contact-message » désigne toujours le même champ, quelle que soit la langue de son libellé. Un libellé traduit ferait une mauvaise clé : le changement de langue changerait aussi le nom nécessaire pour retrouver la valeur.

Avant une navigation reconnue comme un changement de langue, le mécanisme conserve les valeurs inscrites, la position de lecture et des renseignements sur l'élément actif. Il place cet ensemble versionné dans le stockage de session. Sur la nouvelle page, les contrôles récupèrent leurs valeurs; le défilement et le focus sont rétablis après l'affichage, puis la copie de transfert est effacée. C'est un passage entre deux pages, pas une promesse de conserver indéfiniment les messages inachevés.

La fonction prépare aussi les valeurs avant le premier affichage du contrôle. Elle évite de montrer un contenu par défaut avant de le remplacer. Pour une section dépliable, le même principe évite qu'une carte s'ouvre un instant avant de retrouver son état fermé.

L'implémentation distingue le fait qu'un envoi a réussi des phrases traduites qui le décrivent. Elle peut conserver la réussite et reconstruire la confirmation dans la nouvelle langue. Garder l'ancienne phrase laisserait une partie de l'interface dans la langue précédente.

Ce mécanisme concerne les valeurs inscrites; il ne signifie pas que tous les parcours linguistiques sont réglés. Le lien de contact d'un plan français doit aussi choisir la destination française. Trouver cette destination et conserver le message sont deux responsabilités différentes. Les deux comptent pour la personne qui utilise le site.

Le site emprunte à la signalisation du transport collectif, aux plans de lignes, au dessin technique et aux fenêtres de terminal. L'orange et le jaune reviennent comme repères. Les marqueurs de sections et le tableau de destinations prolongent cet intérêt dans les pages. La référence est personnelle, mais les composants ont des rôles ordinaires : expliquer une relation, identifier une action ou faciliter la lecture d'une longue page.

Les tokens de design donnent un nom à des décisions communes. Un composant utilise un rôle, comme une couleur principale, une bordure ou une durée de mouvement, au lieu d'inventer une nouvelle valeur isolée. Le site possède aussi ses propres choix de style et de disposition. Réutiliser des composants de base n'oblige pas chaque page à devenir la même composition.

Le paquet consommateur enregistre la provenance de ses ressources partagées. Les copies versionnées gardent une version examinée à la disposition du site, et un contrôle d'intégrité peut les comparer à l'adoption enregistrée. Cela distingue le développement du système partagé de son adoption dans ce produit. Modifier directement une copie ne constitue pas automatiquement une amélioration de la source commune.

La carte dépliable montre le lien entre apparence et interaction. Son en-tête est un vrai bouton, dont l'état d'expansion passe par le composant de base. À la souris, on peut aussi cliquer une zone non interactive de la carte. Le gestionnaire laisse les liens, champs et boutons accomplir leur propre action. Il évite qu'un clic sur une carte imbriquée ferme sa parente et ignore le clic qui termine une sélection de texte.

Ces exceptions ont un but concret. Copier une phrase ne devrait pas fermer la section. Suivre un lien devrait suivre ce lien. Cliquer l'en-tête devrait ouvrir ou fermer une seule fois, même si la carte entière traite aussi les clics.

Les thèmes clair et sombre, les mises en page adaptatives, les règles de réduction du mouvement et le mode calme ajoutent des contextes où le même contenu doit rester utilisable. L'idée visuelle donne sa personnalité au site. Les éléments partagés et leurs règles d'interaction aident à ce que cette personnalité ne nuise pas à la lecture.

La page de contact propose un formulaire court, une adresse courriel et un lien pour réserver un appel d'introduction. Elle donne aussi du contexte sur la ville, les langues de travail et les types de problèmes auxquels je m'intéresse.

Le formulaire suit une séquence. Il vérifie d'abord le nom, le courriel et le message. Une valeur absente n'est pas la même chose qu'une adresse dont le format échoue à la vérification. Les erreurs proviennent du contenu traduit et désignent le champ concerné. Seul un formulaire valide passe à l'envoi.

Pendant une requête, le gestionnaire empêche un nouvel envoi et la commande reste désactivée. Le bouton expose son état occupé et change son texte visible. La personne ne devrait pas avoir à deviner si son premier clic a fait quelque chose.

La requête est envoyée à Web3Forms. Si le service signale un échec ou si la requête provoque une erreur, le formulaire inscrit le problème et retire l'état d'envoi en cours. Il s'arrête avant la séquence de réussite. La confirmation repose sur la réponse du service, sans inspection distincte de la boîte courriel de destination.

Il existe aussi une étape plus tôt : le moment entre l'apparition du HTML préparé et l'activation des gestionnaires JavaScript dans le navigateur. Le bouton reste désactivé jusqu'à ce que le gestionnaire soit prêt. Le code explique pourquoi : un envoi natif du formulaire pourrait autrement recharger la page et placer les valeurs saisies dans les paramètres de son adresse. Le chargement, la confidentialité et le retour visuel se rencontrent ici dans un choix concret.

Les vues ordinateur et mobile peuvent afficher des dispositions différentes. Les identifiants des éléments comprennent donc la disposition pour que les libellés et les descriptions d'erreur visent le bon contrôle. L'identifiant utilisé lors du changement de langue reste indépendant de cette présentation : le champ du message représente toujours la même valeur.

Prenons une connexion lente. La personne envoie une fois, voit l'indication d'attente, puis reçoit une erreur. Le résultat utile est un formulaire qui explique ce qui s'est passé et permet de reprendre. Une animation de réussite déclenchée après un délai serait plus simple à dessiner, mais elle ne raconterait pas le résultat de la requête. Cette séquence fait partie du fonctionnement réel de la page de contact.

Ces sujets deviennent plus faciles à examiner quand on les relie à une action. Dans le formulaire, les libellés doivent identifier les champs. Un champ en erreur utilise aria-invalid et pointe vers son explication avec aria-describedby. Un envoi en cours expose aria-busy. Ces attributs complètent les indications visibles, sans les remplacer.

Dans un long article, l'en-tête d'une section doit rester une commande utilisable au clavier. La navigation doit viser les bons endroits du contenu. Déplier une carte, sélectionner une phrase et suivre un lien sont trois actions, même si elles se produisent dans le même rectangle à l'écran.

Les extraits de code ont leur propre traitement. Le bloc conserve le programme comme texte brut. L'interface peut recevoir une coloration préparée côté serveur; sinon, elle dispose d'un affichage simple où le texte est échappé. La copie utilise le corps du code. L'explication peut ainsi rester lisible sans demander au navigateur d'exécuter l'exemple comme du contenu de page.

Le texte riche ordinaire pose une autre question, puisque l'éditeur peut conserver des marques HTML à l'intérieur du texte. Un BlockEditorDoc valide décrit une structure. Il ne constitue pas à lui seul une politique complète de nettoyage du HTML. Les permissions d'édition, les marques acceptées et le chemin d'affichage forment une frontière distincte. La validation du schéma ne remplace pas cette analyse.

De la même façon, vérifier le format d'un courriel dans le navigateur aide la personne à remplir le formulaire, mais ne peut pas assurer la protection du service d'envoi externe. Un accès nécessaire à la génération du site appartient à l'environnement de génération, pas à un article public ni aux fichiers envoyés au navigateur. Et retirer un aperçu des résultats de recherche ne le rend pas privé : noindex concerne l'indexation, pas le contrôle d'accès.

Ce sont des responsabilités précises que je peux examiner et améliorer. Elles décrivent des choix d'implémentation, sans constituer une certification d'accessibilité ni une affirmation générale selon laquelle un site serait sécurisé.

Les vérifications ne répondent pas toutes à la même question. Le contrôle des types peut détecter un décalage entre les données attendues et reçues par un composant. Les schémas peuvent rejeter un contenu CMS mal formé. Les tests unitaires peuvent exercer une transformation ou un choix de traitement d'erreur. Les tests dans le navigateur peuvent parcourir une interaction.

Les schémas partagés comprennent aussi des comparaisons, à la compilation, entre les types qu'ils produisent et les interfaces écrites séparément. Cela rend un changement de modèle visible des deux côtés du passage CMS vers site. Sans ce lien, un champ pourrait apparaître dans une interprétation et disparaître dans l'autre.

Les tests d'export couvrent notamment un aperçu non autorisé qui tente une lecture récente, une limite de temps dépassée, un média local absent et un résultat non live soumis à la politique stricte. Les tests de la carte vérifient qu'un clic d'en-tête bascule une seule fois, qu'un élément interactif conserve son action et que le bouton garde sa sémantique d'expansion. Ces questions sont utiles parce qu'elles correspondent à des erreurs identifiables.

Le workflow web vérifie les types, les tests unitaires, l'intégrité du contenu généré, l'intégrité des ressources de design copiées, les tokens du produit, le paquet partagé, la génération et la quantité de code envoyée au navigateur. Il prévoit aussi une étape de tests dans le navigateur. Le CMS possède ses propres validations et opérations. Cette organisation décrit la façon de travailler; une version précise a encore besoin de ses propres résultats.

Il faut particulièrement bien expliquer l'intégrité du contenu généré. Le manifeste contient une empreinte SHA-256 pour chaque fichier produit. Si le fichier change sans mise à jour correspondante, la vérification peut détecter la différence. Le manifeste indique aussi si l'export utilisait des données récentes ou un cache.

Une empreinte ne juge pas la justesse d'un paragraphe. Si quelqu'un modifiait le fichier et son empreinte, leur correspondance ne prouverait pas indépendamment que le contenu provient du CMS. Le contrôle aide à repérer les écarts; le processus de publication et la révision restent responsables de la provenance.

C'est pourquoi une affirmation précise, comme « ce test exerce un échec d'export », m'intéresse davantage qu'un grand nombre de tests présenté comme une note de qualité. Le nombre ne dit pas quelle erreur compte, ce qui a été vérifié ni ce sur quoi le lecteur peut s'appuyer.

Quand une page est incorrecte, je dois d'abord trouver où se situe le problème. Le CMS peut encore contenir l'ancien texte. Le module exporté peut ne pas inclure la dernière modification. Le site peut avoir été généré sans cet export. Ou l'adresse publique peut encore servir un autre déploiement. Ces situations demandent des corrections différentes.

Supposons qu'un titre corrigé apparaisse dans Directus, mais pas sur la page publique. Je commencerais par identifier la langue modifiée, la source annoncée par l'export et la génération ainsi que le déploiement auxquels la page appartient. Réécrire le composant à ce moment pourrait masquer un problème de publication.

Les opérations sur le schéma doivent suivre un chemin distinct des changements éditoriaux. Le dépôt contient des états de configuration du CMS et des outils pour comparer la structure voulue à un environnement cible. Une modification peut toucher des champs, des relations ou des données existantes. Le workflow sépare donc les validations et comparaisons en lecture seule des actions opérationnelles explicites. Corriger un paragraphe n'est pas la même opération que modifier la structure qui le conserve.

Le développement et la production ont aussi des rôles différents. Un environnement de développement sert à examiner un changement avant son arrivée sur le site public. Une opération en production exige la bonne cible, un périmètre défini et une trace de ce qui s'est passé. Une démonstration locale réussie ne devient pas automatiquement une preuve de fonctionnement en production.

Le design partagé ajoute une autre question d'entretien. Si le problème vient d'un composant de base utilisé par plusieurs produits, corriger seulement sa copie dans ce site peut créer un écart. Si le problème concerne uniquement la mise en page des projets, déplacer la correction dans le paquet commun peut y introduire une hypothèse propre au produit. L'emplacement de la correction fait partie de la décision.

C'est le côté opérationnel de la responsabilité du site : expliquer d'où vient le contenu, où intervenir, ce que les vérifications établissent et ce qui doit se produire avant que les visiteurs voient une nouvelle version.

Des outils d'IA ont participé à l'implémentation et à la révision. Dans mon article publié sur ce projet, je présente Claude comme l'outil principal d'implémentation et Codex comme un outil de révision qui a aussi aidé à certaines modifications. Je dirigeais l'architecture, gardais le contexte du projet et examinais les résultats.

La frontière du contenu en donne un exemple. Une phrase inscrite directement dans un composant peut avoir exactement la même apparence qu'une phrase provenant du CMS. J'ai trouvé des textes partagés encore présents dans le frontend alors que le modèle choisi prévoyait leur édition dans le CMS. Regarder la page ne suffisait pas : il fallait suivre les données dans les fichiers.

Cet exemple relie les domaines décrits ici. Le résultat visible appartenait au site, la source souhaitée appartenait à l'outil d'édition et le lien manquant concernait le traitement ainsi que l'export. Dire que la page était terminée parce qu'elle semblait correcte aurait manqué l'exigence.

Les courts extraits de code servent le même objectif. Le schéma montre le contenu possible d'une section contrôlée par l'éditeur. La décision d'export montre quand des données de remplacement doivent faire échouer une génération. Les valeurs inscrites du formulaire montrent ce que l'interface prévoit transporter au changement de langue. Chaque extrait soutient une explication limitée, qu'on peut comparer au code qui l'entoure.

Je n'ai pas besoin de prétendre avoir tapé chaque ligne pour assumer la responsabilité du résultat. Je dois comprendre les décisions présentées, examiner les modifications plutôt que les accepter à leur apparence et reconnaître ce qui demande davantage d'étude. Le code généré, les paquets externes, les composants partagés et mes décisions contribuent tous au produit. Ma révision doit tenir compte de leurs interactions.

Comment un portfolio trilingue relie SvelteKit, Directus et une publication vérifiée, avec du contenu structuré et un formulaire qui conserve le brouillon.

3 Langues du site
SvelteKit Framework du site
Directus Gestion du contenu
Neon Hébergement de la base du CMS
Vercel Hébergement du site
SvelteKitSvelte 5TypeScriptTailwind CSSGSAPDirectusNeonBunTurboVercelGitHub ActionsPlaywrightVitest
Site en ligne Dépôt privé (pour le moment)

Bâtissons quelque chosequi avance.

Base de données, pipeline, tableau de bord, site web : peu importe où ça accroche, c'est là qu'on commence.