Mark DordelGet in touch

How this site was built

The denouement

Every quest ends with a look back at the road. This is the story of how this site was built, told as its own lifecycle: the same six stages the site describes, applied to itself. The tools are on the colophon page. This page is about what happened.

The road, walked once more, from the first brief to the last watch.

232
browser test runs on every push: 116 tests, on a desktop and a phone profile
4
problems the checks caught before launch
<10 s
to build the whole site
460 KB
total weight of the built site, fonts included

The road, stage by stage

  1. Requirements

    The Council

    The brief was a résumé and one reference site. I wanted a personal site in the spirit of Keith Huster's that sells what I do for a client's development lifecycle: strategy, automation, release readiness and AI adoption. Ground rules came first. Everything comes from the résumé, no invented numbers, "seasoned" instead of a years count, and credentials live on the CV page.

    • A résumé as the single source of truth
    • Ground rules for the copy
  2. Plan and design

    Rivendell

    The idea was simple: your lifecycle is a road, and quality walks all of it. Six stages became six waypoints, dressed in a fantasy-journey theme of parchment, ink and crimson seals. I fixed about seventeen color and font tokens and checked their contrast ratios before writing any CSS. Then the stack: static Astro, content in YAML validated by schemas, layout in components.

    • Design tokens, light and dark
    • Content schemas
    • A page and component plan
  3. Build

    The Mines of Moria

    The first version was a single hand-written HTML file, which made design changes quick. Once the design settled I rebuilt it as a project. Copy moved into 18 YAML files, markup into ten components, behavior into four small scripts, and the road map became SVG drawn from the content. Fonts are installed from npm and served from the same origin.

    • 18 content files
    • 10 components and 5 pages
    • 4 small scripts
  4. Test

    The Bridge

    Nothing crosses without evidence. A strict schema rejects bad content, an HTML validator checks the output, a link checker walks every anchor, and Playwright drives the built site in a real browser with axe watching for accessibility problems, in light and dark mode, on a desktop and a phone profile. The bridge held, and it also found four things I would rather nobody saw.

    • A strict content schema
    • HTML and link checks
    • 116 browser tests on two profiles
  5. Release

    The Great River

    A change reaches the world by one route. Commit, and a local hook validates it. Push, and the browser tests run. Open a pull request, and CI runs every check plus a secret scan. Merge to main, and the exact build that passed is deployed to Cloudflare. The only secrets are the two deploy credentials, and they live in GitHub's encrypted store, never in the repository.

    • A five-job CI pipeline
    • A deploy that only runs from main
    • Secrets kept out of git
  6. Maintain

    The Watch

    The road stays open through small habits. Dependabot proposes updates weekly and CI decides whether they land. Guard tests pin the wording decisions I made on purpose, so they don't drift. Changing a role or a number is a one-file edit that the schema checks. Next on the list: a form service so messages deliver without an email app, and an image pipeline if photos arrive.

    • Weekly dependency updates
    • Guard tests for wording
    • A one-file edit for any change

What the checks caught

Text silently dropped from a YAML file

Two lines of copy contained unquoted commas inside one-line entries, so YAML split them and half the text vanished without an error. A comparison of the old and new pages spotted it. The schema is now strict, so any stray key fails the build and names the file.

Caught by a text comparison, then the strict schema.

Gold text that was too faint

The gold line on the dark AI panel measured 3.97:1 against the 4.5:1 that WCAG AA asks for. I had checked the panel color but not the slightly lighter tint under it. A lighter gold now carries text on dark panels, and the accessibility tests fail if any pairing slips.

Caught by axe accessibility checks in the browser tests.

Road map stops that were hard to click

Only the painted circle and the label responded to a click, so the space between them did nothing. The click test for each waypoint timed out. Every stop now has a full-size hit area.

Caught by the Playwright waypoint tests.

A compass rose with its top cut off

The compass behind the hero was clipped by the top edge of the section. No test noticed. I saw it the first time I looked at a real render, and moved it.

Caught by a screenshot review, by eye.

A skip link real Safari users couldn't reach

Chromium and Firefox include a plain link in the keyboard tab order by default; WebKit, the engine behind Safari, doesn't, unless a person has "Full Keyboard Access" turned on system-wide. The skip link exists specifically to be the first thing a keyboard user reaches, so on Safari it was quietly unreachable. It now carries an explicit tabindex.

Caught by the WebKit project, once it actually ran.

The end of the road, for now

The tools and the reasons for each are on the colophon page. Read the colophon.

Designed and built with Claude in a chat, over many rounds of direction and revision, then turned into this repository. The layout was inspired by keithhuster.com. Nothing here is a template.

Updated September 21, 2026

Want to talk about your SDLC?

Get in touch