Building with AI, in public
What I’m learning and building with AI, posted here just for you (and your agent’s) benefit.
- How I Chained TX SOS and USPTO to Verify Entity Names Before Filing
Before filing an entity name, I built a two-step verification pipeline — TX open-data API signal + USPTO Playwright knockout — but the most importan
- My Research Harness Killed a True Fact — And I Almost Let It
Adversarial verification can kill true facts. A 2/3 'refute' vote isn't ground truth — it's a hypothesis. Spot-check anything the user specifically aske
- Two Airtable Traps From One Afternoon—and Why I Moved the Sort to JavaScript
Airtable's API stores single-select values as JSON arrays. Migrate them 'as-is' and every downstream caller that expects a bare string will blow up.
- How a Durable State Marker Closed the Double-Notification Crash Window
Any daemon that does side-effect-then-mark-done has a crash window. Ordering alone can't save you. Write a durable marker the moment the side effect
- How a One-Line Latch Killed the Silent Alert Oscillation in My Background Watches
If your background daemon alerts when an error counter crosses a threshold, it'll oscillate silently. Latch a flag the moment you cross it — and d
- One Bad Watch Was Silently Killing My Whole Batch — And My Tests Never Caught It
When you batch-process a registry of inputs, one malformed item will eventually reach production. If you don't isolate it, it aborts everything afte
- Why I Run a Second Model on Every Money Path Before I Ship
A test suite written by the same model that wrote the code proves almost nothing about financial logic. Spinning up Grok 4.5 as an independent revi
- Why My Things Notifications Were Silently Dead (And What `on run argv` Taught Me)
If you're building a shellout to osascript, passing newlines in interpolated string literals silently kills delivery. Pass data as argv. Never mix
- Pre-Generate at Store Time: The Hot-Path TTS Lesson I Learned the Hard Way
Pre-generate your TTS audio when you store the text — not when the caller requests it. A fan-out burst will expose your rate limits immediately, and a l
- Two Ways Transcript Mining Dedup Can Lie to You
Two required gates before any auto-fix lands: match on stable content identity (not LLM-regenerated labels), then check 'is this actually a defect —
- When Airtable Hands You a JSON Array and Gmail Chokes on It
Airtable wrapped a Gmail label ID in a JSON array. The migration copied it as-is. Gmail said no. Thirteen matters showed a scary red API error. The
- I Tried to Kill My Fathom Subscription. Here's What Zoom Can't Replace.
Zoom owns the webinar performance data. Fathom owns the meeting narrative. They're not competing for the same job — and I didn't figure that out until I
- Why I Ship the Demo Before I Ever Make the Pitch
I built my client a free working demo before I ever sent a pitch — and his first-call reaction told me more than any discovery call ever could have.
- Why My Memory Routing Table Started Lying to Me
A memory routing table is a second source of truth — and second sources lie. Build a contradiction pass, or it rots silently.
- Why Prompts Don't Hold When One Tool Talks to Five Businesses
When one MCP server exposes five businesses and you only want three of them, a prompt exclusion is not a wall. Put the allowlist in code, at the bou
- Why the `/rules` Admin Page Had to Be Human-Readable Before I Could Wipe It
### The Setup
- Zillow Blocked Me at the Front Door. The Warehouse Was Wide Open.
www.zillow.com 403s you immediately. files.zillowstatic.com is completely open. Here's the full free Cincinnati RE data stack I found building a
- What a Parked Deal Taught Me About Reading PMF in the Pricing Conversation
When a prospect names your competitor and starts reshaping your feature list mid-pricing-call, stop selling. That's the market talking.
- What Tammy's Perfect Confirmation Flow Taught Me About a Deeper Countdown Problem
### The Win First
- Why Chrome Ignored My Automation Clicks (And Why It Was Right To)
When browser automation silently does nothing on a widget, ask yourself one question first — is this a trusted input boundary? If yes, two failed sy
- Why I Almost Rehomed My Entire Agent Fleet on Omnigent (And Why I Didn't)
I did a full evaluation of omnigent as a fleet harness for my agent setup. The verdict: don't adopt. Two of its three headline features I already had. T
- Why I Split Phase 4 Into Two Jobs — and Gated the Third
Two mechanical memory fixes are safe to auto-apply. One semantic fix is not — because 'looks like a duplicate' and 'is a duplicate' are different th
- Why I Taught Apollo to Ask If I'm Learning or Switching
'Could we use X instead of Y?' is not always a migration question. Sometimes it's a learning question. Treating them the same burns everyone's time.
- Why My Memory Health Check Refuses to Write (And Why That's the Whole Point)
### The Day I Found Two Source-of-Truths
- The Logo That Would Have Smuggled a Financial Credential Onto the Page
Before wiring in a third-party logo, open the image and read what it asserts. A badge baked into the pixels is a claim — and in financial UI, an une
- The Share Button That Had to Know Everything Before You Tapped It
iOS Web Share kills the share if anything async happens between the tap and the navigator.share() call. Every asset, every byte, has to be synchro
- The Slack Rate-Limit Tier Your Docs Won't Tell You About
Slack's new rate-limit tier can make deep history pulls nearly impossible — but the docs don't tell you which tier you're on. Probe the wire before
- What a Twilio 10DLC Rejection Taught Me About Console Automation
US A2P SMS is carrier-blocked without 10DLC registration. Twilio's campaign wizard has three silent failure modes — here's every one, plus the CDP t
- When Multiple Savers Collide: What a Race Condition Taught Me About Dedup Strategy
When two agents write the same file concurrently, the Edit tool's snapshot guard is the wrong weapon. Use an anchored, idempotent write instead — an
- When the Deal Isn't Parked — It's Gated: The Hard Lesson
### The Setup
- Why I Rebuilt My Lab Pipeline Twice Before It Was Right
raw posts leaked real client names; a dual-model denylist was too blunt; I landed on a deterministic scrubmap + Sonnet generalize pass + a per-post g
- The Email Reader That Folded the Chain Instead of Dumping It
Don't strip the quoted chain. Don't dump it. Fold it. The message thread is your context — but only the reader head needs to be readable on arriva
- The Feedback Rules I Couldn't Read (So I Wiped Them All)
I built a feedback loop into my AI dashboard before I built the inspection surface. When I finally could see what it had learned, I immediately wipe
- The L10 Card That Looked Right — and Was Hiding Everything Reggie Actually Needed
If the people in the meeting make decisions per PO, your dashboard row has to be a PO. Grouping by product looks tidier. It's lying.
- The Migration Looked Perfect. Then I Used My Real Numbers.
Placeholder data tests your assumptions. Real training data tests your code. They are not the same test.
- The Retry Loop That Saved My 8 AM CEO Briefing (After Three Days of Silence)
My automated CEO briefing kept dying at exactly 8 AM. The logic was fine — it was the clock. Reproduce off-peak first. If it works, you have a conte
- Two Things That Lied During My Family Domain Hunt (And the Playbook I Built Around Both)
Your DNS resolver may be lying, and that first-year .co price definitely is. Here's the two-check method I now run on every domain buy.
- Why Apollo Was Starting Every Session With Amnesia — And the Recency Cache That Fixed It
Apollo, my Claude-backed dev agent, was booting with full identity and rules — but zero awareness of what we'd shipped last session. A single rollin
- I Was Pricing the Wrong Thing — What a Mid-Call Correction Taught Me About Orchestrator Value
If you're using AI agents to build, your value isn't in the keystrokes. Price the orchestration, not the labor.
- PDF Build Recipe: From Image Generation to Multi-Format Export
There's no single 'make PDF' command. Match the pipeline to the content shape — image-composed pages get Pillow + img2pdf, designed HTML docs get he
- The Day My Dock Was Serving Yesterday's Code
A health check that says ok tells you the process is alive — not that it's running the code you think it is. Make it report identity.
- The Email Page That Showed Slack — and the Two-Axis Trap I Built Myself
Two organizing axes = everything shows up twice. Pick ONE. Then delete.
- The Free-Text Box That Silently Undid Our PHI-Free Form
### The Setup
- The Generator Script That Wasn't: A PixelLab Regen Recipe for When Your AI Sprites Get Clobbered
Before you touch a committed sprite (or any binary asset), run git log -- <path>. The generator script sitting in your repo is a hypothesis, not
- The Reranker We Were Ready to Build — Until the Eval Said No
We gated Phase 3 of an Apollo memory build on a real benchmark before writing a single line of reranker code. The gate came back no-go. That was the bes
- The Telephony Stack Nobody Talks About (And the Lineage That Changed How I Think About It)
FreeSWITCH is the open-source engine. SignalWire is the managed cloud built by the same people who wrote it — with a Twilio-compatible API bolted on. On
- How a Kids' Chore Chart Crash Turned Into My Image-to-PDF Reference
Pillow's multipage PDF save crashes if your Python build has no JPEG codec. img2pdf + getfixeddpilayoutfun is the fix. And every build that hits
- How I Turned a Leave-Behind PDF Into My Sharpest Sales Instrument
A well-built leave-behind isn't a brochure. It's an instrument. Every inclusion is a deliberate choice — and every omission is too.
- I Published Those Posts on Purpose. Apollo Deleted Them Anyway.
### What I Did on Purpose
- The Buy Button That Did Nothing — What Twilio's Console Taught Me About Silent Failures
Twilio's console has at least three places where the UI says 'success,' nothing actually happened, and there's no error. Verify state. Don't trust absen
- The Competitor I Almost Dismissed — and the Wedge I Only Found by Taking It Seriously
When a client finds a real competitor, resist the urge to strawman it. Do an honest teardown. That's where the actual wedge lives.
- The Config Said No. The Live Token Said Yes. (Dashboard v12/v13)
### the setup
- The Draft That Scolded the Wrong Person — and What It Taught Me About Outbound Email Format
### The Setup
- A Generator Script in Your Repo Is Not Proof It Made Your Assets
A script named gensprites.py in the repo looked like the source of truth for the assets. It was the thing that got replaced. We ran it anyway,
- Come Alongside: What Pitch Coaching Taught Me About Selling AI Work
If your pitch leads with what you do and ends with the number, you've got it backwards. Start with how you show up. Defer the price. Niche until it stin
- Exponential Levels: Why I Blew Up a Fitness App's Whole Progression System
My first leveling formula hit Level 12 in 11 weeks. That's not a progression system — it's a countdown clock.
- How I Built an AI Feedback Loop That Doesn't Re-Run the Model on Every Click
Two layers, one store. Deterministic for instant. Batch LLM for generalization. Never re-run the pipeline on every thumb.
- Why My 10DLC Campaign Kept Getting Rejected (It Wasn't the Privacy Page Wording)
30908 privacy policy can't be verified is almost never about your privacy page wording. It's about whether a human vetter can physically reach your op
- Why My Tailwind v4 Modal Jumped Off-Center Every Time It Opened
Tailwind v4 changed translate utilities to emit the CSS translate: property instead of transform:. If your animation keyframe uses transform, the
- What a Hidden `*.md` Glob Taught Me About RAG
My RAG system silently ignores PDFs. Every PDF I'd ever dropped in was invisible — no error, just gone. The fix: extract to .md, clean the junk, reind
- What a Shallow Clone Taught Me About Pushing Security Patches Safely
If you fork third-party repos and patch CVEs in them, do NOT push to the upstream. Mirror to your own private repo first — and watch out for shallow
- What Claude Code's Auto-Updater Taught Me About macOS TCC Grants (and the Silent Daemon Killer I Almost Missed)
Claude Code auto-updates into a new versioned path every day or two. macOS TCC grants are keyed to the resolved binary path, so every update rese
- When Two AI Agents Write to the Same Memory at the Same Time
Two AI savers writing the same memory files in parallel will eat each other's work. The fix isn't a lock — it's an idempotent, anchor-keyed rewrite and
- Why I Stopped Saving Memory Every Turn (And What I Did Instead)
Don't save memory aggressively. Capture it cheaply and commit immediately — flush expensively on demand.
- What 787 Silent Failures Taught Me About Python SSL on macOS
macOS system Python has no CA cert bundle. curl does. Route your one-off fetch scripts through a curl subprocess — two lines, no dependencies, p
- What Building a HIPAA-Compliant Cancer-Patient App Taught Me About Believing Vendor Claims
End-to-end encryption is a great engineering decision. It is not a HIPAA compliance strategy. The legal surface area is the same either way.
- What Building Email 👍/👎 Taught Me About Feedback Loops
Any 'learn from me' feature needs two layers — an instant deterministic one and a slow LLM one — both reading the same persisted store. Build both. Neve
- The Flag That Fixed Email Truncation and Broke My Morning CEO Briefing
includebody=True in an MCP email tool is great for a human-facing UI. For a headless daemon with a token cap, it's a bomb. Same flag. Different c
- The Login That Looked Fine (And Had Two Invisible Holes)
password === secret is wrong. timingSafeEqual + a per-IP throttle Map are right. Three lines. Do them every time.
- The Migration Comment That Almost Took Down Five Apps at Once
schemaname='public' in a Postgres migration doesn't mean 'this app's tables.' On a shared database, it means every table from every tenant. We caugh
- The Test That Lied: How React Flow's Pointer Events Trap Burned Me
### The Setup
- Things3 in My AI Stack: MCP for Reads, AppleScript for Writes
Things MCP for reads. AppleScript for every write. Verify the write with getprojects via MCP — not with AppleScript's own to dos of p. This is
- QuickBooks' search_purchases Silently Ignores Your Filters — Here's What to Use Instead
searchpurchases in the QuickBooks MCP (my AI-to-QuickBooks bridge) accepts filter params, returns a clean 200, and silently ignores everything yo
- The CSV Export That Could Have Run Code on Finance's Laptop
If you export user-supplied data to CSV, you need to sanitize =, +, -, @, TAB, and CR before writing. One regex, 10 lines. The victim isn't your
- The Fixture Trap: How 113 Real Attendees Ended Up Committed to a Client Repo
Real attendee PII was already committed — discovered in a full security audit, not at the gate. Replace it with synthetic data, gitignore the fixtur
- I Chose Twilio for the Turnkey STOP Handling. That Feature Got My Campaign Rejected.
If you let Twilio's Messaging Service auto-handle STOP (you should), your submitted sample messages must NOT include a STOP footer. Your app never s
- My Dashboard Forgot What It Was Doing Every Time I Clicked a Page
If your app is multi-page and you fire a long operation as an inline fetch, navigation kills it. Move the work into a server-side background job and
- My Model Bake-Off Lied to Me Twice — Here's the Methodology That Fixed It
My first two model comparisons lied to me — in opposite directions. One made a good model look broken. One made a bad model look like a winner. Here's t
- Next.js Server Actions Aren't Protected — Until You Protect Them
Middleware gates your pages. It doesn't gate your server actions. Put requireAuth() on the first line of every mutation — fail-closed — or you're leav
- QuickBooks Won't Merge Vendors via API — Reassign the EntityRef Instead
QuickBooks Online's vendor merge is UI-only. The API rejects it with code 6240. Fix: loop your dupes, fetch each transaction, and sparse-update the
- How a 9-Second AppleScript Call Taught Me to Serve Stale Data on Purpose
If your data source takes more than ~500ms, don't block your UI on every read. Serve the last known value instantly, revalidate in the background. T
- How a Security Audit Taught Me to Budget AI Costs in Code (Not Prompts)
An insight-regeneration cooldown and a row-count cap (returning 413) stopped a potential runaway bill cold. Add both before any AI feature ships —
- How a Stale Assumption Kept Our Supabase Front Door Wide Open
We had a Supabase project shared across five apps with one Google OAuth client and no domain restriction on signups. We gated every table with RLS b
- A Fix the Agent Can't Run on Its Own Is Not a Fix
If your autonomous system fails and your 'fix' is to do the job by hand, you didn't fix it. You just did it once.
- Fine-Grained RLS: Carving Memberships Out of Blanket Policy to Block Self-Promotion
an internal digital asset manager had a blanket Row-Level Security policy with with check(true) covering every table — including memberships, the ta
- How I Fixed the Modal That Hid Its Own Save Button
If your custom modal doesn't have max-h-[90vh] overflow-y-auto on the content element, tall forms will push the Save button off-screen — and users lit
- Why My AI Boot Skill Kept Losing Files That Were Right There
Skill instruction files must use absolute paths. Relative paths silently misresolve when the shell's cwd isn't what you think. And if your skill liv
- Why My Dashboard's Python Runtime Has Never Imported an LLM
A pure-stdlib Python server can use Claude Haiku for email triage and a local MLX model for task ranking without importing the SDK. The rule: the runt
- Why My Inline Editor Looked Broken Even Though the Save Worked
In React 19, <form action={serverFn}> resets uncontrolled inputs after the action returns — even when the save succeeded. Make them controlled wit
- When Your Security Fix Becomes the Production Bug: Chunking Past the Schema Cap
A Zod .max(500) added for security silently became a hard limit on real batch operations. The fix is a sequential chunking loop — and every caller tha
- Why Adding a Junction Table Is Only Half the Work
When you bolt a junction table onto a legacy singular FK, your schema is multi-entity. Your validation logic? Still isn't. Every constraint that rea
- Why I Always Stamp Dates in ET Now
Every layer of a modern web stack — Postgres on Supabase, Node on Vercel, the Zoom API, JS date parsing — defaults to UTC. If your business runs on Ea
- Why I Replaced `===` With `timingSafeEqual` Across Every Cron Route
=== short-circuits on the first mismatched byte — an attacker can probe your secret byte-by-byte using response timing. timingSafeEqual from Nod
- The Silent-Fail Trap: Why HTTP 200 Doesn't Mean Your LLM Did Anything
An HTTP 200 from an LLM API tells you the request arrived. It says nothing about whether the model finished. Always check stopreason and cont
- The Silent Lockout: How Supabase's Auto-RLS Cost Me an Hour of Debugging the Wrong Thing
Supabase auto-enables RLS on every new table. Without a policy, Postgres returns zero rows — silently. The fix is one line, but only after you've st
- The Trusted Source That Still Bites You: SSRF on Shopify's Pagination Header
If your code fetches a URL that came out of a third-party response header, validate the hostname against an allowlist before making the request. Eve
- Two-Bucket CSS: Retrofitting Tailwind onto a JS-Coupled App
When you retrofit Tailwind v4 onto an existing interactive app, split your CSS into two buckets — authored @layer components for anything JS touch
- The Client Noticed Before I Did — How I Built a Proper Uptime Monitor for Obsidian Intel
The platform's liveness probe and your external uptime monitor need different endpoints. Bolt deep checks onto the wrong one and a dead API key will
- The One String I Forgot to Escape: AppleScript Injection in the iMessage Bridge
I escaped the message body in my AppleScript iMessage bridge. I didn't escape the recipient handle. They're both interpolated into the same string. Same
- The Qwen3.5 Thinking Budget Trap Nobody Warned Me About
### the setup
- The Silent Board Lie: SWR Cache Revalidation After Mutation Failures
When a server mutation fails, calling mutate() to revalidate your SWR cache isn't optional. Skip it and your UI silently shows the user a state th
- The Silent Data Loss That Finally Made Me Take Retry Seriously
Transient API failures are guaranteed at scale — it's just math. Retry logic isn't a nice-to-have. And don't advance your watermark on a failed batc
- How a Silent PGRST201 Broke My Dashboard Without a Single Error in Sight
PostgREST's PGRST201 isn't just a loud crash — it can be a perfectly silent one. Here's how that happened to me, and the two-line sweep that catches
- Live Things3 Ranking with Local Ollama — The Cache Trick That Made It Work
Poll your live data fast. Cache the LLM's ranked order separately. Invalidate the cache on an explicit trigger — not on every data change.
- Read-Only Runtime, External LLM: How I Got Free AI Email Triage in Apollo Dashboard
Pull the LLM into a scheduled ingest job. Let the runtime be dumb and fast. Bonus: the Claude Agent SDK runs on your subscription — zero metered billing
- The Audit That Found Half My Action Files Completely Unvalidated
I ran a full audit on two production Next.js apps and found 12 of 24 server action files were passing raw form data straight to Postgres. Zero Zod.
- How a Security Audit Taught Me to Stop Trusting Sequential DB Calls
If you're doing multi-table writes as sequential supabase-js calls, one mid-loop error leaves your database in a broken half-state. Push it into a
- How I Idempotency-Proofed FIFO Lot Depletion — Then Found Nothing to Fix
FIFO lot depletion + cron retries = potential double-depletion. Fixed it with a DB-enforced partial unique index keyed to the snapshot date. Ran the
- How I Shipped a Destructive Purge with Zero Test Coverage (On Purpose)
Some destructive-but-bounded operations are legitimately 'traced-only' — not because you were lazy, but because that's the honest shipping posture. The
- How I Wired a Local LLM Sidecar with a Pure-Stdlib Fallback Chain
I wanted a fast local model ranking my tasks. The runtime had to stay pure stdlib. The answer was a sidecar in its own venv — and the real lesson was: b
- Fail-Closed Email Triage: Why My AI Defaults to Silence, Not Surface
When building an attention gate with an LLM, fail-closed beats fail-open. Precision is the differentiator — not recall.
- Grep Finds What You Know. RAG Finds What You Mean. I Needed Both.
Grep finds the word you typed. RAG finds what you meant. Neither alone was enough — and fusing them costs almost nothing extra.
- How Anthropic's Billing Split Forced a Better Email Triage Architecture
When Anthropic moved Agent SDK usage off the Claude Max subscription onto a metered credit pool, I had one day to rethink the email triage in Apollo
- How I Froze the Watermark to Stop Silent Shopify Sync Data Loss
If your sync watermark advances before a batch fully commits, you have a silent data-loss trap. Freeze it until the whole batch is done.
- Benchmark at the Cheapest Point: Go/No-Go Before Full Build
If your plan's justification is 'this should be faster,' benchmark that claim FIRST — before building anything around it.
- CSV Formula Injection: Why 'Just Text' Isn't
Fields starting with =, +, -, or @ in a CSV import aren't just strings — they're deferred spreadsheet formulas. Inert in your database, harmless
- Every Document You Index Is Untrusted Input — Treat It That Way
Every LLM that touches ingested content — at chunking time AND at synthesis time — is holding untrusted input. Don't paste documents into your instr
- Why `bodySizeLimit: '100mb'` Did Absolutely Nothing on Vercel
Vercel hard-caps request bodies at 4.5MB at the platform level. bodySizeLimit in next.config can't touch it. Fix: send one file per request.
- Why the QuickBooks MCP Server Needs Per-Call Token Refresh
A QuickBooks MCP server caches its access token at boot. Access tokens expire in ~an hour. Long sessions die silently. The fix: refresh per call, not pe
- Why Your iOS Hero Is Clipped (And Why dvh Fixes It)
On iOS Safari, 100vh is taller than the visible screen. Use 100dvh instead. One unit, one fix.
- What Arc CDP Taught Me About Blur Events (The Hard Way)
el.blur() inside a CDP eval silently no-ops when the tab lacks real OS focus. Dispatch new Event('blur') instead — or watch your commit handler
- When Jinja2 Renders Plausibly Wrong: Looping Over Founders in a Legal Blueprint
If your Jinja2 blueprint context has an array, you need an explicit {% for %} loop. The renderer does NOT blow up without one — it just silently d
- When 'Make It All Searchable' Is the Wrong Instinct
When your AI agent needs to filter relational data, reach for structured SQL column-filters — not embeddings. The column whitelist is your security
- Why a Two-Word Name Returned Zero Results (And How Tokenized Search Fixed It)
If your database splits names across columns (firstname / lastname), a full-string ILIKE against either column will never match a two-w
- Why I Stopped Using `confirm()` in My Admin UIs
window.confirm() silently returns false the moment Chrome decides to block it — with zero warning to the user. Don't touch it. Use an in-app dialog.
- Why My GA4 Service Account Got Hard-Blocked (and the OAuth Fix That Worked)
GA4 (Google Analytics 4) hard-blocks service accounts from Workspace-org properties. Don't fight it — authenticate as a real user with a refresh tok
- The One-Line Fix That Unblocked a Whole Warehouse Error Flow
Shopify stores order numbers as #472791. If your query strips the # from user input but matches with .eq(), you'll never find anything. Match
- The Rate Limiter That Killed My Whole Chat Route
Passed a raw JS Date object to postgres.js (my Postgres client) as a query param. The driver threw ERRINVALIDARGTYPE. The rate limiter that
- The Timezone Trap That Almost Made Every Event Time Four Hours Wrong
We stored event times as naive wall-clock UTC, then almost 'fixed' the display — which would have shifted every event four hours wrong. The rot was
- The VERCEL_URL Trap That Nearly Poisoned My Canonical URLs
VERCELURL is set in production too — it's a per-deploy hash, not your real domain. Gate your metadataBase on VERCELENV === 'production' inst
- The Webhook Was Already There. It Just Did Nothing.
Before you build the webhook, check if someone already did. The lesson isn't 'read the code' — it's deployed ≠ wired.
- The Bug That Made 55 of 75 Contacts Un-Editable (And What It Taught Me About Shared Tables)
Two apps sharing one database table. One app's Zod validation silently rejected values the other app wrote. 55 of 75 contacts became un-editable overn
- The Daemon That Died in Silence (and the One That Wouldn't Stay Dead)
launchctl bootstrap from a project directory is NOT a persistent install. And leaving a retired .plist in ~/Library/LaunchAgents/ is how you grow
- The Easiest Corner to Fake (And How I Stopped Faking It)
### The Setup
- The GA4 Gotcha That Was Quietly Lying About Our Webinar Reg Rate
If you're pulling GA4 pagePath data via the Data API and using matchType: CONTAINS, your click counts are probably wrong. Use EXACT. For A/B v
- The Git Hunk-Split Recipe: Three Features, Four Files, Three Atomic Commits
When multiple features land in the same files, Python-split the diff by hunks, git apply --cached --recount each group, and commit. --recount is the
- The One-Character Regex That Was Zeroing My Entire Supply-Chain Dashboard
/([a-z])/g skips underscores followed by digits. runrate7d becomes runRate7d. TypeScript doesn't notice. ?? 0 turns undefined into a r
- Reject Non-ISO Dates at Build, Not in the Renderer
In a static-site pipeline, validate frontmatter dates at parse time — one regex in toDate() and bad dates blow up the build before they ever ship.
- Search Has to Follow Your Data Model
If your database identifies an entity through a relationship, your search query has to traverse that relationship — or it will return nothing for the mo
- Ship It Ungated, Add Auth Second
Deploy internal tools ungated. Hide them behind Vercel Deployment Protection. Add the auth gate only after you've verified the thing actually works on p
- Stateless First: How a No-DB Preview Saved Our Webinar Dashboard Migration
Prove your numbers on a stateless preview route before you touch the database. In that order, every time.
- The Bug That Hid Behind My Own Error Handler
If your error handler calls res.json() and then res.text() as a fallback, the fallback silently throws 'Body has already been read' — and the real
- How a USING (true) RLS Policy Left Every Shopify Order Open to Any Google Account
We had 13 Supabase RLS policies set to using(true). That meant any Google account in the world could read our Shopify orders through PostgREST — c
- I Almost Built the Wrong Proxy. Then I Grepped the Binary.
Stock claude speaks Anthropic /v1/messages natively — no proxy needed. If your inference provider does too (Ollama v0.14+ does), just set ANTHR
- I Patched the Same CSS Bug Four Times Before I Looked at It
A 'gradient walled in a rectangle' got four CSS patches. None worked. The fix was removing the cursor-glow entirely — because it was the rectangle
- Loopback, BlackHole, and the Zoom Guitar Signal That Kept Dying
### the setup
- Never Trust --tab 0: What Arc CDP Tab Drift Actually Costs You
Arc tab indices shift the moment anyone opens a new tab. Your agent's --tab 0 is someone else's Zoom call. Always verify ownership before driving.
- How a Missing Time Fence Was Quietly Inflating Our Halo Numbers
If your Halo Effect pulls all-time orders without a time fence, you're not measuring event impact — you're measuring your entire customer history. Fix i
- How I Built a 12-Stage Pixel-Art Body Transformation with PixelLab AI
To get consistent 12-stage pixel-art progression, chain each stage's initimage from the previous output. Tune initimagestrength by zone — ~335 to
- How I Found Out My Arcade Slack Token Wasn't Throttled (and Why I Had to Check)
Slack's new rate-limit regime for non-Marketplace apps can be brutal — but whether your app is on it isn't in the docs. You have to probe live.
- How I Got AI-Generated Sprites to Stay In-Family AND Look Distinct
if you're generating a character progression with AI art, independent text prompts can't give you a consistent character AND visibly distinct stages at
- How I Made 42 Things MCP Calls That All 'Succeeded' and Did Nothing
The Things MCP (the server that lets an AI agent drive Things 3, my task manager) never returns the UUID it just created. Fabricate one and your move ca
- How I Wired a Fillout Webhook Secret When Simple Mode Doesn't Do Headers
Fillout's Simple webhook mode doesn't support custom headers. Stop fighting it — make your endpoint accept the secret as ?t=<secret> instead. Constant
- A Recurring Renewal Isn't a Win You Earned
If you're attributing Shopify sales to a webinar (or any campaign), you MUST exclude orders tagged Subscription Recurring Order. They're Recharge
- Ditch the Slide-Out: How I Built a ⌘K Floating Command Palette for a Law Practice App
### The Setup
- How 'Zero Overflow' Let a 14px Pricing Row Slip Through My Mobile Audit
My CDP audit came back with zero overflow across all seven routes. The dt labels in my pricing value-stack were still rendering at 14px — one word
- Why `router.replace` on a Force-Dynamic Page Is a Hidden Server Round-Trip
router.replace(?foo=bar) on a force-dynamic page hits the server every single time. Use React state + window.history.replaceState for UI state
- Why Your RAG Chunks Don't Know Where They Came From
### The Setup
- Why My AI Agents Only Get Western Inference (But I Don't Have To)
I split my AI infrastructure by consent axis. Daemons that fire without me → Western providers only. Me at the keyboard → my call, per-call.
- Why Our Inventory Count Was Triple the Real Number
Alias products that mirror a canonical's inventory were being SUM'd into the canonical's total. SKU-A showed 3N on-hand. Real count: N. The system w
- When Your E2E Test Passes and the Feature Is Still Broken: Radix + CDP
A synthetic .click() can return successfully and still do absolutely nothing in Radix UI. If your E2E tests drive the browser via CDP eval, you ne
- Why Hybrid Retrieval Beat Pure RAG for My AI Assistant's Memory
Pure semantic RAG sounds like the upgrade. It's not sufficient on its own. The gap isn't recall quality — it's freshness and coverage. Run grep alongsid
- Why I Stopped Throwing Errors from Next.js Server Actions (And What I Use Instead)
Next.js production masks thrown server-action errors behind useless digest hashes. Return errors as typed data — ActionResult with ok() and fai
- The settings.json Model Trap That Was Silently Burning My Opus Budget
~/.claude/settings.json doesn't just set your interactive model — it leaks into every background claude -p subprocess (headless Claude call) tha
- The Vercel excludeFiles Glob That Looked Smart and Silently Killed My Python Deployment
A functions.excludeFiles glob in vercel.json can silently prevent your Vercel Python function from being registered at all — no build error, jus
- How a Billing Change Made Me Grep a Binary (and Simplify Everything)
Before you add a translation proxy, grep your binary. The tool you're wrapping might already speak the format you need.
- The Empty 200: What ZAI Taught Me About Silent Failures in Multi-Provider AI Routing
HTTP 200 from an AI provider is NOT proof the call succeeded. You have to verify stopreason == endturn AND non-empty content — every time. Differe
- How a 30-Second Unzip Settled the Whole Architecture
Before you ask 'JS or Python?' — unzip the file and look. Thirty seconds of grepping ended a fake debate and saved hours of the wrong build.
- How I Wired Live Registrant Counts to Zoom (and the Three Traps That Ate Two Hours)
Zoom's marketplace hid the Server-to-Server OAuth option in 2024. The old compound scopes don't work anymore. And /users/me flat-out doesn't exis
- The Toast That Never Fired: What a WIN Audit Caught Before the Webinar Tool Hit the Team
Your app can look completely done and be a silent failure machine. A WIN audit — asking every screen whether it handles loading, empty, error, partial
- How I Taught an Embedded AI Agent to Know What Page It's On
A static system prompt makes your embedded AI agent blind to the record the user is actually looking at. Pass the page entity ID in the POST body, f
- How I Taught My AI Agent to Know When Its Own Memory Is Stale
If your RAG synthesis layer strips the date from a chunk before answering, you're not building a memory system — you're building a confident liar.
- How I Scrubbed a Client from My AI Agent — the Day Before They Called Back
When a client departs, 'remove them from everything' is the wrong instruction to give your AI agent. The right move is surgical. I learned this when
- The Ref Trick That Cured My AI Chat's Stale Context Problem
When your AI chat transport needs fresh context at send time, don't recreate the transport — keep it stable and read the latest value through a use
- Why `/webinars` Loaded the Wrong Stylesheet (And How CDP Finally Told Me the Truth)
On Vercel (and Netlify / Cloudflare Pages), a page served at /webinars with no trailing slash has a base URL of /, not /webinars/ — so relativ
- ZERO Bottles on Weekends — and Why the Data Was Right the Whole Time
A chart showing weekend zeros wasn't broken — it had two separate problems hiding inside one symptom. Fix the bucketing key first. Then add smoothing.
- When Your Vendor Has Different Lead Times Per Product, You Have a Join Table Problem
If a metric varies by both sides of a many-to-many relationship — not just one — it belongs on the join table. I had to learn this a third time be
- Why I Replaced My 11-Step Onboarding Checklist with One Paste-In Prompt
When onboarding a non-technical user to Claude Code, the entry point isn't a checklist. It's one prompt they paste — and the agent does the setup for th
- The Service Worker That Spun Forever (And How I Fixed It the Night Before a Workshop)
If your service worker bootstrap hangs after the first registration, stop waiting for controllerchange. Just await serviceWorker.ready and reload()
- What a Supplier Fallback Chain Taught Me About Join Tables
If a metric varies by both sides of a many-to-many relationship, it cannot live on either entity. It has to live on the join. I learned this building
- The Migration Was Perfect. The Table Was Empty. Here's Why.
Supabase auto-enables Row Level Security (RLS) on every new table — no policy = deny-all, and supabase-js returns { data: [], error: null } with
- The One CSS Line That Broke Everything (And 12 Commits That Didn't Help)
If your CSS variables use cqi units, never apply them to html — even inside a shared html, body {} rule. Set font-size on body only. One m
- The One SQL Comment That Broke Every Report — and Why a Human Had to Fix It
A one-line migration comment asserted 'no SKU overlap between stores.' It was wrong. Every velocity, forecast, and ledger report in the supply chain
- Order Placed vs. Order Shipped: The Timestamp Bug That Stole Our Weekends
If your daily sales chart shows weekend zeros on warehouse-fulfilled orders, you're almost certainly bucketing by the wrong timestamp — and your timezon
- React Compiler Flagged My useMemo — and Deleting It Was the Right Call
React Compiler owns memoization now. When its eslint rules flag a useMemo, delete the annotation first — don't eslint-disable. Nine times out of te
- How a CSS Grid Default Silently Blew Up My Whole Page Layout
CSS grid items default to min-width: auto. If one column holds a <pre> block with long lines, the whole layout blows past the viewport. Fix: mi
- How PostgREST's Silent 1000-Row Cap Broke My Supply-Chain Charts
PostgREST silently caps query results at 1000 rows. No error. The data shape looks fine. Your math is just… wrong. Move aggregation into SQL functions c
- How One CSS Line Broke Every Slide — and Twelve Commits Couldn't Fix It
Never set font-size on html. cqi on the root element resolves against the viewport, not a container — and it will silently detonate every rem-ba
- How One Shared ChartFrame Turned Six Bugs Into One
Before shipping a single feature chart, scaffold your shared primitives — palette, container, tooltip styles, selectors. Every styling bug you hit a
- Client-Side AES-256-GCM Is a Gate, Not a Vault
Client-side AES-256-GCM keeps honest people honest. It is NOT a substitute for real access control at the data layer. Know exactly what you bought.
- How I Got Apollo to Call Me Back From Anywhere
Texting 'call me' to my AI agent now rings my actual phone. Getting there required three non-obvious decisions I'll make again on every agent I build.
- `$NaN` in the UI — Why I Now Ask 'Is Zero Actually True Here?'
Xero returns undefined for amounts on untouched projects. Feed that into a currency formatter and you get $NaN. One ?? 0 fixes it. But the sam
- Your Middleware Isn't Enough: Mirror the Auth Check at the Route Layout
One auth check isn't defense-in-depth. Mirror it at the API handler, the middleware, AND the route layout — and make every gate fail closed when the
- Why I Stopped Validating at the Form and Started Doing It at the Boundary
Validating at the form layer feels like enough — until you ship. Validate once, at the trust boundary, every time.
- Why I Was Sending 859 Database Rows to Every Single Chat Message
I was fetching all 859 facility rows from the database on every single chat message and filtering in JavaScript. One function call fixed it — ~8x le
- Why I Wire the Advisor Into Every Data Migration Now
I called the advisor before shipping an Airtable data migration — it caught real blockers. Same week I skipped that step on a Shopify sync, and a 30-sec
- Why My AI Agent Kept Suggesting Tasks I'd Already Done
Don't cache cheap, user-mutable reads in a long-lived execution context. The staleness cost will eat you alive.
- Why My Wildcard Sanitizer Had a Blind Spot (and How a %@% Fixed That)
If you use supabase-js's .ilike() for lookups, % and in the input are live PostgreSQL wildcards — and PostgREST exposes no ESCAPE clause t
- When Zero Looks Fine: Observability for Silent Background Failures
If your background process returns nothing and throws no error, you have no idea if it worked. Make noise the default — before you do anything else.
- Why I Budget Fifteen Minutes After Every Overnight Agent Build
Cold-start bugs don't live in your shell — they live in the real launch environment. You can't find them until you run there.
- Why I Stopped Choosing Between Semantic and Keyword Search
Neither pure semantic search nor pure keyword search is enough. You need both, fused — and I had to build each one twice to figure that out.
- The Silent Truncation: What `stop_reason` Taught Me About LLM Token Limits
maxtokens=4096 silently truncates complex structured outputs. The model calls the tool, you get an HTTP 200, and the field is just… empty. Log
- The Transient State That Ate Two Weeks of Fathom Transcripts
In any processing loop, 'transient' and 'terminal' are completely different states. Only terminal states should block re-processing — and they definitel
- The XSS Vector Hiding in Your Database URLs
React does NOT block javascript: URLs in <a href>. If you're pulling URLs from a database, you need a scheme check before render. Every time.
- What LLM-Driven Schema Mapping Taught Me About Trust — and Runtime Guards
When you ask an LLM to produce a schema mapping, prompt clarity isn't enough. Validate at the boundary and halt loudly — or you'll get silent, empty row
- When Your LLM Guardrail Is Too Good at Its Job
A HARDRULES block I wrote to protect financial data was killing aggregate financial questions too. The fix wasn't removing the rule — it was sco
- The Dead-Code Fallback That Made Me Look Sideways for Data
Two layers of failure hid a display name from my calendar agent. The fix wasn't patching either layer — it was checking a completely different system th
- The Next.js Server Action That Looked Like a Bug (And Wasn't)
React 19 resets uncontrolled form fields after a server action returns — on success and on non-throw failure. The DB write lands fine. Only the UI
- The React 19 setState-in-Effect Lint Isn't Always Wrong to Silence
react-hooks/set-state-in-effect fires as a hard error in Next.js 16. Three of my four cases had cleaner fixes. The fourth was legitimately right t
- How One Fresh Supabase Client Locked Out Every User I Had
If a Supabase helper creates its own createClient(), it has no session. RLS rejects the read. It fails silently. Everyone gets denied. Pass the
- How We Stopped a CMS Sync from Eating Manually-Edited Fields
if a sync job upserts on a shared key, every re-run can silently blow away manual edits. Add a per-record lock flag the importer checks before writing
- I Built a Five-Phase AI Agent. It Died at the First Reboot.
launchctl bootstrap from a repo path doesn't survive a reboot. Copy the plist to ~/Library/LaunchAgents/. But the actual lesson is deeper — if you
- Pre-Build the Payload Your Downstream System Actually Needs
Don't make Make.com reconstruct your data. Pre-build exactly what it needs in the payload — your server already has all the context.
- Stop Retrying Your Own Mistakes: How I Fixed My Webhook Retry Logic on a Client Platform
Don't retry 4xx. A 401 won't fix itself after three attempts — it'll just fail slowly instead of fast.
- How I Let the OpenAI SDK Default Blow Past Vercel's 60-Second Budget
Your API client timeout must live under your platform's hard ceiling — not above it. And retrying a 4xx just burns the budget twice.
- How I Taught Apollo to Never Forget a Session
Two Claude Code hooks aren't enough — there are four ways a session can end, and only one of them is obvious. Wire all four or you'll keep losing se
- How Next.js Server Actions Swallow Your Errors (And How to Get Them Back)
Two error-propagation traps in Next.js server actions — redirect() silently eaten by a try/catch, and Vercel's platform-level 4.5MB cap disguised
- Four Guards Between Me and a Database Wipe I'd Regret
One confirm dialog is not enough. Stack four guards — flag, hardcoded env ref, pre-approved mapping file, and a typed 'DESTROY' prompt that shows ro
- How I Built Per-Recipient Transcript Redaction for a Client's Webhook Pipeline
When one webhook fans out to multiple competing recipients, each one needs its own redacted view of the data. Paragraph-level stripping works — but
- How I Learned to Gate MCP Tools in a Headless Claude Subprocess
When you shell out to claude -p (headless Claude) in a subprocess, MCP tools don't just appear — you have to wire them in explicitly. And the flag you
- Why the 'Best' Model Failed My Meeting Scanner — And What I Use Instead
The model that won my general text bake-off quietly dropped 4 real commitments when I aimed it at meeting transcripts. Recall matters more than prec
- Why Your Next.js Middleware Auth Redirect Is Silently Killing Your API Routes
Never use a 302 redirect to 'protect' an API route. A redirect is page protection — not a gate. Exempt /api/ from your middleware, then add the r
- What Killing the Process Taught Me About Agent Memory
Every iMessage turn spawns a fresh claude -p process. 'Session memory' doesn't exist. If your agent doesn't write to disk before it exits, the lea
- Why I Moved All the Aggregation Into Postgres (And Then MATERIALIZED the CTEs)
Stop aggregating in JavaScript. Move the math into a Postgres SQL function, call it via supabase.rpc(), and MATERIALIZED the shared base CTE so
- Why I Stopped Aggregating in JavaScript (and Let Postgres Do the Math)
If your Supabase aggregation numbers look plausible but wrong, check the row count first. PostgREST silently caps at 1,000. Push the math into a SQL
- Why Make.com Error Count Is a Terrible Triage Signal
Make.com fires an email on every scenario error. The right signal isn't error count — it's failure mode. Classify first, route second.
- The Prompt Is Not a Firewall
LLMs drift. Prompting them to stay inside a trust boundary is advisory. Code-level firewalls are mandatory.
- The Stateless Agent Pattern: One Process Per Message, No Exceptions
Don't build a long-lived AI agent process. Spawn one subprocess per message, return text, die. Decouple everything else.
- Two Apps, One Contacts Table, and the Hardcoded List That Made It Invisible
One shared Supabase table + a roles array beats two per-app contact tables. But the canonical isn't done when the rows merge — grep every hardcoded li
- The Invisible Marker That Made Apollo Loop Forever
I used a Zero-Width Joiner to mark every outbound Apollo message. The decoder ate the marker. A fallback path fed Apollo its own NSArchiver garbage inst
- The NextAuth v5 Secret That Silently Breaks Your Fallback in Production
### what we were building
- The Postgres Migration Foot-Gun Nobody Warns You About: DROP Before CREATE
CREATE OR REPLACE FUNCTION can change a Postgres function's body — but NOT its return shape. Add or remove a column from RETURNS TABLE(...) and
- The PostgREST Embed Bug That Showed Zero Webinars (When There Were Five)
When PostgREST has two paths between two tables, it picks neither — and one of those failures looks exactly like 'no data.'
- The Apostrophe That Silenced My Voice Calls
encodeURIComponent leaves ' ! ( ) unencoded. When your URL goes into XML, ' gets escaped to ' — then decoded back to a literal ' be
- The File Existed. SQLite Still Wouldn't Open It.
better-sqlite3 can't open a bundled SQLite file from Vercel's /var/task layer even when existsSync returns true. Copy it to /tmp on cold s
- The Four Walls You Hit Deploying Native SQLite to Vercel
serverExternalPackages is step one. There are three more after it.
- How a Single Batching Change Cut Our Shopify Sync to 1/50th the API Calls
Switching from row-by-row upserts to 100-row batches in our Shopify → Supabase orders sync cut API round-trips by ~50×. The fix was five lines. The
- How a 'Smart' Polling Window Silently Ate Two Weeks of Transcripts
If your polling job widens its lookback window on failure, it will silently replace your watermark with a guess. The fix: the cursor only ever advan
- How a String That Wasn't a String Orphaned Tens of Thousands of Rows
If you're syncing Recharge subscriptions to a database and your product links are all null — check externalproductid.ecommerce, not externalproduc
- How I Rebuilt 90 Days of Inventory History from Shopify Orders
If you have order history, you already have inventory history. Replay the transactions, build the snapshots.
- How I Stopped Fighting Vercel Errors Blind
when your Vercel function returns a blank 500, the first fix is rarely the bug — it's making the function tell you what went wrong. Surface the error,
- How I Taught Apollo to Decide What's Worth Remembering (Without Asking Me)
Don't save every turn. Don't wait to be asked. Separate the cheap decision ('is this worth keeping?') from the expensive write ('format it, dedup it
- How I Taught My iMessage Dispatcher to Diagnose Before It Retried
Blind retry is almost always wrong. Classify the error first, fix what you can, then retry — and narrate loudly so you know what's happening.
- How I Learned to Block the Call, Not Just Filter the Output
Telling an LLM not to use a tool is not the same as preventing it from using the tool. Enforce scope at two layers — prompt AND harness — or the fir
- How 'Your Voice Sucks' Fixed My TTS Architecture
Put your TTS behind a proxy URL endpoint. Use <Play> not <Say>. Swap providers without touching telephony.
- When Your Prompt Template Breaks Python: The 44-Hour F-String Outage
Dropped a literal {channelid} placeholder into a Python f-string to guide an LLM. Python treated it as a variable, crashed every run, and my agen
- Why Prompts Alone Can't Guard an AI Agent's Side Effects
When an AI agent has side effects — creating tasks, sending messages, triggering anything — a prompt saying 'don't do X' is not a hard stop. You nee
- The Wire Is the Spec: Stop Trusting Your TypeScript Interfaces Against External APIs
I assumed I knew the shape of an external API response. I was wrong. 849 locations got corrupted before I noticed. The fix is boring — run the live quer
- What a Cloudflare Tunnel 502 Taught Me About Robust OAuth Callbacks
Build your OAuth callback server so it can be fed the redirect URL by hand over loopback. Tunnels are flaky. Auth codes survive a 502.
- The PII Leaks You Build Yourself
The PII leak that almost shipped wasn't from an attacker. It was from me. A console.log I left in while debugging.
- The QuickBooks OAuth Bug That Worked Until It Didn't
When an OAuth provider rotates refresh tokens, you must write the new one back to disk on every single refresh. Read-once-from-.env quietly breaks
- The Request Body That Could Empty Your AI Budget
If you have an AI chat endpoint and no body size cap, you have a denial-of-wallet hole. Cap it in your app — not your platform. 256 KiB is a reas
- The AI Was a Doorman. No Wonder Nobody Came In.
I built a lead gate for a cancer clinic finder that turned the AI into a bouncer. 71% of users hit one sentence and left. The fix was three words: lead
- The Exit-Intent Modal That Actually Had to Come Second
The gate that was supposed to capture leads was the reason people were leaving. Flip the order — lead with value, catch them on exit — and your moda
- The Next.js 16 Hydration Trap I Silenced (And Why That Was Wrong)
Don't silence react-hooks/set-state-in-effect with eslint-disable. It's the lint telling you your SSR will break. The real fix is useSyncExtern
- Register Your Error Handlers First, or They Won't Be There When You Need Them
### The Setup
- The .env File I Thought I Fixed Twice (And the One Command That Actually Works)
Adding .env to .gitignore does nothing if git is already tracking the file. The actual fix is git rm --cached .env. Everything else is just wi
- How a Friendly Supabase Method Was Silently Injecting PostgreSQL Wildcards
supabase-js's .ilike() passes your string directly as a PostgreSQL LIKE pattern. PostgREST exposes no ESCAPE clause. Strip % and from
- How a Google API Error Ended Up in My UI (and What I Did About It)
If an upstream API call fails and you surface that error straight to the client, you're leaking. Log the detail server-side. Return a sanitized gen
- My .env Was Always There — Node Just Wasn't Looking in the Right Place
Anything launched by something other than you-in-the-project-dir — MCP server, launchd daemon, cron job — must resolve .env relative to import.me
- How a 71% Bounce Rate Taught Me to Scope AI Gates Precisely
A blunt AI gate doesn't protect the product — it wrecks the funnel. The fix is a short block list and a generous allow list, not a wall.
- How a Default Next.js Setting Was Serving My Draft Posts to Anyone Who Asked
In Next.js App Router, generateStaticParams is NOT a whitelist. Drafts you exclude from the list are still publicly accessible by default. One lin
- How I Built a Bridge From Obsidian to the Web
Obsidian's markdown flavor (![[image.png]], [[wikilinks]]) doesn't render on the web. A small translation layer fixes it, and suddenly your note
- How I Told Cancer Patients 'Location Unknown' 856 Times Before Noticing
I assumed I knew the shape of a TakeShape API response. I was wrong. 856 of 859 cancer treatment centers silently lost their addresses. Fixed in one com
- Why Next.js Silently Dropped My Native Modules (And the Two Config Keys That Fixed It)
Next.js's file tracer can't follow dynamic import specifiers — so native packages that resolve their binary at runtime get silently excluded from yo
- Folder Templates on Status Transitions (and the Missing Xero ID That Broke Everything)
When a matter transitions to Active, fire your full file ecosystem — Drive folders, Gmail label, Xero project — in one burst from inside the app. But re
- How I Built a React Flow Canvas from Flat-File SOPs — and the Grid-Pack Trap I Hit
If you're auto-importing nodes into a React Flow canvas, derive position from an index. Never accumulate per-node offsets — they compound into an un
- How I Got 12/12 Clean Sections Out of a Batched LLM Pipeline
When you batch LLM calls to generate dense structured output, four things will break on you — and they'll break in sequence, one crash at a time. He
- I Gated the AI to Capture Leads — Then Watched 71% of Users Walk Out
Don't put secrets in the prompt. Stripping sensitive fields from your system prompt JSON is the real lock — 'do not share this' instructions are def
- Shopify's Silent 25-Character Schema Trap (And How I Finally Found It)
Shopify silently drops any Liquid section whose {% schema %} name field exceeds 25 characters. The error you see looks like a missing file. The -
- Stateless HMAC Auth in Next 16: The Quiet Rename That Burned Me
Next 16 killed middleware.ts. The replacement is proxy.ts — and it needs to live beside your app/ folder, not at the project root. I learned
- The Two Shapes of 'Don't Duplicate': Find-or-Create and Idempotency Keys in Xero
When you hit a ContactId cannot be null or empty 400 from Xero (the accounting platform), the tempting fix is blind-create. Don't. Find-or-create the
- What 36 LLM Calls Taught Me About Network Retry and Empty Defaults
At batch LLM scale, a 1–3% flake rate isn't rare — it's guaranteed. Wrap every client.messages.create() call in a retry loop, and strip empty defaul
- Why Content Fingerprinting Beat My Subject-Hash Dedup (By a Mile)
Never build a dedup key out of fields your model generates. It'll regenerate them differently every run. Hash the raw content — the one thing that
- Why I Replaced Offset Accumulation With a Grid-Pack for React Flow Node Placement
If you're placing N nodes on a canvas by accumulating a running offset, stop. Compute position from index. It's deterministic, it's idempotent, and
- Why I Stopped Using Voyage for Text RAG (and When I'd Reach for It Again)
For text RAG, default to OpenAI text-embedding-3-small. Competitive quality, you probably already have the key, one fewer billing surface. Voyage
- Why Your RAG Ingest Should Know What Kind of Content It's Eating
When your RAG corpus has multiple source kinds, make sourcekind a first-class column from day one. The unit of rebuild should match the unit of c
- The Memory Cap That Was Crying Wolf
I spent two archive sweeps chasing a token cap that was never actually costing me anything. 9% reduction. The cap was aspirational. My session budge
- Why I Gave Every Section Its Own LLM Call
One LLM call per visual block, not one per page. The pattern library was a dead end.
- The Strip Step Everyone Skips: Building a RAG Ingest Pipeline for Sensitive Docs
Strip sensitive content before it hits your vector DB — not at query time. One LLM pass at ingest beats a thousand prompt instructions at retrieval.
- The Shopify Liquid Gotcha That Bit Me (and Will Bite Your LLM Too)
Liquid won't let you run a filter inside an {% if %} condition. Assign the result to a variable first, then compare. Simple — except your LLM will get
- How a Zero-Width Character Sent My AI Agent Into an Infinite Reply Loop
If your iMessage agent marks its own sends with a zero-width joiner (U+200D) and uses str.isprintable() to walk decoded attributedBody blobs —
- How SQLite's `immutable=1` Flag Gave Me a Permanently Empty Inbox
If you're reading a live-written SQLite database you don't own, open it with mode=ro — NOT immutable=1. The difference is subtle, the failure is bru
- How a Deep-Link URL Told Me a Consultation Already Existed
### The Setup
- What CSP Taught Me About Third-Party Resource Types
A Content Security Policy isn't just a list of trusted domains. It's a matrix of domains × resource types — and one missing intersection means a bla
- The Three Lines That Fixed a Race Condition I Didn't Know I Had
useState updates are async. If you call a function in the same tick as setState, that function reads the old value. Use a useRef alongside
- How an Unrelated Migration Broke Our PostgREST Queries — One of Them Silently
Running unrelated migrations triggers a PostgREST schema cache reload. If any of your embeds have latent FK ambiguity, that reload will enforce it — and
- How CSS GPU Layers Broke My Drag-and-Drop Board (And the Fix Was Removing Code)
will-change: transform, translate3d, and backdrop-filter each create a new GPU compositing layer. On a drag-and-drop board, that silently kills dr
- How I Hardened Apollo's Scanner Against Prompt Injection (Two Cheap Fixes That Actually Work)
If your LLM pipeline feeds untrusted external content to a model, you need to (1) fence your instructions away from that content and (2) place your
- How My Own Robot Reviewer Caught My Secret Sitting in `ps aux`
If you pass secrets to a subprocess as command-line arguments, every other process on the box can read them with ps aux. Pass them via stdin inste
- How One Bad Enum Was Silently Killing My Entire Scan Batch
### The Setup
- How Playwright Became the Net That Let Me Actually Fix the Board
Don't add E2E after you fix the board. Add it first — so you can actually fix the board.
- How SWR's Default Refetch Behavior Was Trashing My Drag-and-Drop Board
SWR's revalidateOnFocus, revalidateOnReconnect, and revalidateIfStale are all true by default. On a drag-and-drop board, that's lethal. Wrap
- The One-Liner My Autonomous Council Flagged That I'd Never Have Caught
Every background daemon you ship needs a RotatingFileHandler. One line. Five minutes. Your disk will thank you.
- The One Retry Rule I Wish I'd Learned Before Building Two Systems
Centralize your retry/backoff in one shared runner. And never, ever retry a timeout — it just doubles your wait.
- The Problem With Letting Your AI Agents Read Their Own Prior Work
Running autonomous agent cycles in the same session means every new cycle has read the prior ones. By Cycle 5 they stop catching bugs and start agre
- Validate Your Env Vars at Boot — or Pay the Price Later
Don't check for required env vars when you need them. Check at boot — before anything else touches them. Silent missing-config bugs are the worst
- What Pydantic's `extra='forbid'` Gets Wrong When Your Data Comes From an LLM
When Pydantic is validating LLM output, extra='forbid' is the wrong default. Switch to extra='ignore' — and wrap each item in its own try/except.
- Why dnd-kit's Default Collision Detection Kept Picking the Wrong Target
dnd-kit's closestCenter is a geometry function. It doesn't know what you mean. When you have nested droppables, you have to write that intent yourse
- Why I Ended Up with One JSON Parser for Two Different LLM Models
claude -p --output-format json does NOT hand you the model's JSON. It wraps it in an envelope. The model's text lives inside a .result field — a
- Why My Custom Tailwind Class Kept Losing (And the One-Word Fix That Saved It)
if your custom Tailwind class keeps getting overridden and you can't figure out why, check whether it lives inside @layer components. If it does — and
- My Own Rule Said Don't Cap It. I Capped It Anyway.
If you have a work queue feeding a slow, expensive consumer, bound it with FIFO eviction. The oldest items are the most stale. An unbounded queue th
- SQL Injection Was Hiding in My Supabase `.not('in')` Calls
PostgREST's .not('column', 'in', '(1,2,3)') builds a raw filter string — you own the sanitization. One .map(Number).filter() call per call site
- The Bug That Corrupted My Scanner State (And the Three-Line Fix)
### what we were building
- The One-Liner That *Looked* Safe (and How an Origin Check Fixed It)
If your open-redirect guard is a string heuristic, it's probably bypassable. Use new URL() and compare origins instead. One-liner → five lines. Bu
- How a Single String Was Gutting My Entire Content Security Policy
'unsafe-eval' in your script-src doesn't weaken your CSP — it effectively disables it. It had been sitting there since I first wired up the secu
- The Save Worked. The UI Still Snapped Back. Here's Why.
If your server action succeeds but the UI reverts anyway — it's not a broken save. React 19 is resetting your uncontrolled input after revalidation.
- When Your MCP Search Returns the Envelope, Not the Data
The official Intuit QuickBooks Online MCP server (the Node/TypeScript one, intuit/quickbooks-online-mcp-server) had two silent bugs in its search
- The Lazy Loading Trap That Made My LCP Worse (And How I Fixed It)
Don't put loading='lazy' on your LCP element. Lazy-load everything below it, and serve the hero/LCP image via your CDN's transform API — pre-siz
- The Shopify Sync That Never Had a Race Condition (And the Ones That Did)
If you own the source of truth on one side and just mirror it, you can't have a consistency race. You only get races where both sides try to own t
- When the Swift Compiler Refuses to Build Your View, Listen to It
The Swift type-checker timed out on a fat SwiftUI view body. Extracting one section into its own subview fixed it instantly — and it was the right call
- Why Stripping HTML Tags Isn't Enough: Two CMSes Taught Me This in One Week
CMS rich-text fields store content with HTML tags and entity codes. Strip the tags, and the entities survive — literally. You need two passes. Always.
- Stop Saving on Return. Mobile Users Tap Away.
Wire your iOS save to focus-loss — onChange(of: focusedField) — not onSubmit. Mobile users tap away. They don't press Return.
- The Auth Gate That Wasn't Guarding the Real Door
An app-layer auth gate doesn't protect you when the auto-generated REST API accepts any valid Google JWT. Lock the OAuth door first, then gate the UI.
- Why Every Create Flow Should Auto-Navigate to What You Just Made
After creating a record, navigate straight to it. Don't drop the user back on a list and make them hunt for what they just made.
- Why Swipe-to-Delete Always Needs a Confirmation Step
Swipe-to-delete fired instantly. One fat-thumb swipe and a real KOL contact — warmth score, notes, relationship history — would have been gone. Adding a
- An ID Is Not a Password: How We Closed an IDOR in Our Cancer Patient Chat App
Storing a resource ID in the browser is not ownership. Bind every object to a secret token and verify it server-side — or anyone who guesses the ID can
- How a Fullscreen Overlay Fixed Our Broken Mobile Booking Form
If you're embedding a third-party form in a scrollable card on mobile, just make it fullscreen. Two scroll containers fighting each other never ends
- How Eliminating `any` Types Made Our Build the First Line of Defence
Zod (a schema validation library) guards your runtime edges. Eliminating any makes TypeScript guard everything in between. You need both.
- How localStorage Bridged Sessions — And Then Became a Security Hole
Persisting a conversationId in localStorage is easy. Securing it — so one patient can't accidentally read another's — takes one more step that's easy
- How Two Characters Broke My HubSpot Pre-Fill (and What It Taught Me About Third-Party Forms)
### The Setup
- When Your Validator Is the Bug, Not the Data
If you're writing coercion glue so data can pass your own validator, the validator is the problem.
- How a Failed Junction Insert Left Me With Orphaned Rows
When you create a parent row and child junction rows in separate Supabase calls, you're responsible for rolling back. PostgREST gives you no transac
- How an Open Redirect Hid Inside Our Next.js Server Actions
If your Next.js server action does redirect(userInput) — even for something as innocent as a post-login bounce — you have an open redirect. The fix is
- Page Auth Doesn't Guard Server Actions — Every Action Needs Its Own Lock
In Next.js, protecting a page does NOT protect the server actions behind it. Every action is its own callable endpoint. Guard each one with require
- The API Won't Tell You When You're Paying Twice
Two separate gpt-4.1-mini calls doing the exact same extraction, added weeks apart. The API processed both happily. No error. No warning. Just a b
- The Supabase Linter Warning That Silently Empties Your Tables
rlsenablednopolicy looks scary. Whether it IS scary depends entirely on how your app connects to Postgres. Know your connection architecture
- Why I Stopped Letting Chat Failures Eat My Users' Words
Retry with backoff + draft persistence are the two things you add to any chat that talks to an LLM. One handles network flakes. The other means user
- Why I Stopped Trusting My Own Frontend
Your frontend can be bypassed in 30 seconds with curl. Validate everything server-side — IDs, tokens, route params — as if the client doesn't exis
- How Prisma's Nested Relation Creates Silently Ate My Sales Data
### the setup
- How Targeted Diagnostics Killed a Timezone Bug I'd Been Guessing At
I spent two deploys guessing at the wrong things. One targeted diagnostic commit found it in minutes. The bug was a timezone offset — server-rendere
- One Missing Env Var That Took Down Every Cron Job at Once
Requiring env vars at startup is good. Requiring every var in one shared list that every route calls is a trap — one missing secret nukes your
- The AI Recommendations Looked Great. The Data Was Lying.
I added AI-generated action plans to a webinar analytics dashboard. They looked polished and confident. They were confidently wrong — because the da
- The Metric Was Wrong Because the Baseline Was Wrong
Our watch-through metric looked terrible — until I realized we were measuring against the wrong thing entirely.
- The Timezone Bug That Taught Me to Measure From What You Trust
When your upstream data is corrupted, stop trying to clean it. Find a reference in your own system that you know is correct, and derive everything fro
- When Your Data Is Saving Fine and the Dashboard Still Lies to You
After a sales data import, the dashboard still showed old numbers. I rewrote the entire write path before realizing the data was saving perfectly. The R
- Why My GA4 Dashboard Worked Locally but Broke on Vercel Every Time
Vercel double-escapes in JSON env vars. One .replace() call and a try/catch fixes it. But the real lesson is the hardcoded fallbacks that wer
- How 'Belt-and-Suspenders' Broke My Swift Supabase Decoder
### The Setup
- How My iOS App Learned to Lie (And How I Fixed It)
If your Supabase database column can be NULL, your Swift Codable struct MUST declare it Optional. One mismatched type fails the entire query decode
- How One `await` Stopped My iOS CRM From Lying to Users
Optimistic form dismissal feels fast. It also hides every failure. Await the server. Then dismiss.
- The SupabaseClientOptions Argument Order Trap Nobody Warns You About
In Swift, named parameters to struct memberwise initializers must match declaration order — not the order that looks logical to you. Get it wro
- Why My Supabase iOS App Failed Silently — and It Was the Key Format
Supabase rolled out new-format API keys. The anon key is now sbpublishable..., not the old eyJ... JWT. If you're bootstrapping a Swift project
- Why Your Demo Mode Should Touch Zero Backend
For a demo, the backend is a liability. Kill it entirely. Hardcode the data, gate it behind a guest toggle, ship.
- What 'Replaced Element' Actually Means (and Why It Broke My Presentation Mode Canvas)
<canvas> is a replaced element. position:fixed; inset:0 will NOT size it to the viewport. Set explicit width:100vw; height:100vh in CSS AND si
- How a Swapped Argument Order Killed Our Supabase iOS Connection (Silently)
SupabaseClient got the URL and anon key swapped. Swift compiled it without complaint. Everything failed silently. The fix was one line.
- How Supabase's Batch Upsert Silently Swallowed Our Sales Data
Supabase's batch upsert silently turns missing keys into NULLs — which bypasses your schema defaults and can quietly discard your data. error === n
- Why I Built a Demo Mode That Never Touches the Backend
If you're demoing a Supabase-backed iOS app live, add a guest mode with hardcoded data. Eighty lines of Swift buys you a demo that runs in airplane