Writing

Notes from building and debugging.

Debugging stories, design constraints, and the tooling decisions that were too useful to leave inside a pull request.

SVGAnimationAccessibilityTesting

The real text never moves

Four diagrams on this site now animate the mechanisms they explain. The animation is a copy drawn over the real graphic, and the original labels stay put. How that works, how it's tested, and what it costs in page speed.

Read the essay →

Archive

8 more notes

02 · Sep 24, 2026

It was the cable

I turned a ten-year-old Dell laptop into a home server running Debian, Docker Compose, Home Assistant, Uptime Kuma, Caddy, Tailscale and Paperless-ngx. Getting the services running was the easy part.

Self-HostingDockerHome Assistant

03 · Aug 25, 2026

Every fixture was one line long

A review found that the one feature my job-search tool exists for was destroying its own output. The test suite stayed green through all of it, because every fixture in it shared the assumption the bug was made of.

TestingAgents

04 · Aug 24, 2026

The edge said HIT. The browser asked anyway.

Cloudflare was caching this site's assets and reporting it on every response. The browser was still revalidating all six of them on every visit, because of a default header I had never read.

CloudflarePerformance

05 · Aug 20, 2026

What changed when an agent started using my CLI

rmine was built for two callers from the start: me at a terminal, and a coding agent. The design decisions that only make sense because of the second one.

GoAgentsDeveloper Tooling

06 · Aug 19, 2026

Three agents that don't trust each other

An effort estimator built out of three subagents. The decisions that mattered were about what to withhold from each one, not what to tell them.

AgentsEstimationClaude Code

07 · Aug 18, 2026

The sync job that took half a day

A device sync was running 12 to 15 hours against millions of software records. The fix was batching and eager loading, but the lasting part was measuring first.

Ruby on RailsPerformance

08 · Aug 17, 2026

I used it internally for two years before publishing it

bitwise_attributes packs boolean flags into one integer column. Most of what makes it a library rather than a snippet came from the gap between those two things.

RubyRailsOpen Source

09 · Aug 16, 2026

Building on a DOM that isn't mine

A 300-line Chrome extension that adds a translate button to WhatsApp Web Status. One commit fixed four bugs, and all four came from the same wrong assumption.

JavaScriptChrome Extensions

RSS →