Behind the scenes
This site is part of my application as much as its content is. Its code, its tests and its decisions are public: here is how it is built, and what keeps it from getting worse.
Measured just now, in your browser
These figures do not come from a lab: your browser measured them as it loaded this site.
- First contentful paint
- Measuring
- Largest contentful paint
- Measuring
- CI threshold: 2,000 ms
- Layout shift
- Measuring
- CI threshold: 0.050
- JavaScript downloaded, compressed
- Measuring
- Files requested
- Measuring
What the CI turns down
Every change goes through a pull request, and the CI blocks it if any of these checks fails.
A loose type
Strict TypeScript: no “any”, no “unknown”, no type assertion. Whatever comes from outside (address, storage, form) goes through a Zod schema.
A warning
Oxlint then type-aware ESLint, without a single warning. The feature architecture and the direction of imports are enforced by the lint.
Dead code
Knip on the whole repository, then on the shipped code alone: no unused file, export or dependency.
A regression
Unit tests in Node, components in a real Chromium, Playwright journeys on 5 devices. At least 90% of lines and 85% of branches covered.
An accessibility barrier
axe on every page, in both themes (WCAG 2.2 AA), and a Lighthouse accessibility score of 100.
Extra weight
Initial JavaScript under 125 KB and CSS under 15 KB, compressed. Lighthouse: performance of at least 95, largest paint under 2 s, blocking under 150 ms.
The decisions
35 architecture decisions, each with its context, its choice and the alternatives it turned down. Among them:
- prerender every page at build time, so the content shows without waiting for JavaScript;
- animate in native CSS, on the compositor, without a library;
- put the language in the address, one page per language;
- race the two computing cycles to scale, rather than fake a computation.