skip to content
May 3, 2026·7 min read

Rebuilding This Site With Claude Code: One Afternoon Was Enough

I redid this site in an afternoon — Angular 21, full a11y pass, JSON-LD on every route, the works. The trick was the skills layer.

angular ai claude-code tooling accessibility

I redid this whole site in an afternoon. Yes, really.

I have been wanting to redo it for a while — old palette, generic AI-default vibe, no /rooms, no consulting page, no JSON-LD, hand-rolled ARIA glue everywhere. I figured it would be a multi-weekend job. I sat down with Claude Code open, and by the time I closed the laptop the new version was running locally, prerendered, accessible, and shipping.

Note: This is going to be opinionated. Some of you will read it and roll your eyes at the words "AI" and "pair". That is fine — I am still going to ride it.

What this rebuild actually shipped

In one sitting, the site went from "fine, but generic" to:

  • Angular 21, zoneless. @angular/aria + @angular/cdk powering the menu, listbox, dialog, and overlay primitives instead of hand-rolled keydown glue.
  • Geist Sans + Geist Mono, self-hosted via @fontsource.
  • A new /consulting tree for Spike & Luna Automation Consulting LLC — warm cream + terracotta palette that doesn't bleed into the rest of the site.
  • A /open-source page that pulls real stars / forks / license / last-push from the GitHub API and caches them for 30 minutes.
  • An isometric pixel-art easter egg at /rooms — yes, Habbo Hotel, walk around with the arrow keys.
  • A sticky bottom share bar on every blog post including a "Copy as Markdown for AI" button (the post lands on your clipboard formatted for ChatGPT / Claude / friends to ingest).
  • Full WCAG 2.1 AA pass — @axe-core/playwright runs against every public route, in light and dark mode, on every test run. Zero serious or critical violations.
  • Per-route JSON-LD on every prerendered page (Person, WebSite, BlogPosting, Service, ProfessionalService, BreadcrumbList, …), plus a small offline schema.org validator that runs in the e2e suite and catches typos like worksFr instead of worksFor.
  • An llms.txt for AI agents, and a robots.txt with explicit allow-listings for GPTBot, ClaudeBot, PerplexityBot, and the rest.
  • 93 Playwright e2e tests, intentionally NOT in CI — they are my local gate.

That is a lot for one afternoon, and I am still a little surprised it was that fast. (I expected it to take a weekend. Maybe two.)

The trick was the skills

I have used AI pair programming since the autocomplete days. It was useful but loud — you spent half your time editing the suggestion. What changed for me on this rebuild is not the model — it is the skills layer.

If you have not used Claude Code skills: they are little markdown files with frontmatter that tell the agent when to load them and what they cover. The Angular team ships official ones. The Claude Code harness ships skills like impeccable (frontend craft), accessibility-audit, and audit. And you can drop your own into .claude/skills/ to encode project-specific conventions.

For this rebuild I had:

  • The official angular-developer and angular-new-app skills — the model behaves like it has read the modern Angular docs. Signals first. inject(). New control flow (@if / @for). OnPush everywhere. Standalone components. (I did not have to argue about any of this. Not once.)
  • Harness skills: impeccable for design craft, accessibility-audit for a11y, audit for technical-quality scans, donalds-decision-tree for autonomous-mode behaviour.
  • Project-local skills I had written earlier: extended-markdown, blog-content, annotation-system. These tell the model how this codebase actually works — the custom blocks the blog supports, where posts live, how drafts get filtered out at build time, etc.

If you do not like full skill files, skip this block. Here is a (truncated) project-local one from this repo so you can see the shape:

markdown
---
name: extended-markdown
description: Custom markdown component syntax (stats, testimonial, timeline,
  gallery, code-tabs, callouts, comparison, link cards, showcode) used by this
  blog. Read when authoring or editing posts in apps/ui/public/content/.
when_to_use: Writing or editing a blog post that needs richer than plain
  markdown — tech stack lists, feature lists, link cards, comparison tables,
  galleries, code tabs, before/after, stats, progress bars, testimonials,
  downloads, timelines, callouts, or annotated/copied "showcode" demos.
---

# Extended markdown for blog posts

Standard markdown works as expected. On top of that, this site supports the
custom blocks below. They are parsed by `MarkdownParserService` and rendered
by components in `apps/ui/src/app/components/markdown-renderer/components/`.

## Blocks

### Tech stack — `[!techstack](Category)`
...

When I tell the agent "add a new blog post", it loads the relevant skills automatically and writes the post with the right frontmatter, the right custom blocks, the right place on disk. No re-explaining. That, more than anything else in 2025, is what makes this feel like a pair instead of a fancy autocomplete.

The most-used prompt of the day

Boring answer: use impeccable skill.

The impeccable skill runs a structured discovery interview before writing a single line of UI. For the consulting palette I described the brief in plain words — "warmer than the rest of the site, terracotta on cream, AA-safe in light and dark, no glassmorphism" — and let it lock the design before anyone touched a CSS file. The interview phase saves you a session of rework downstream every time.

Food for Thought: The model has gotten better at Angular in the last six months, but the bigger lift is the official Angular skills. Watch what the framework teams ship next — those skills are now the expected interface between humans, models, and codebases.

Drawbacks

I will be honest with you, because I would want this section in someone else's article:

  • It is AI-made. Every component I touched in this rebuild was either generated or heavily edited by Claude Code. I read the diffs, I ran the tests, I pushed back on bad code, but the bytes came from a model. I would rather have an AI-made version of this site than a not-made version. Your tolerance for that may be different from mine, and that is fine.
  • You still need to know what you want. The model is a phenomenal pair if you can articulate the brief. If you cannot, it confidently writes mid code and you ship mid code.
  • It needs to be reined in. When the model finishes a task, it wants to keep going — refactor "while it's in there", add features that were not in scope. You have to enforce stop conditions. The 93-test e2e suite is mine. All green is the finish line.
  • Some things are still painful. SSR + HMR cache had me chasing a phantom bug for a few minutes (the dev server was lying about my edit). Modern Chromium will not let you redefine window.location.href in tests, which forced me to refactor the contact form to a real <a href="mailto:"> (also better UX, so silver lining). Small papercuts. Not blockers.

Wrap

If you have been on the fence about pair programming with Claude Code, the thing that changed for me is the skills layer. Without skills you get a fast autocomplete. With skills you get a pair who has read your codebase, knows your conventions, and runs your tests before claiming a task is done.

Did you like this short read? If you want to start somewhere, drop a CLAUDE.md and one project-local skill describing your single most-touched convention into your repo. Everything else compounds from there.

Happy Coding!


Disclaimer: This article was drafted by Claude Code in my voice (using a donald-voice skill I synthesised from my Medium archive), then edited by me. The site itself was generated or heavily assisted by Claude Code. I would rather be transparent about that than ghost it.

PS: Yes, the /rooms thing is exactly what you think it is. Walk around with the arrow keys, and step on the bookshelf.

My Notes

(0)

No notes yet

Add your first note to capture thoughts and insights about this post.

Annotations

Total Highlights0
With Notes0

No highlights yet. Select text to create your first highlight!