yesid.dev
Mon propre site, mené comme un mandat client : le CMS comme source de vérité, du contenu généré servi à l'edge, et chaque affirmation verrouillée par un test.
La plupart des portfolios décrivent le travail. Celui-ci doit y survivre : le site est édité, construit, testé et livré par le même pipeline que je monterais pour un client. L'étude de cas et le livrable sont le même artefact.
La forme est simple. Le contenu vit dans Directus, sur une instance Postgres Neon. Au moment du build, export-fallbacks.ts régénère 21 modules TypeScript typés à partir de l'état réel du CMS et note chacun dans un manifeste SHA-256. SvelteKit prérend chaque page en français et en anglais, puis Vercel sert le résultat. Les visiteurs ne réveillent jamais le CMS : 0 appel par visite.
flowchart LR
directus["CMS Directus"] --> export["export-fallbacks.ts"]
export --> cache["21 modules de contenu typés"]
cache --> manifest["manifeste SHA-256"]
cache --> svelte["prérendu SvelteKit (FR + EN)"]
svelte --> vercel["edge Vercel"]Cette frontière est appliquée, pas promise. Sur Vercel, l'export est vivant ou mort : si le CMS ne répond pas, le build échoue au lieu de livrer du contenu périmé. En local, un fallback est permis, mais il affiche une bannière impossible à manquer et le manifeste note quels modules viennent du cache. Un hook pre-commit et une vérification CI rejettent tous les deux les modifications à la main des fichiers générés. J'édite le CMS, ou rien.
La page services trace une ligne de métro à quatre stations : Bases de données et SQL, Pipelines et automatisation, Tableaux de bord et analytique, Sites web et commerce en ligne. Ce build s'arrête à chacune d'elles, pas comme démo, mais comme structure porteuse.
- `Bases de données et SQL` : le contenu repose dans une instance Postgres Neon derrière Directus. Le schéma est versionné en snapshots, les tags et la pile technique sont de vraies relations M2M au lieu de JSON dénormalisé, et le réglage de l'autosuspend garde la facture de base de données proche de zéro entre les visites.
- `Pipelines et automatisation` : une publication dans le CMS déclenche un hook de déploiement, le build tire le contenu réel, régénère chaque module et le hache dans un manifeste. Les scripts capables d'écrire dans le CMS refusent tous de toucher la prod par accident.
- `Tableaux de bord et analytique` : les métriques en haut de cette page ne sont pas du marketing. Les comptes de tests, la couverture de langue et les budgets d'octets sortent de commandes qu'on peut relancer, et les plus importants sont verrouillés par des tests qui échouent. C'est la même discipline que je veux dans n'importe quel tableau de bord : des chiffres avec des reçus.
- `Sites web et commerce en ligne` : la vitrine, c'est le site que tu es en train de lire. Bilingue par défaut, prérendu en français et en anglais, thèmes clair et sombre, et un contrat `prefers-reduced-motion` vérifié de bout en bout. Le volet commerce en ligne de cette station se prouve plutôt sur les mandats clients.
Le métro n'est pas non plus une couche de peinture. Le chrome PROCHAIN ARRÊT, le tableau du terminus et le petit tableau des retards dans le héro lisent leurs étiquettes du même pipeline CMS que le reste du texte. Même le décor est bilingue et couvert par les tests.
Les métriques pourrissent vite sur les sites portfolio, alors voici d'où viennent les miennes. Chaque suite ci-dessous était au vert le jour où cette page a été écrite, et les comptes sortent du rapporteur de tests, pas d'une estimation.
cd apps/web && bunx vitest run # 1 871 tests, 170 fichiers
cd apps/cms && bun test # 729 tests, 69 fichiers
bun run --cwd packages/shared test # 84 tests
bun run --cwd packages/tokens test # 43 tests
cd apps/web && bunx playwright test # 424 tests e2e, 37 fichiersÇa fait 3 151 tests entre une modification de contenu et la production. La suite Playwright de bout en bout roule en trois shards en CI contre un aperçu local hermétique : pas d'URL déployée, pas de quota edge dépensé, juste le build sous test.
La promesse bilingue est un test qui échoue, pas une politique. Un marcheur d'intégrité visite chaque chaîne visible par les visiteurs dans le contenu généré et verrouille les comptes :
// apps/web/src/lib/content/integrity.test.ts
const LOCKED = { TOTAL: 650, WITH_FR: 650, NO_FR: 0, ES_WITHOUT_FR: 0 };
// 650 chaînes visibles par les visiteurs. 650 avec leur français. Zéro dette.
// Retire une traduction et la suite vire au rouge avant la poussée.Le même réflexe garde le reste du build :
- Les avertissements `svelte-check` sont verrouillés à `0`. La gate est passée de 46 à zéro sans une seule suppression, et la CI échoue si un seul repousse.
- Les schémas de contenu vivent une seule fois dans `packages/shared`, en schémas `Zod` importés par l'app web et par les scripts CMS. Les deux bouts du pipeline ne peuvent pas dériver en silence.
- Le moteur de pile interactif reste séparé du bundle principal, derrière un budget gzip épinglé à 25 Ko et remesuré après chaque build.
- Les cartes de partage OG sont frappées à partir du wordmark SVG canonique, en 1200x630, avec un budget dur de 150 Ko par carte.
- La CI est frugale exprès : déclencheurs sur PR seulement, cache distant turbo partagé, navigateurs en cache et une étiquette pour sauter les changements de docs. J'ai déjà brûlé les minutes gratuites de GitHub Actions une fois. Une seule.
Rien de tout ça n'est exotique. C'est de l'infrastructure numérique ordinaire, pointée d'abord vers mon propre site. Si tu veux savoir de quoi ça a l'air de travailler avec moi, cette page est la réponse : le pipeline qui l'a construite, c'est le pitch.
yesid.dev est le seul projet où je suis à la fois le client et l'entrepreneur. C'est un site SvelteKit bilingue, édité dans Directus, régénéré en modules TypeScript typés au moment du build, puis servi prérendu depuis l'edge Vercel avec 0 appel au CMS par visite.
C'est aussi la preuve en marche des quatre services. Le contenu vit dans une base Postgres que j'ajuste moi-même, un pipeline reconstruit le site à chaque publication, les chiffres de cette étude de cas sont mesurés plutôt qu'estimés, et la vitrine, c'est le site lui-même.
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.