How this site was built: a map, ten tickets, and Claude Code

The wayfinder map, the ticket loop, and what the review caught.

Start with a map

I don't type most of my code any more; I decide what gets built and check that it was built right. For this site that started as a map: one markdown file with a destination, notes, the open questions, and the research to do. The destination was a locked spec: positioning, the career story as content, page structure, a visual direction built around the TWY neon sign, the AI showcase, and the stack. Nothing left to decide before a build starts.

The map also keeps what is not decided. Hosting, metadata, analytics and the cut-over from the old site sit under “Not yet specified”, and they still do. Writing that list down is what keeps the tickets small.

Ten tickets, one at a time

Each open question became a ticket: a type (research, grilling, prototype, task), a question, and later an answer. The first two were research into things I could verify: TWY GmbH in the Swiss public records, and my own LinkedIn export. Then the current Angular setup, the old site's content, positioning, the career story, the sign, page structure, the AI showcase, and finally the stack. Ten tickets, all resolved on 14 October 2026, each closed with a one-line gist in the map.

Prototypes where a decision needs something to look at

Ticket 07 asked whether the sign is a logo, a hero, or a background. Arguing about it would have taken longer than building four switchable variants, so Claude Code built them on a branch and I looked.

“I kinda like C, but we'll need the frosted glass effect once we start scrolling.”

That verdict held for a day. The design phase that followed reopened it for performance: a full-viewport canvas plus a full-viewport backdrop blur is the costliest thing a phone can be asked to paint. The sign now owns the first viewport on desktop and is a poster everywhere else. The prototype was still worth it: the cyclorama set and the sign's settings survived from it.

Code written test-first

The build itself is plain Angular CLI, prerendered to static files, no server. Code is written test-first by Claude Code against the decisions in the tickets: a Vitest unit for the content build step, Playwright against the prerendered dist for the routes and the hero text. The search on the Writing index is a small example: the posts are a build-time constant, the query is a signal on the page, and the match list is a computed over two pure functions that have their own unit test:

src/app/pages/writing-search.ts
/** The query as it is matched: trimmed and lower-cased; '' means "no filter". */
export function normalizeQuery(query: string): string {
  return query.trim().toLowerCase();
}

/** Every post whose title or summary contains the query; all posts for an empty query. */
export function filterPosts<T extends Searchable>(posts: readonly T[], query: string): T[] {
  const q = normalizeQuery(query);
  if (!q) return [...posts];
  return posts.filter((p) => `${p.title} ${p.summary}`.toLowerCase().includes(q));
}
The two marked lines are the whole search: a trimmed, lower-cased query against title and summary.

Markdown becomes JSON before ng build. The content step runs as prebuild, so a forgotten step cannot ship a stale page:

package.json
diff --git a/package.json b/package.json
@@ -6,9 +6,12 @@
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "build": "ng build",
    "content": "node scripts/build-content.ts",
    "prebuild": "npm run content",
    "pretest": "npm run content",
    "test": "ng test",
    "e2e": "playwright test",
    "lint": "oxlint"
  },

What the review caught

Review happens twice: against the spec, and against the repo's standards. I read every diff. The design system went through the same loop, and its reviewer found thirty items, three of them blockers:

  • At 1280×800 the email button sat below the fold; the hero stage was too tall.
  • Dimmed code lines dropped comments to 2.35:1; highlighting is now a wash and a gutter marker, and nothing is dimmed.
  • Phone navigation was not specified at all; it is now two rows with a scrollable link row, no menu, no JavaScript.

Note

In my own projects this is the whole workflow. At clients I use it where the client allows.

The guardrails are the point: specs before code, tests before implementation, review before merge. The map and the ten tickets are in the public repo and rendered at How this site was built.

Stehen Sie in Ihrer Codebasis vor etwas Ähnlichem? Ich bin ab Januar 2027 frei. Schreiben Sie mir.