Writing from the workshop
123 articles on the parts that actually hurt.

Your Browser Is Rejecting Every Drop On Purpose
A drop zone with a correctly wired drop listener that never fires — no error, no typo, nothing in the console. The browser is silently refusing the drop by design, and only one specific line stops it.
Sep 20, 2026 · 6 min
Nuxt Hydration Mismatch: Why It Happens and How to Fix It
A Nuxt hydration mismatch happens when the server's HTML disagrees with the client's first render. Learn why, and the fixes that actually work.
Sep 20, 2026 · 14 min
Chrome Already Has The Eyedropper You're Building
You're about to build a canvas-based color picker with a magnifier loupe. Chrome shipped a native one years ago — and it can sample pixels your own canvas can't even see.
Sep 20, 2026 · 5 min
NestJS Testing Module: Provider Overrides (with Cheat Sheet)
A complete guide to NestJS's testing module: how overrideProvider really wires mocks, why get() fails on scoped providers, and using useMocker.
Sep 18, 2026 · 13 min
The CSS Property That Fixes Dark Mode's Ugly White Boxes
You shipped dark mode. The page is black, the text is white — and then the date picker opens like a floodlight. color-scheme is the one-line CSS property that tells the browser your native form controls need to catch up too.
Sep 18, 2026 · 4 min
Stop Debouncing Resize. The Browser Already Watches It.
A debounced resize handler comparing window.innerWidth to a magic number can't ever see dark mode or reduced motion — and it fires dozens of times for one thing matchMedia fires once for.
Sep 17, 2026 · 6 min
Your Fetch Already Streams. You're Buffering It Anyway.
A chat UI that types out its reply letter by letter isn't proof it's streaming — it's often proof the opposite. fetch() delivers a real ReadableStream body, and most code drains it into one string before showing a single character.
Sep 16, 2026 · 5 min