The blog.
Shorter posts, smaller than an Insight — things noticed in the middle of the engagement that didn't need a full essay.
The filter that silently did nothing
A tag filter that looked finished and did absolutely nothing — no error, no effect. The cause was a one-line collision between the JavaScript and the CSS.
Keep credentials in data, not config
A deploy that might invalidate your API keys is a deploy you'll hesitate to run. That hesitation is a smell — and the cause is usually that secrets live in the wrong place.
Generate your sitemap from the database, not by hand
A hand-maintained sitemap.xml is drift waiting to happen. Generate it from the same database the site renders from, and it can't fall out of sync — because it is the content.
Your tests passed; the document is still broken
Every automated check passed and the document was still visibly broken. The only thing that caught it was rendering each page to an image and looking.
Compiling isn't proof: validate state-changing SQL against the real schema
'It compiled and the first batch ran fine' is the most expensive false comfort in data work.
Your MCP server probably doesn't need its own deployment
The reflex when adding an MCP server to an existing product is to stand up a new service. Often the better answer is a route.
The silver layer is not a serving layer
A report that times out usually isn't a visuals problem - it's a grain problem.
Test the layers that pay: coverage is not a strategy
Asked to estimate 'adding unit tests' to a mature codebase, the honest answer is that the estimate is the wrong question.
Copilot Studio's sharp edges: scope claims and character budgets
Two constraints that cost real hours: the three-way OAuth scope mismatch behind most custom-connector 401s, and the hard 8,000-character ceiling on agent instructions.