WRITING
We build in the open.
Notes on building AI-native software. What's working, what breaks, and what we're learning in production. The same thinking that goes into the products goes into the writing.
Latest
- 11 min read
Cheap code is a reason to build fewer things, not more
AI collapsed the cost of producing a surface and did nothing to the cost of reviewing one. Every architecture decision that traded build effort against surface count is now mispriced, and most teams are drawing the opposite conclusion.
- 11 min read
Progressive web apps on iPhone in 2026: what is true and what is folklore
Do PWAs work on iOS? Push has worked since 2023, the 50MB cache cap does not exist, and the seven-day eviction rule never applied to installed web apps. What is actually true in 2026, sourced to WebKit.
- 12 min read
Web app vs mobile app in 2026: what actually forces you native
Most web app vs mobile app comparisons are decision tables that avoid making a decision. Device capability is the only technical input that forces a native build. Everything else moved in 2026, and most of it moved toward the web.
AI-native, not AI-enabled
The useful question is not what AI can add to software that already exists. It's what becomes buildable that wasn't, and the answer shows up in architecture rather than in features.
- 11 min read
Cheap code is a reason to build fewer things, not more
AI collapsed the cost of producing a surface and did nothing to the cost of reviewing one. Every architecture decision that traded build effort against surface count is now mispriced, and most teams are drawing the opposite conclusion.
- 8 min read
AI homogenization is a build problem, not a philosophy problem
The strongest research on AI homogenization points at one uncomfortable risk: AI can improve individual outputs while compressing the variation across them. What that looks like inside a working product studio is four specific incidents from our last quarter, and one operating rule we changed as a result.
- 8 min read
I got tired of logging out of Claude twelve times a day, so I built Lanes
A work account and a personal account, one desktop app, and no way to run both. The fix was one command-line flag. Getting there meant finding out which AI desktop apps actually honor it, and two of the three don't.
- 5 min read
AI-native, not AI-enabled
Most "AI software" is old software with a chat box bolted on. Here's the difference between AI-native and AI-enabled, and why we started a company on the other side of it.
The last twenty percent
Software that demos and software that holds up under real users fail in different places, and the second kind of failure is rarely bad code. These posts are about the assumptions that survive review, the defaults nobody checked, and the verification work that catches both.
- 11 min read
Progressive web apps on iPhone in 2026: what is true and what is folklore
Do PWAs work on iOS? Push has worked since 2023, the 50MB cache cap does not exist, and the seven-day eviction rule never applied to installed web apps. What is actually true in 2026, sourced to WebKit.
- 12 min read
Web app vs mobile app in 2026: what actually forces you native
Most web app vs mobile app comparisons are decision tables that avoid making a decision. Device capability is the only technical input that forces a native build. Everything else moved in 2026, and most of it moved toward the web.
- 7 min read
Mobile apps didn't get an AI feature. They got a new backend.
Every post about AI and mobile is about new capability. The change that matters is about ownership: half your system now belongs to someone else and updates on their schedule. Four assumptions mobile development was built on, and what happened to each.
- 7 min read
Observability is an exfiltration surface: what our analytics collected by default
We added analytics to diagnose a slow page. Reading the raw events took ten seconds and turned into a two-hour audit, because the defaults collected far more than we'd have chosen and one masking setting covered less than its name suggests.
- 12 min read
MCP is a trust boundary you didn't know you crossed
Connecting an MCP server feels like installing a package. It's closer to creating a user account. The vendor statistics say 82% of servers are vulnerable. The one peer-reviewed measurement says 7.2%. Both sides of that gap are making the same mistake.
- 6 min read
The failure mode isn't bad code
Bad code gets caught. What doesn't get caught is plausible code with a confident summary, written by the same process that wrote the code. Four things that passed review, passed their tests, and were wrong anyway.
- 4 min read
proacl IS NULL means PUBLIC EXECUTE, not no grants
The catalog records PostgreSQL's default grant as NULL, and NULL reads as nothing, so the obvious audit comes back empty on a database full of world-callable functions. What we changed, and the rule underneath it.
- 3 min read
Our lint rule kept passing because it had stopped checking anything
A lint rule that strips string literals before matching can never see an import, because the module specifier is itself a string literal. Ours ran on every commit, passed every time, and was checking nothing. The tests that caught it were written to fail.