Colophon
Comment ce site est construit — stack, architecture, cache et sécurité.
Stack technique
Frontend
Framework React (App Router, SSR, SSG)
Bibliothèque UI — Server & Client Components
Typage statique de bout en bout
CSS utility-first, configuration CSS-first (`@theme`) — mode sombre via class
Toggle dark/light avec persistance
i18n
Internationalisation EN/FR/ES (App Router, middleware)
Blog
Rendu MDX intégré Next.js
Parsing des frontmatter YAML
rehype / remark
Transformation AST HTML + Markdown
Coloration syntaxique côté serveur
Backend
Cache stale-while-revalidate + rate-limiting sur les endpoints d'écriture et sensibles (contact, témoignages, invalidation cache, admin, rapports CSP, health) + historique de disponibilité sur 30 jours
Acheminement par email des messages du formulaire de contact — hébergé dans l'UE, aucune persistance côté serveur
Déploiement & Observabilité
Hébergement — CDN mondial, HTTPS automatique, preview deployments
CI/CD & Qualité
GitHub Actions
Pipeline CI : build, lint, typecheck, tests unitaires, audit sécurité npm, E2E Playwright, Lighthouse CI
Budgets performance & accessibilité sur chaque PR, bloquants en cas de régression
Audit WCAG 2.2 AA automatisé sur 9 routes — zéro tolérance pour les violations critiques
Dependabot
Mises à jour npm hebdomadaires (5 groupes), Actions mensuelles — majors next-intl/framer-motion en revue manuelle
Score supply chain sécurité hebdomadaire — branch protection, SAST, dependency pinning, signed commits
Content Publish Safety
Contrôle quotidien de public.projects : aucun projet n'est publié sans ses trois langues
Décisions d'architecture
- →One-page landing avec sections distinctes pour les compétences, l'expérience, les services, les projets et le contact — navigation par ancres.
- →Track toggle côté client (cookie `track`) : un seul composant hero, compétences et services adaptés selon le profil Salesforce ou IT Ops.
- →Pages dédiées pour About, Certifications et Blog — accessibles via la navbar, non dupliquées dans la landing.
- →Server Components par défaut : seuls les composants interactifs (hero, toggle de thème, formulaire) sont marqués `use client`.
- →Aucune lecture de base de données côté client : l'historique de disponibilité et le tableau des incidents sont lus dans Redis côté serveur. Les fiches projets sont versionnées dans `content/` et servies statiquement.
- →Blog MDX : articles écrits en `.mdx` dans `content/blog/posts/{locale}/` — rendu statique au build, pas de base de données requise.
Stratégie de cache
- →Upstash Redis conserve l'historique de disponibilité (un relevé par jour, 30 jours) , le tableau des incidents de l'administration, et met en cache les vues de `/status` avec un TTL de 1 à 5 minutes.
- →stale-while-revalidate : si la donnée est en cache, elle est retournée immédiatement pendant qu'une revalidation asynchrone se déclenche en arrière-plan.
- →Invalidation manuelle : l'endpoint `POST /api/cache/invalidate` (protégé par secret) permet de purger le cache après une mise à jour des données.
- →RSS feed : `Cache-Control: public, max-age=3600, stale-while-revalidate=86400` — 1h en cache CDN, revalidé toutes les 24h.
- →ISR (pages HTML) : non activé sur Vercel CDN par choix de sécurité — le nonce CSP généré par requête (suppression de `'unsafe-inline'`) est incompatible avec un HTML mis en cache.
Sécurité
- →CSP nonce-based : `'unsafe-inline'` retiré de `script-src`. Un nonce cryptographique unique est généré par requête dans le proxy (`proxy.ts`) et appliqué aux scripts d'hydratation de Next.js ; les scripts qu'ils chargent héritent de la confiance via `'strict-dynamic'`. Tout script inline sans nonce est bloqué par le navigateur. Aucun script, style ni cadre tiers n'est autorisé : le site ne charge ni outil de mesure d'audience ni widget externe.
- →En-têtes HTTP dans `next.config.mjs` : HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy étendu, Cross-Origin-Opener-Policy (`same-origin`), Cross-Origin-Resource-Policy (`same-origin`), Report-To, Reporting-Endpoints. Fingerprinting du framework désactivé (`poweredByHeader: false`).
- →Contenu des projets versionné : les fiches projets et leurs visuels sont commités dans le dépôt et servis statiquement — aucune base de données n'est exposée pour cette partie.
- →Rate-limiting via Upstash Redis (fenêtre glissante) sur les endpoints sensibles : contact (5 req/10 min), témoignages (3 req/24h), invalidation cache (10 req/min), health check (30 req/min), rapports CSP (20 req/min), panneau admin (5 req/15 min — protection anti brute-force). Si Redis n'est pas configuré en production, le limiteur bascule en *fail-closed* (toutes les requêtes bloquées). En cas de panne transitoire de Redis, il bascule en *fail-open* pour ne pas pénaliser les utilisateurs légitimes — sauf sur `/admin` où le comportement reste *fail-closed*.
- →Honeypot : champs cachés dans les formulaires de contact et de témoignages — les bots remplissant ces champs reçoivent un 200 silencieux.
- →Validation d'origine : les requêtes API provenant d'origines inconnues sont rejetées en production.
- →CORS restreint : `/api/health` scoped à l'origine du site uniquement — les outils de monitoring opèrent en serveur-à-serveur.
- →security.txt disponible à `/.well-known/security.txt` (RFC 9116) — contact de divulgation responsable.
- →Aucun secret dans les variables `NEXT_PUBLIC_*` — toutes les clés sensibles (token Redis, identifiants admin, secrets HMAC) restent strictement côté serveur.
- →Validation externe (tiers neutres) : securityheaders.com · Mozilla Observatory — posture HTTP vérifiée indépendamment du site.
Code source
Le dépôt de ce site est public — architecture, CI/CD, tests et sécurité consultables directement sur GitHub.