Skip to content

How this site is built

This site runs on explicit agent contracts. Every change to copy, content, or code moves through a small named task with its own context, its allowed paths, and its gates. Language models help inside scheduled automation loops, never inside the production build, and their output reaches the site only after a reviewed pull request. What follows is the real machinery, in the order a change travels through it.

Principles

Smallest sufficient context

I give each task the least context it needs, generated from the manifest, so a run reasons over a few files instead of the whole repository.

A deterministic build

The production build never calls a model. The same input always produces the same output, so a deploy is reproducible and free of surprises.

Generation is a proposal

Model-written copy is a draft, not a commit. The deterministic gates decide whether it ships, and a human reviews it in a pull request first.

The gates decide the merge

An automation pull request merges only with every deterministic gate green, and only while the auto-merge switch is on. Whatever a gate flags — a judge-flagged article, a rescue fix — stops at a labelled PR and waits for me.

One voice, two languages

Everything I publish stays in the first person, and English and Italian ship together. A parity check fails the build when one language falls behind.

Workflows

The eight workflows a change can travel through, from contract to production deploy.

01

Agent contracts

A manifest, a set of roles, and one file per task define who does what, where they may write, and when they must stop.

  1. The manifest lists the stack, the source ownership, the roles, the tasks, and the gates in one place.
  2. Each task names its allowed paths, its commands, and the conditions that stop the run.
  3. A check validates the manifest, the roles, the tasks, and the brand rules before any work begins.
npm run agent:checknpm run agent:context

02

Copy and tone of voice

Deterministic linting keeps the writing in my voice; an optional model pass humanizes drafts, and the gates decide what stays.

  1. The copy check runs one-pattern rules plus a density-weighted anti-slop audit across English and Italian.
  2. A fix step applies the safe, deterministic replacements without touching meaning.
  3. An AI review lets a model propose rewrites; copy-lint, frontmatter, and parity choose whether to keep them.
npm run copy:checknpm run copy:ai-review -- --changed --write

03

Full automation loops

Scheduled GitHub Actions jobs refresh content, draft articles, and propose SEO changes. They open pull requests — never direct commits to main.

  1. The weekly refresh translates missing articles, fills Italian UI keys, generates grounded FAQ and takeaways, humanizes drafts, rebuilds feeds, and runs content health on the built site.
  2. Monthly loops draft one grounded article behind originality gates and an advisory judge, and turn Search Console demand into SEO meta proposals plus topic-gap briefs.
  3. A showcase loop proposes case studies from public repositories, and merges one only with every gate green; CI rescue attempts fixes on ci-failure issues with Codex and never merges its own work.
  4. Automation pushes through a GitHub App token so Flash CI runs on the PR; dirty runs get needs-human, and every automation PR carries needs-translation-review.
npm run content:mapnpm run copy:ai-review:full -- --writenpm run article:judge

04

Publication pipeline

Archived software releases live in a separate repository. The site consumes Zenodo concept DOIs through a registry, sync script, and drift gate — never auto-updated in build.

  1. The software repo publishes a GitHub release, reserves a new Zenodo version DOI, and syncs CITATION.cff from release.toml.
  2. publications.json is the site registry: concept DOI for public copy, version DOI and publishedVersion for drift checks.
  3. publication:sync refreshes the registry from Zenodo and GitHub, propagates concept DOIs into catalog and project copy, and regenerates landing JSON-LD.
  4. publication:check fails CI when github-stats, consumer files, or Zenodo metadata drift; a human reviews the PR before merge.
npm run publication:syncnpm run publication:check

05

SEO and GEO

The sitemap, the llms.txt index, and the structured data all derive from one route table, so the machine-readable surface never drifts from the site.

  1. Static routes live in a single shared list that feeds both the sitemap and the llms.txt index.
  2. Every page carries JSON-LD: a person, the breadcrumb trail, and a type that fits the page.
  3. A Search Console loop and a topic-gap report point me at what to write next; a manual GEO baseline tracks mentions and citations in AI answers.
npm run seo:checknpm run topic:gap

06

Quality gates

One command runs the full pre-merge gate: types, lint, format, tests, content health, parity, and generated-output drift.

  1. The quality check is the local equivalent of the gate that CI runs on every change.
  2. Generated files are regenerated and compared, so stale output fails the build instead of slipping through.
  3. A governance check guards the public docs against claims I no longer make.
npm run quality:check

07

Deterministic build

The production build is pure: it prerenders every route, writes markdown mirrors for readers and models, and calls no external model.

  1. Vite builds the app, then a prerender step writes static HTML for each localized route.
  2. Markdown mirrors of each article ship next to the HTML for machine readers.
  3. The container serves the result; nothing on this path depends on an API key.
npm run build

08

CI and deploy

Flash CI builds the site, scans rendered pages, and runs browser checks; a green main run triggers a supersede-safe deploy to production.

  1. After the pre-merge gates pass, CI runs a production build, content:scan on dist/, and a bundle-size budget check.
  2. A separate browser job downloads that build and runs contrast and visual-regression checks before merge is allowed.
  3. Deploy follows a successful Flash CI run on main, pushes arm64 images to GHCR, and verifies production serves the new commit.
npm run buildnpm run content:scannpm run perf:budget

Quality gates

Every change clears the pre-merge gates before merge. Flash CI repeats the same set, then runs post-build checks on the downloaded dist/.

Pre-merge

Agent contractsagent:checkFrontmattervalidateRead timereadtime:checkOG assetsog:checkEN/IT parityi18n:check:strictArticle structurei18n:articlesTone of voicecopy:checkContent healthcontent:healthPublication driftpublication:checkShowcase schemashowcase:checkGenerated driftgenerated:checkSEOseo:checkSEO ledgerseo:ledger:checkGovernancegovernance:checkTypestypecheckLintlintCSS lintlint:cssWorkflow lintlint:actionsFormatformat:checkTeststest:run

Post-build (CI)

Rendered page scancontent:scanBundle budgetperf:budgetContrast + visual regressionbrowser checks

Have a project in mind?

Tell me about the operational problem you want to solve. A few lines about the context and the systems involved are enough for a first assessment.

Write me a few lines about your project