drewkhoury.com about drew
★ The Ten-Page Report · Pinned

I built this site with an AI. Here's what that was like.

"The merger of two of my sites into this one — built across a couple of weeks of conversation with Claude. Both old sites are preserved verbatim alongside this report so you can poke them yourself."

May 11, 2026

This site is new. It used to be two sites — one a Hugo blog at drewkhoury.com with a decade of essays, and one a freshly-built Astro portfolio at portfolio-drew.web.app with the experiments and tools I’d been making more recently. Both are preserved verbatim, served as static snapshots:

If you want to compare what was to what is — open those alongside this page. Before · before · after.

This report is about how the merger happened. Not the technical bits — those are in my GitHub if you want them. This is about what it was actually like to design and build a site through a long conversation with a language model.

Two sites I couldn’t quite stitch together

The two sites were doing different jobs. The Hugo one was a decade of writing — twenty-two essays, the Manager README, the eight-piece Good Software Delivery series, the public speaking. The Astro one was twelve projects and forty single-interaction experiments, with a procedural-mark logo, a Cmd+K palette, an ASCII theme, a settings cog that let you roll a new look. They felt like they were made by two different people, because in some sense they were.

I’d been sitting with the question for months: should I tie them together somehow? Two URLs to share. Two design systems. Two senses of who I am.

When I finally typed the question into Claude, the first answer back was good. Not “yes! merging is wise!” — more like, here’s the actual trade-off you’re carrying.

Two sites lets you be two things without contradiction. One site forces a coherence that maybe doesn’t exist. Is the unification valuable, or just neat?

That was the right first question. I went and thought about it.

The pattern that worked

What I noticed early — and kept noticing — is that the most useful thing Claude did wasn’t the writing or the building. It was the structured pushback. Whenever I described what I wanted, the response came back in two halves: here’s how I’d do it, and here’s where it could go wrong.

When I asked for proposals to merge the sites, the response wasn’t three variations of the same thing. It was three meaningfully different shapes — Editorial (writing leads, hire-friendly), Atelier (making leads, maker-first), and Almanac (everything in one chronological feed). Each had a paragraph on what it gained and what it gave up. The Almanac mockup came with this line:

The merger is the design.

That was the one that broke through for me. Of course — if I’d been trying to merge two voices into one, the honest thing was to acknowledge the timeline. Don’t pick a voice. Let the timeline be the voice.

I picked Almanac, and the rest of the project bent around that choice.

Decisions before code

The next thing that worked was the order of operations. Before any code got written for the real site, we built a planning page — a long interactive HTML document with eight tabs: overview, inventory, decisions, URL map, schemas, phases, mockups, risks. Every page on the old site (fifty-two of them) was catalogued. Every decision had two or three options with a recommendation marked. Every old URL had a planned destination.

I could click decisions and they persisted. I could check off phase tasks and they persisted. The plan tracked itself.

This is the part of working with a model that I keep underestimating: the willingness to build scaffolding instead of the thing. I’d say “make me a thing” and the first instinct was always to make the thing. But the better move — the one I had to ask for explicitly, sometimes more than once — was to back up and make the system that makes the thing. The inventory page wasn’t the site. It was the thing I needed to look at before I built the site. Same with the decisions tracker. Same with the URL map.

If I were going to give advice to anyone working with a model on something larger than a snippet: demand the planning artifact before the build. Make it interactive. Make it skim-able. Make it the thing you can take a week to think about.

The moment of friction

Halfway through, I broke it.

The inventory page had filter chips — click “Reports” and the page should show only reports. I clicked. Nothing happened. I said: “the pills don’t work.” Two iterations of fixes later, I said: “nope just goes to top of page?” Two more iterations later, frustrated: “rebuild the page, this isn’t working.”

The model rebuilt. Then asked me to test. I said: “you test it.”

What happened next was the most useful thing it had done all session. Instead of insisting the code was right, it installed Puppeteer, drove the page in headless Chrome, and ran forty-three assertions. Forty-three passed. It then took screenshots showing the filter visibly working.

The bug was real, by the way — not in the filter, but in me. After the click, the page scrolled to the top, and the filter bar was below the viewport. So when I scrolled up, I was looking at the (unchanged) taxonomy block, which made the page look identical. The pills were working the whole time; the scroll-to-top was hiding the proof.

This is something I want to write down clearly, because it’s true of working with models in general: the failure mode that frustrates you most is often a perceptual gap between you and the artifact, not a defect in the artifact. Tests don’t fix that gap; visual evidence does. The screenshots — not the passing tests — were what finally let me see what I’d been doing wrong.

I sat with that for a while. Felt a bit silly. Then we removed the scroll-to-top, replaced it with scroll-to-filter-bar, and moved on.

Where it earned its keep

The migration was the test. Twenty-two essays in TOML and YAML front-matter, slug structures with Medium UUIDs, dead Katacoda embeds, Hugo shortcodes, a "wow, so cool." editing artifact someone (me) left in the cost-of-failure essay seven years ago. A long tail of cleanup.

I asked for a migration script — Node, idempotent, re-runnable. It came back as a 300-line file that walks the Hugo content tree, parses both TOML and YAML front-matter (Hugo uses both, depending on the post’s age), strips known artifacts, preserves slugs verbatim so inbound links keep working, and writes everything into Astro content collections with a clean schema.

It produced twenty-seven post files and eleven talk files on the first run. Two real bugs surfaced over the next hour — both fixable from the script, both re-runnable without losing anything. The output was good enough that I read the cost-of-failure post end to end without flinching.

I want to be careful here. The script wasn’t a magical thing. It was a thing I would have written in a couple of hours myself. The compression was real but not staggering. What it bought me was an evening of design conversation that would otherwise have been an evening of typing.

What I’d do differently

A few things, honestly:

I’d lock the decisions before the build, not during. I let some choices stay open during construction because I wasn’t sure yet. That meant a few things got built twice. The plan’s decision tracker is built for this exact reason — to force the choosing up front — and I still didn’t use it that way the first time around.

I’d push back on defaults sooner. The model has good taste, but it’s still defaults. When I let it pick on something I didn’t have a strong opinion on, I usually got something fine but generic. When I challenged the default, I got something better. The Almanac concept came out of me saying “I want all three modes” — Editorial alone would have been the safer pick.

I’d plan for the boring parts. Image localization (Medium’s CDN-hosted images, mostly), redirects (sixty-something of them in firebase.json), dead-embed banners (Katacoda shut down in 2022 and three of my posts still reference it). All boring, all important. I left them as follow-ups; in hindsight I’d have insisted they happen during the main pass.

I’d publish in stages, not all at once. The merger could have shipped as just-Almanac-first, then Editorial, then Atelier added later. I built all three at once. There’s something to be said for letting visitors get used to one shape before introducing alternatives.

What I won’t take credit for

The site I’m typing this on has good bones, and I want to be clear that a lot of those bones aren’t mine. The design system — the beige #f7f5f1 background, the Geist Sans and Geist Mono pairing, the procedural marks, the ASCII mode, the Cmd+K palette — all came out of the portfolio site I was building solo before this merge. The voice — “small, careful things that change how teams work” — is mine, but the architecture that displays that voice has months of work in it that predates this conversation.

What the merge added was: a way for the writing to live next to the making without either feeling like a tenant in the other’s house.

Browse the old sites

I built this site as much for the delta as for the destination. So both old sites are preserved as wayback-style mirrors, fully browsable, no external dependencies:

They’re submodules in this site’s repo, snapshotted with wget in May 2026. If you ever wonder how I got from there to here, click through. The old DevOps essays are intact. The Manager README is intact. The procedural-mark gallery is intact. None of it left.

The plan and the inventory

If you want the build artifact rather than the essay version: the planning document I worked through is still online at drewkhoury.com/proposals/plan.html. Eight tabs. Fifty-two entries inventoried. Fourteen decisions tracked. Four phases with twenty-eight tasks. The whole thing was built before any of the real site code was, and I used it as the spec.

The inventory page — every old URL with a new destination and a per-page migration plan — is at drewkhoury.com/proposals/inventory.html. Filterable by content type. Each entry has a one-paragraph plan with a risk tag.

If you’re thinking about doing something like this — merge two sites, port content, work with a model on it for more than a single session — those artifacts may be more useful than this essay.

A footnote on the word “with”

I keep saying “I built this site with an AI” and that preposition is doing some load-bearing work. The site is mine. The decisions are mine. The voice is mine. What the model did was speed up the parts that are mechanical (parse this, migrate that, write the redirect map, build the inventory table) and occasionally surface a question I wouldn’t have asked myself — like the first time it pushed back on whether merging was even the right move.

The thing it did most of all was be patient with me thinking out loud. That’s worth a lot, and it’s the part that’s hardest to articulate to people who haven’t tried it.

If you want to talk about any of this, I’m at drew.khoury@gmail.com or via the Calendly on /about. If you want to read the work that paid for the bones of this house, the Manager README is pinned and still my favourite thing I’ve written.

— Drew