Skip to content

Colophon

How this site is built — stack, architecture, caching, and security.

Tech stack

Frontend

React framework (App Router, SSR, SSG)
UI library — Server & Client Components
End-to-end static typing
Utility-first CSS, CSS-first configuration (`@theme`) — dark mode via class
Dark/light toggle with persistence

i18n

EN/FR/ES internationalisation (App Router, middleware)

Blog

Next.js MDX rendering
YAML frontmatter parsing
rehype / remark
HTML + Markdown AST transformation
Server-side syntax highlighting

Backend

Stale-while-revalidate cache + rate-limiting on write and sensitive endpoints (contact, testimonials, cache invalidation, admin, CSP reports, health) + 30-day uptime history
Email delivery for contact-form messages — EU-hosted, no server-side persistence

Deployment & Observability

Hosting — global CDN, automatic HTTPS, preview deployments

CI/CD & Quality

GitHub Actions
CI pipeline: build, lint, typecheck, unit tests, npm security audit, Playwright E2E, Lighthouse CI
Performance & accessibility budgets on every PR, blocking on regression
Automated WCAG 2.2 AA audit on 9 routes — zero tolerance for critical violations
Dependabot
Weekly npm updates (5 groups), monthly Actions — next-intl/framer-motion majors require manual review
Weekly supply chain security scoring — branch protection, SAST, dependency pinning, signed commits
Content Publish Safety
Daily check of public.projects: no project goes live without its three languages

Architecture decisions

  • →One-page landing with distinct sections for skills, experience, services, projects, and contact — anchor-based navigation.
  • →Client-side track toggle (cookie `track`): a single hero component, skills and services adapt to Salesforce or IT Ops profile.
  • →Dedicated pages for About, Certifications, and Blog — accessible via the navbar, not duplicated in the landing.
  • →Server Components by default: only interactive components (hero, theme toggle, contact form) are marked `use client`.
  • →No database reads from the client: the uptime history and the incident dashboard are read from Redis on the server. Project entries are version-controlled in `content/` and served statically.
  • →MDX Blog: articles written as `.mdx` files in `content/blog/posts/{locale}/` — statically rendered at build time, no database required.

Caching strategy

  • →Upstash Redis keeps the uptime history (one check a day, 30 days) , the admin incident dashboard, and caches the `/status` views with a 1- to 5-minute TTL.
  • →stale-while-revalidate: if data is cached, it's returned immediately while an async revalidation runs in the background.
  • →Manual invalidation: the `POST /api/cache/invalidate` endpoint (protected by secret) allows purging cache after data updates.
  • →RSS feed: `Cache-Control: public, max-age=3600, stale-while-revalidate=86400` — 1h CDN cache, revalidated every 24h.
  • →ISR (HTML pages): disabled on Vercel CDN by security design — the per-request CSP nonce (eliminating `'unsafe-inline'`) is incompatible with cached HTML.

Security

  • →Nonce-based CSP: `'unsafe-inline'` removed from `script-src`. A unique cryptographic nonce is generated per request in the proxy (`proxy.ts`) and applied to Next.js hydration scripts; scripts they load inherit trust through `'strict-dynamic'`. Any inline script without a nonce is blocked by the browser. No third-party script, style or frame is allowed: the site loads no audience-measurement tool and no external widget.
  • →HTTP headers in `next.config.mjs`: HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, extended Permissions-Policy, Cross-Origin-Opener-Policy (`same-origin`), Cross-Origin-Resource-Policy (`same-origin`), Report-To, Reporting-Endpoints. Framework fingerprinting disabled (`poweredByHeader: false`).
  • →Version-controlled project content: project entries and their assets are committed to the repo and served statically — no database is exposed for this part.
  • →Rate-limiting via Upstash Redis (sliding window) on sensitive endpoints: contact (5 req/10 min), testimonials (3 req/24h), cache invalidation (10 req/min), health check (30 req/min), CSP reports (20 req/min), admin panel (5 req/15 min — brute-force protection). If Redis is not configured in production, the limiter fails closed (all requests blocked). During a transient Redis outage, it fails open to avoid blocking legitimate users — except on `/admin`, which remains fail-closed.
  • →Honeypot fields on contact and testimonial forms — bots filling hidden fields receive a silent 200 response.
  • →Origin validation: API requests from unknown origins are rejected in production.
  • →CORS restricted: `/api/health` scoped to the site origin only — monitoring tools call server-to-server, no browser CORS needed.
  • →security.txt at `/.well-known/security.txt` (RFC 9116) — responsible disclosure contact.
  • →No secrets in `NEXT_PUBLIC_*` — all sensitive keys (Redis token, admin credentials, HMAC secrets) remain strictly server-side.
  • →External validation (neutral third parties): securityheaders.com · Mozilla Observatory — HTTP security posture verified independently from the site.

Source code

This site's repository is public — architecture, CI/CD, tests, and security are all viewable directly on GitHub.