← All case studies
case study

Building This Site With Claude

Turning a hand-duplicated static site into a real component system, implemented directly with Claude Code.
Org
Personal project — this site
Role
Design engineer — design, architecture, and build
Timeline
Sept 2026, ongoing
Design Engineering
Design Systems
Astro
Vercel
AI-Assisted Development
Component Architecture
Problem

A static HTML site with nav and footer hand-copy-pasted onto every page, no shared components, drifting design tokens, and a contact form with no backend.

Solution

A componentized Astro rebuild — shared design-token package, real Astro components, case studies as a content collection, a working PHP contact handler — built working directly with Claude Code as the implementation partner.

Impact

Repeated markup collapsed into single components; adding a case study is now a markdown file, not a hand-built page; the contact form actually sends mail; the same token system is packaged for reuse on future sites.

Why This Case Study Exists

The site you’re reading this on is the evidence. I made every design and architecture decision here, and then built it — not by writing a spec and handing it off, but working directly in the terminal with Claude Code, reviewing every diff before it shipped. Astro is the framework, Claude Code was the implementation partner, Vercel is part of the toolchain. If “design engineer” means owning both the interface decision and the component that ships it, this is that loop, end to end.

The Starting Point

The outgoing build was static, framework-free HTML: no templating, no shared partials. Nav and footer were hand-duplicated inline across every page. tokens.css held the design tokens, but layout was one-off inline styles per file. The contact form had no backend. Case-study cross-references were plain text, not links. It worked, but every new page meant copying markup and hoping I hadn’t drifted from the last copy.

What I Decided to Build

  • A shared design-token package, not a copy-pasted stylesheet. pigeon-design-system now holds the tokens, base CSS, and most components (Nav, Footer, CaseStudyCard, PillTag, ContactForm, TableOfContents), linked into this repo as a file: dependency. This site’s Layout.astro is a thin wrapper around the package’s layout — it hardcodes this site’s nav items and footer links, everything else comes from the shared package. The point: the next site I build on this visual system installs a dependency instead of re-copying CSS.
  • Case studies as a content collection, not hand-written pages. src/content/case-studies/*.md feeds a single [slug].astro template through getStaticPaths. Adding a case study is now adding a markdown file with the right frontmatter — including this one.
  • A real contact-form backend. ContactForm.astro posts to a plain-PHP handler that Dreamhost executes natively, closing a gap the static build never solved.
  • Static output, deliberately. Dreamhost is plain file hosting, so astro.config.mjs sets output: 'static' and trailingSlash: 'always' to match Apache’s directory-index behavior — no serverless or edge adapter, because there’s no server to run one on.

Working With Claude Code

I set the constraints — keep the Pigeon visual system pixel-for-pixel, extract the tokens into something reusable, match Dreamhost’s static-hosting behavior — and Claude Code wrote the .astro components, the content schema, and the layout wiring against them. I reviewed every diff, same as I’d review a pull request from an engineer.

It wasn’t all prompting and accepting. When the shared package caused a broken CI build, the fix was vendoring pigeon-design-system as a git submodule so the build pipeline could actually resolve it — a real infrastructure problem, not a copy-editing pass. That’s the difference between “asked an AI to build a website” and design engineering: the AI is fast at producing code, but deciding what’s broken, why, and what the correct fix is is still the job.

What I’d Call This

Not a UX generalist gesturing at code, and not an engineer executing someone else’s Figma file — the same person owning the design decision and the component that ships it. Claude Code did a lot of the typing, which shortened the loop between “I want this pattern” and “this pattern exists, componentized, in the browser” to something much closer to real time than a Figma-to-handoff cycle ever was.

Reflection

This is still in progress, on purpose — I’m writing this case study before the rebuild is even committed to git, because the process is the point, not just the finished artifact. What’s left: cutting over from the static build, reconciling the case-study meta row to a consistent Role / Timeline / Team / Tools order, and turning the remaining plain-text cross-references into real links. None of that changes the argument this case study is making.