DIL.DEV
LOADING0%
DIL.DEV

NOTES

Engineering notes from building production systems.

What I built, the commands I ran, the numbers I measured and what I would change. Written for engineers.

NOTES BY EMAIL

  1. Resumable Line Provisioning: Save the Assistant ID Before the SIP Call A line create command for AI phone receptionists that resumes each step from what the client file already proves, with one critical ordering fix: persist the assistant ID before the SIP create. voice-agentsprovisioningvapiautomation
  2. PixiJS Sets touch-action: none, and Phones Stopped Scrolling Over the Photos PixiJS defaults to touch-action: none on its canvas, which silently kills page scroll on phones. Three CSS properties and a Playwright audit fix it for good. pixi.jsWebGLmobileplaywright
  3. PostgREST Stops at 1,000 Rows and the Dashboard Never Says So PostgREST silently caps unpaged selects at 1,000 rows. An admin dashboard counting synced jobs in memory showed 0 for newer users once the table grew past that limit. supabasepostgrestdebuggingadmin
  4. Pulling n8n Executions into Postgres: Oldest First, Replay-Safe, Blind to Hand Edits An edge function on a five-minute cron pulls n8n workflow executions into Postgres oldest-first, with replay safety proven across two backfills and 209 executions writing zero duplicate events. n8npostgrespg_cronevent-store
  5. A Fake SMS YES Could Have Won a Lead and Charged a Card An open webhook on a plumber lead network accepted any POST, meaning a spoofed YES could claim a lead and trigger a card charge. Basic auth fixed it with a zero-downtime rollout. webhookssecuritytwilion8n
  6. A Broadcast Tool for 860 Members Now Needs a Typed SEND One misclick in a members composer could mail 860 people instantly. Two commits fixed that: a typed confirm step and a split send-test endpoint. safetyadmin-uiapi-designemail
  7. Months of Green Ticks over a Cleanup Job That Never Deleted a File A scheduled cleanup reported success for months while doing nothing. pm2 never read the droplet .env, so CLEANUP_SECRET was undefined, every call got a 403, and an echo fallback swallowed the error. pm2devopsnodedebugging
  8. Stripe Redelivered a Stale payment_failed After the Customer Had Already Paid A checkout decline raised invoice.payment_failed before the subscription row existed, the handler threw, and Stripe redelivered the event after the customer paid, flipping them to past_due. stripewebhooksbillingsaas
  9. Choosing a Voice Agent's Transcriber by Measured Turn Latency Three transcribers failed or lagged before landing on Soniox primary with Deepgram fallback. The 1.8 s average from one provider caused the agent to cut callers off nine times. voice-aitranscriptionlatencysipmultilingual
  10. Tell a Model to Aim at the Floor and Half Its Drafts Fall Under It When the length target and the throw floor are the same number, the model clusters at it. Separating aim, expansion threshold, throw floor and ceiling fixed the distribution. llmcontent-pipelinen8nprompt-engineering
  11. Haiku Invented the Date on 10 of 18 Nightly Notes, So the Script Owns It Now A nightly capture job let Haiku write the H1 date and it hallucinated it on 10 of 18 notes. automationllmclaudeshell-scripting
  12. The Idle Watchdog That Killed Healthy Reasoning Models at 300 Seconds A file-size watchdog could not tell a thinking model from a wedged process. A throttled heartbeat sidecar fixed it without letting genuine wedges survive. shellai-toolingdebuggingstreaming
  13. My Agent Loop Marked 15 Tasks Done With No Tests Running Every gate stage defaulted to an empty string, so 15 tasks logged gate:none and the harness called the run clean. A severity-ladder preflight now blocks a hollow gate stack before task selection. agent-loopcitestingautomation
  14. Two Mobile Scroll-Video Bugs That Only Show Up on Real Phones iOS holds a paused video at readyState 1 so every seek stays pending and the frame paints black. A second bug: ScrollTrigger points computed once go stale when page content grows. iosvideoscrollIntersectionObserver
  15. Six Local Supabase Stacks, 61 Containers, and 96% Swap Running six local Supabase stacks simultaneously pushed swap to 96% and caused repeated OOM failures during db reset. The real lesson is surfacing infrastructure exhaustion before blaming your code. supabasedockerlocal-devdebugging
  16. The Silent Redirect That Made Uploads Vanish A submitted upload looked lost because a route redirect swallowed it into a magazine edition. Here is how the redirect was found and removed. routingnuxtdebugginguploads
  17. Notes Is Prerendered Markdown, Not a CMS How the dil.dev/notes pipeline works: markdown files, a Vite plugin, strict frontmatter validation, and no CMS in sight. vitemarkdownjson-ldstatic-site
  18. The Skull Turns Once Across Eight Stops, Newest First The home page is now the skull lab: a Tripo sugar-skull bust rotates one full revolution across eight project stops, driven entirely by scroll position. three.jsLenisscrollWebGL
  19. Reduced Motion Skips the Skull Engine and the Split Titles Reduced-motion visitors skip engine loading and SplitText entirely. The smoke transition falls back to plain navigation so nothing breaks. accessibilitygsapwebglpage-transitions
  20. Every Canonical on https://dil.dev, Including the Sitemap Every URL on dil.dev points its canonical, og:url and sitemap loc at the apex host. A postbuild script enforces this so a stray Netlify subdomain never leaks into the index. seocanonicalsitemapnetlify
  21. A Thank-You Page Visit Is Not a Lead Counting a thank-you page visit as a conversion inflates your lead numbers. Fire tracking only after Netlify acknowledges a real submission. netlifyanalyticsformsconversion
  22. Consent Under the Mark, Once, Never a Banner The preloader asks for analytics consent once, under the mark. No banner, no fixed control. Here is how the pattern works and why it holds. analyticsconsentGA4privacy
  23. Three Labels on a Tilted Ring Around the Skull, Dimming Behind It Year, stop count and VIEW orbit the skull on a tilted ring that dims labels as they pass behind it. This is the only place translate and parallax are permitted. three.jsWebGLscrollorbit
  24. A Hidden Instrument: Self-Hosted MediaPipe Hands, Camera Never Shown dil.dev has a browser instrument hidden behind three entry points. Start loads ~20 MB of self-hosted MediaPipe and Tone.js; the camera feed is never rendered or sent anywhere. mediapipetone.jswebglprivacy
  25. 58MB to 1.6MB: shipping a 3D face mesh with glTF-Transform and scroll-driven three.js An AI-generated head mesh came out at 57.97MB and 987,094 vertices. One glTF-Transform command took it to 1.61MB and 89,200 vertices for a scroll-driven three.js hero. three.jsWebGLglTFperformance
  26. Smoke page transitions: domain-warped fbm from the click point, checked in real Chrome A raw WebGL 1 shader blooms smoke from the click, swaps the page behind it without a reload, then drains toward the pointer. Plus the Playwright timing bug that made my checks sample 1.4s late. WebGLGLSLPlaywrighttesting
  27. Netlify config.path vs a netlify.toml redirect: why /api/* 404'd A forced /api/* rewrite pointed at /.netlify/functions/api, a URL that stops existing once a v2 function sets config.path. Every data route 404'd in production. The fix was deleting one redirect rule. Netlifyserverlessdebugging