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.
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/cdkpowering the menu, listbox, dialog, and overlay primitives instead of hand-rolledkeydownglue. - Geist Sans + Geist Mono, self-hosted via
@fontsource. - A new
/consultingtree for Spike & Luna Automation Consulting LLC — warm cream + terracotta palette that doesn't bleed into the rest of the site. - A
/open-sourcepage 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/playwrightruns 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 likeworksFrinstead ofworksFor. - An
llms.txtfor AI agents, and arobots.txtwith 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-developerandangular-new-appskills — the model behaves like it has read the modern Angular docs. Signals first.inject(). New control flow (@if/@for).OnPusheverywhere. Standalone components. (I did not have to argue about any of this. Not once.) - Harness skills:
impeccablefor design craft,accessibility-auditfor a11y,auditfor technical-quality scans,donalds-decision-treefor 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:
---
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.hrefin 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-voiceskill 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.