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
- 12 min read
Apple rejected 23% of App Store submissions in 2025, and most rejections cited Performance
Apple's own transparency report shows 2,093,244 of 9,100,620 App Store submissions rejected in 2025. The Performance section, home of App Completeness, was cited in 1,354,418 of them. Here is what that means before you press submit.
- 12 min read
Your app's maintenance budget is set by Apple's and Google's calendars
Most app maintenance cost pages quote a percentage nobody can source. The part of maintenance you cannot skip is published by Apple and Google as dated rules. Here is the calendar, the fees, and a rule for budgeting it.
- 11 min read
Your coding agent's hook probably checks nothing
A coding agent hook can run on every edit and still never reach the model. How Claude Code, Codex and Cursor actually deliver a hook's result, what silently does nothing, and a one-minute test that proves your hook can fail.
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
Your coding agent's hook probably checks nothing
A coding agent hook can run on every edit and still never reach the model. How Claude Code, Codex and Cursor actually deliver a hook's result, what silently does nothing, and a one-minute test that proves your hook can fail.
- 11 min read
Core Web Vitals finally see past the first page of a single-page app
Chrome 151 can now measure LCP, INP and CLS for many client-side route changes in a single-page app. CrUX, PageSpeed Insights and Google Search have not decided what to do with that yet, so your own real-user monitoring is the only place you will see it.
- 14 min read
Dependency cooldowns matter more once AI agents run npm install
A dependency cooldown tells your package manager to ignore versions younger than a set age. Several high-profile recent compromises of popular packages were pulled within hours, so a one-day window would have kept them out of any fresh install. That matters more when an agent runs the install.
- 13 min read
Your AGENTS.md costs more than it earns
Do AGENTS.md files help coding agents? In a 2026 cross-agent study, auto-generated context files raised inference cost by 20 percent or more without significantly improving task success. Much of what goes in these files is information the agent already had.
- 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.
- 12 min read
Apple rejected 23% of App Store submissions in 2025, and most rejections cited Performance
Apple's own transparency report shows 2,093,244 of 9,100,620 App Store submissions rejected in 2025. The Performance section, home of App Completeness, was cited in 1,354,418 of them. Here is what that means before you press submit.
- 12 min read
Your app's maintenance budget is set by Apple's and Google's calendars
Most app maintenance cost pages quote a percentage nobody can source. The part of maintenance you cannot skip is published by Apple and Google as dated rules. Here is the calendar, the fees, and a rule for budgeting it.
- 11 min read
A pageview in a single-page app is whatever your analytics tool decides it is
In a Next.js App Router app, no browser event says a page was viewed. GA4, PostHog, Vercel, Plausible, Umami and Cloudflare each pick their own trigger, and several of those definitions changed in 2026. What each one counts, and why the numbers will not match.
- 12 min read
A check that cannot fail tells you nothing
Tests that always pass, audits that come back empty, settings whose names promise more than they do. Every blind check we have found shared an assumption with the bug it was meant to catch, which is why review rarely catches them either.
- 6 min read
Model deprecation: why pinning an LLM snapshot sets a deadline
Pinning an LLM to a dated snapshot keeps its behavior stable, and it also leaves you with a retirement date you don't control. When the eval platform you'd use to test a replacement is retired around the same time, the migration gets harder than the pin was easy.
- 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.