Enrico Icardi's personal site. Static HTML, no framework, no dependencies, no build tooling beyond Node's standard library, and a hard requirement: Lighthouse 100 in every category, on every page, mobile and desktop — enforced by the test suite and the deploy pipeline.
- One build script.
build.mjs(Node ≥ 18, built-ins only) renderscontent/<lang>.jsoninto static pages, inlines all CSS, and emitssitemap.xml(with hreflang alternates),robots.txt,llms.txt,llms-full.txt, a plain-textcv.mdper language, JSON-LD (ProfilePage/Person) and OG meta. - Nine languages. English at
/, the rest under/<lang>/. Adding a language = one JSON file + one line inORDER. - ~1 KB of JavaScript, inline. Theme (system → light → dark, applied before paint) and one-time language auto-select on
/fromnavigator.languages. No framework, no hydration, no cookies. - "One Day" blog. Each post is a folder with one complete, art-directed standalone HTML document per language, copied verbatim — every post is free to look entirely different. The index and sitemap are generated.
- LLM/GEO-ready.
llms.txt,llms-full.txt(whole site as plain text), per-languagecv.md, richPersonschema withknowsAbout/hasOccupation, and a robots.txt that welcomes AI crawlers. - Editorial type system. Serif display (Times stack, zero bytes) over Maison Neue text, four sizes total, half-line vertical rhythm, drop caps, sticky CV timeline with dates hanging in the margin on wide screens, light/dark via a single
light-dark()token set. - Cookie-less analytics. GoatCounter: one async script + a
noscriptpixel, no cookies, no consent banner needed. SetGOATCOUNTERinbuild.mjs('' disables it). - E2E = Lighthouse.
npm testbuilds, serves, and fails unless every category is 100 on a sample of pages, mobile + desktop. GitHub Actions runs it on every push and deploys to GitHub Pages only when green.
npm run dev # build + serve at :5173, rebuilds on every reload — no install needed
npm run build # one-off build to dist/
npm test # the Lighthouse gate (needs Chrome; lighthouse comes via npx)Deploy = push to main (repo Settings → Pages → Source: "GitHub Actions").
content/oneday/2026-09-14-my-slug/
it.html # a COMPLETE standalone HTML document — any design you like
en.html # optional translations, same idea
The build copies each file verbatim to /{lang}/one-day/my-slug/, lists it on the index (title from the file's <title>, date from the folder name), links untranslated languages to the Italian version, and adds it to the sitemap. Posts are not part of the Lighthouse gate — each post owns its performance.
See CHANGELOG.md for history.
Take it, gut content/*.json, put your own life in. Two things are not covered by the MIT license and you must replace them:
src/fonts/— Maison Neue is a commercial typeface by Milieu Grotesque; the subsets here are licensed for this site only.src/img/and everything undercontent/— Enrico's texts, portrait and blog posts. © Enrico Icardi, all rights reserved.
Everything else — the build script, the CSS system (tokens → base → components, four type sizes, half-line rhythm), the test gate, the workflow — is MIT. Use it however you want.