Case studies johnbarbagallo.info

A portfolio that checks its own claims.

Role
Owner, director of the build
Period
2026 – present
Stack
Astro · TypeScript · Playwright · nginx

A personal site is a set of claims about a person. This one is built so every claim has a source, every release is tested on desktop and mobile before it ships, and every file that goes live is checked byte for byte.

The brief

The old site said things I could not stand behind. The brief for the new one was short: say only what can be shown, show where it comes from, and make it hard for the site to drift away from the record without someone noticing.

That turned a portfolio into a small release engineering problem. The content had to have a single source, the checks had to run on every release, and a release had to be something that could be verified and undone.

How it is built

  • Static. Astro builds plain HTML and CSS with a few small scripts for motion and navigation. There is no server-side code, database or login on the site, so there is very little to attack or keep patched.
  • One source of truth. The career record lives in one JSON file. The résumé page, the public resume.json and both PDF downloads are generated from it, and so is the email address on every page.
  • Nothing borrowed at runtime. Fonts are served from this domain and no third-party script runs. A strict Content-Security-Policy says so to the browser.
  • Evidence on the page. Each case study lists what is verified, what is pending and what is not claimed. Numbers appear only with their source.

How a release ships

  1. Build and validate. A production build is checked for leftover review notes, private names, retired claims and stray email addresses, in the pages and inside the PDFs.
  2. Test. The release candidate is tested on desktop and mobile: content, navigation, accessibility, horizontal overflow and the PDFs. RC7 passed 421 tests with none failing.
  3. Freeze. The files are tagged and written to a manifest with a SHA-256 hash for each one. The candidate is never edited after that; a fix means a new candidate.
  4. Deploy. The files are uploaded beside the live site and checked against the manifest on the server, then swapped in with a directory rename. The previous release stays on the server as the rollback.
  5. Verify. The live homepage hash is compared with the candidate’s, and a checker requests every public file once and compares it with the manifest.

Access for a deployment is a fresh key, added for that release and removed afterwards, with a check that it no longer works.

The incident

During one release check, the site was fine and the check was wrong. To confirm that a configuration file was hidden, my verifier requested it. The server’s intrusion protection treats that request as an attack, and it blocked my address for ten minutes in the middle of the check.

The fix was to the process, not the server. The public checker now never requests protected paths, and those files are verified by hash on the server instead. It makes one request at a time with a fixed budget, and it stops after three failures in a row rather than retrying. The rules are written down so the next release starts from them.

Who built it

I directed the build and own every decision on it: the brief, the content, what is claimed and what is left out, and the approval of each release. Much of the code and the test tooling was written with Claude Code, an AI coding assistant, working to that direction and through the same checks as everything else.

Evidence and limitations

What anyone can check: the site itself, its response headers, its page source, the public resume.json and both PDFs. The footer shows the release number and build date of the files you are reading.

What is from my own records: the release history, test counts and hashes come from the private repository and release notes. Server, hosting and access details are not published.