The blog

Building better small-business websites, out loud

Field notes, guides, and ideas on speed, AI search, design, and what actually grows a small business online.

How to move a live status field onto a new model without a big-bang migration
Field notes

How to move a live status field onto a new model without a big-bang migration

We moved lifecycle state to a new model without rewriting every query. The trick was keeping the old status column as a mirror and migrating the writers first.

Read →
Your WhatsApp ads convert where your analytics can't look
Field notes

Your WhatsApp ads convert where your analytics can't look

If your ads open a WhatsApp chat, the conversion happens off your site and won't show in standard web analytics. Here's what actually links ad spend to sales.

Read →
Your git log is already your changelog
Field notes

Your git log is already your changelog

Hand-written changelogs create merge conflicts because every branch edits the same lines. We stopped maintaining one and generate it from commit messages instead.

Read →
A "where are we" dashboard — LLM-written, served static
Field notes

A "where are we" dashboard — LLM-written, served static

A kanban tells you each card's status, not whether you're on track. We generate the board's insight offline with an LLM, commit it, and serve the dashboard static — no runtime LLM call, no API key on the box.

Read →
The AI-search advice we ignored (and what works)
Field notes

The AI-search advice we ignored (and what works)

A lot of "optimize for AI search" advice is theater. Here's what we deliberately skipped — and what actually got small-business sites cited.

Read →
We deleted our TODO file — the issue tracker is the source of truth
Field notes

We deleted our TODO file — the issue tracker is the source of truth

A hand-maintained TODOS.md always drifts from reality. So we deleted it — the issue tracker is the single source of truth, and the repo only holds views generated from it.

Read →
Running multiple AI agents on one repo? Give each its own worktree — and its own everything
Field notes

Running multiple AI agents on one repo? Give each its own worktree — and its own everything

Running several AI coding agents in one git checkout corrupts your history, collides your test databases, and tangles your branches. The fix is the same move every time — isolate the shared state — and here's every place we had to do it.

Read →
Getting your site onto your own domain
Guides

Getting your site onto your own domain

The simplest way to get your website onto yourbusiness.com — what the www version changes, the three ways to do it, and the ownership question to ask before anyone sets it up.

Read →
The hard part of retrying a dropped message is knowing when not to
Field notes

The hard part of retrying a dropped message is knowing when not to

Re-enqueueing a dropped message is easy. The real work is knowing when silence is intentional — opt-outs, human handoffs, races, and WhatsApp's 24-hour window.

Read →