Skip to content
Second Brain Chronicles
Go back

Twenty-Two Pages, One Evening

Twenty-Two Pages, One Evening

My family volunteers with a cat rescue here in Valencia. The rescue’s website was WordPress with a Divi theme. It worked, but updating it meant fighting a page builder that nobody enjoyed using.

The cats were already tracked in Notion. Name, age, health status, compatibility notes, photos. The database was better than the website.

So the question was: what if Notion was the website?

Before Bedtime, After Bedtime

I started the migration before putting the kids to bed — exporting the WordPress content, auditing the existing site, writing specs. Then came back to it late that evening and wanted to see how far subagent-driven development could take it. Not three pages and a deploy — a full bilingual site with dynamic content, form handling, image lightboxes, and a CMS the rescue volunteers already know how to use.

The plan: Astro for the static site, Cloudflare Pages for hosting, Notion as the content source, and n8n as the glue between everything.

I broke the work into thirteen tasks and dispatched each one to a fresh Claude Code subagent. Each agent got exactly the files it needed and nothing else.

Foundation work went first — layout, nav, shared components. Once that landed, the parallel wave launched. Adoption grid, cat detail pages, about page, contact page, adoption form wizard, Spanish translations, English translations — all building at the same time.

Two-stage review on everything. Agent builds it, I check the output, agent gets corrections if needed.

Where It Broke

The compatibility filter was the fun one. Each cat has fields like “good with dogs” and “good with kids.” In Notion, some of these were checkboxes. Others were free text. So a cat with goodWithDogs: "No" was passing the JavaScript filter — because "No" is a non-empty string, and non-empty strings are truthy.

Every cat was compatible with everything. Which would be nice, but isn’t true.

The fix was straightforward — normalize everything to actual booleans before the filter runs. But it’s the kind of bug that only shows up when real data hits the template. A checkbox false and a text field "No" look identical in Notion. They behave very differently in the DOM.

The other fight was CSS specificity. Global heading styles were stomping on page-specific overrides. Three agents independently discovered the same problem and independently solved it three different ways. I picked the cleanest one and applied it everywhere.

The Part That Matters

The whole thing took about five hours. Twenty-two pages across two languages. A five-step adoption form with webhook handling. GLightbox image galleries on every cat profile. OG tags, JSON-LD for the nonprofit, hreflang tags, a sitemap, a robots.txt.

But the number I keep thinking about is zero — how many new tools anyone at the rescue needs to learn. Update a cat’s status in Notion. An n8n workflow detects the change, triggers a Cloudflare Pages rebuild, and the site updates. Nobody opens a dashboard they don’t like.

The CMS decision mattered more than the framework decision. I could have built this in Next.js or Hugo or raw HTML. Wouldn’t have changed the volunteers’ experience at all. What changed it was pointing the build pipeline at the database they already had open every day.

Meet people where they already are — that was the whole decision.


Deployed to Cloudflare Pages. Three n8n workflows handle form submissions, deploy triggers, and Instagram feed sync. The WordPress site is still running in parallel until the rescue confirms they’re comfortable — which, given that they don’t have to do anything different, should be soon.


Share this post on:

Previous Post
The Build Is a Server
Next Post
Fixing My Town's WiFi