{"count":8,"posts":[{"slug":"matter-js-preventdefault-traps-page-scroll","title":"Matter.js calls preventDefault on every touch, and traps your page","summary":"A physics toy on a phone stopped the page scrolling. Not when you touched an object — when you touched anywhere near it.","date":"2026-08-06","tags":["JavaScript","Mobile","Canvas"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/matter-js-preventdefault-traps-page-scroll.webp"},{"slug":"a-portalled-dialog-does-not-fire-reacts-onclose","title":"A portalled <dialog> does not fire React's onClose","summary":"Closing the modal left the app permanently frozen. The event was firing. React just was not listening for it.","date":"2026-07-30","tags":["React","Accessibility","Debugging"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/a-portalled-dialog-does-not-fire-reacts-onclose.webp"},{"slug":"multi-tenant-isolation-belongs-in-the-data-layer","title":"Multi-tenant isolation belongs in the data layer, not in every query","summary":"One endpoint missing a WHERE clause shows one customer another customer's drafts. You find out from the customer.","date":"2026-07-23","tags":["SaaS","PostgreSQL","Architecture"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/multi-tenant-isolation-belongs-in-the-data-layer.webp"},{"slug":"designing-for-a-spike-not-an-average","title":"Designing for the spike, not the average","summary":"A platform that is quiet for days and then serves an entire region inside two minutes. The load shape decided the architecture before any feature did.","date":"2026-07-16","tags":["Architecture","AWS","Scaling"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/designing-for-a-spike-not-an-average.webp"},{"slug":"cloudflare-workers-assets-caching-default","title":"Cloudflare was revalidating every hashed asset on every page load","summary":"Workers Assets ships a default cache header that is correct for hand-written files and wrong for every file a bundler emits.","date":"2026-07-09","tags":["Cloudflare","Performance","Deployment"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/cloudflare-workers-assets-caching-default.webp"},{"slug":"setpointercapture-on-pointerdown-kills-your-click","title":"setPointerCapture on pointerdown silently kills every click","summary":"A draggable marquee where none of the cards were clickable. The drag code was correct. It was one line, in the wrong handler.","date":"2026-07-02","tags":["JavaScript","UI","Debugging"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/setpointercapture-on-pointerdown-kills-your-click.webp"},{"slug":"never-trust-the-delta-your-frame-loop-hands-you","title":"Never trust the delta your frame loop hands you","summary":"An unclamped frame delta made a WebGL hero teleport instead of resume, and pushed an interpolation past its target into negative values.","date":"2026-06-25","tags":["Animation","Performance","WebGL"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/never-trust-the-delta-your-frame-loop-hands-you.webp"},{"slug":"overflow-x-auto-makes-a-vertical-scroll-container","title":"overflow-x: auto quietly makes a vertical scroll container too","summary":"Three full-bleed carousels on a phone ate every upward swipe. The cause was one line of CSS that does something the property name does not say.","date":"2026-06-18","tags":["CSS","Mobile","Debugging"],"readingMinutes":2,"coverUrl":"https://cdn.syedtasavour.com/covers/v2/overflow-x-auto-makes-a-vertical-scroll-container.webp"}]}