Change the code, watch it react
181 runnable demos. Edit the HTML, CSS or JavaScript and it re-runs in your browser.

command / commandfor — interactive playground
Every <dialog> and popover in your app still needs an addEventListener just to open and close — commandfor and the Invoker Commands API let the browser do it with zero JavaScript.
Open the playground →
race condition — interactive playground
Type fast into a search box wired to fetch(), and the result on screen isn't from your last keystroke — it's from whichever request happened to finish last. That's a race condition, and the fix is a one-line guard.
Open the playground →
passive: true — interactive playground
Every touch and wheel listener you add can make the browser wait before it scrolls — because it has to check whether you'll call preventDefault(). `passive: true` tells it you won't, and scrolling stops waiting on your code.
Open the playground →
NestJS validationError.target — ValidationPipe playground
NestJS 12.2 defaults validationError.target to false, so a custom exceptionFactory reading error.target now gets undefined. The fix, plus a cheat sheet.
Open the playground →
btoa() vs toBase64() — interactive playground
btoa() throws on emoji, and the classic String.fromCharCode(...bytes) workaround crashes on large files. toBase64() and fromBase64() on Uint8Array fix both — no string round trip, no library.
Open the playground →
getCurrentPosition() — interactive playground
A "find my location" button that works instantly on your laptop and hangs forever on a phone with a weak signal isn't flaky — it's getCurrentPosition() doing exactly what its defaults tell it to do. No timeout, no cached position, and a watcher nobody told to stop.
Open the playground →
OffscreenCanvas — interactive playground
Click a button while your canvas animation is running and the whole page stalls — because the pixels it draws, your layout, and your input handling all queue up on the same main thread. OffscreenCanvas moves the drawing itself into a worker, so the UI keeps responding no matter how much canvas work is happening.
Open the playground →
Next.js ensureStatic — interactive playground
Next.js 16.4 stabilizes ensureStatic: lock a route's shell, prefetch, or full navigation to static output at build time, with a copy-paste cheat sheet.
Open the playground →
React <Activity> — interactive playground
React's Activity component hides a subtree without unmounting it — what state, effects, and renders actually do, plus a copy-paste cheat sheet.
Open the playground →
Vue provide/inject mutation trap — playground
Vue's guide says wrap provide() state in readonly() — most tutorials skip it. The mutation bug that causes, verified against Vue 3.5, plus a cheat sheet.
Open the playground →
scrollbar-gutter — interactive playground
Opening a modal shifts your whole page sideways because the scrollbar vanishes with it — the bug every scroll-lock library papers over with a JS width measurement and a padding-right hack. `scrollbar-gutter: stable` fixes it in one line now that Safari finally caught up.
Open the playground →
CSS relative color syntax — interactive playground
A design system ships one brand color and four hand-picked hex variants for hover, pressed, border, and tint. Change the brand color and four of those five silently go stale. CSS relative color syntax derives every variant from the one color you actually update.
Open the playground →
Pointer Events — drag without losing the pointer
A draggable card that works with mousedown/mousemove on desktop and breaks the moment you test it on a phone. The fix isn't a second set of touch listeners — it's deleting the mouse ones and switching to Pointer Events, which was built to handle mouse, touch, and pen as one input.
Open the playground →
NestJS 12 @Optional() inheritance — interactive playground
NestJS 12 stops inheriting @Optional() once a subclass redeclares its own constructor — not when it has none at all. Cheat sheet included.
Open the playground →
CSS Grid Lanes — native masonry, DOM order intact
Masonry layouts have meant a JS library or a CSS column-count hack that scrambles reading order ever since Pinterest made the look popular. CSS Grid Lanes finally does it natively — here's the real support story and how to ship it today.
Open the playground →
font-display: swap — the layout shift it leaves behind
Setting font-display: swap kills the flash of invisible text, so most teams call the font-loading problem solved and move on. It doesn't — it just trades FOIT for a layout shift Lighthouse will happily dock you for. Here's the actual fix.
Open the playground →
form.submit() vs requestSubmit() — interactive playground
A Save button living outside the <form> tag, wired to form.submit(), looks like it works — until a blank required field sails through and the page does a full reload your fetch handler never saw coming. requestSubmit() is the method that actually clicks the button for you.
Open the playground →
updateTag vs revalidateTag — interactive playground
Next.js 16 deprecated revalidateTag's single-argument call and added updateTag. What the new profile argument changes, plus a copy-paste cheat sheet.
Open the playground →
Is the header actually stuck? — scroll-state() vs IntersectionObserver
A sticky header that should only cast a shadow once it's actually stuck to the top usually means a hidden sentinel div and an IntersectionObserver. CSS now tracks that state itself — the `scroll-state()` container query reads it directly, no sentinel, no observer, no JS math.
Open the playground →
Vue v-for directive unmounted hook — interactive playground
A custom directive's unmounted hook could silently skip firing inside a keyed v-for list. The directive unmounted hook bug, Vue's real fix, and a cheat sheet.
Open the playground →
requestAnimationFrame vs debounce vs timer-throttle — interactive playground
Debouncing a scroll handler makes it wait until scrolling stops — which is why your sticky header always lags half a beat. requestAnimationFrame fixes the lag by syncing updates to the browser's own paint clock instead of a timer.
Open the playground →
as const — catch the missing case, not the bug report
Object and array literals widen to `string` and `number` the moment you write them, which quietly breaks discriminated unions and exhaustive switch checks. `as const` keeps the literal types — but it also freezes the value, which bites in its own way.
Open the playground →
Nuxt 4.6 nuxt/server — import-boundary playground
Nuxt 4.6 added a new nuxt/server import source alongside h3 — mix the two in one handler and you hit NUXT_E8012. The real boundary, plus a cheat sheet.
Open the playground →
Catch the tear — useSyncExternalStore playground
A useState + useEffect hook that subscribes to window size, localStorage, or a WebSocket looks fine until React 18's concurrent rendering shows two parts of your UI two different values at once. useSyncExternalStore is the hook built to stop that.
Open the playground →
NestJS lifecycle hook order — interactive playground
NestJS 12 changed how lifecycle hooks are ordered. Learn what onModuleInit and onApplicationBootstrap really guarantee, plus a copy-paste cheat sheet.
Open the playground →
translate / rotate / scale — interactive playground
A CSS :hover scale and a JS drag handler both write to `transform` — and the moment JS sets it, the hover rule silently stops working, no error, no warning. The `translate`, `rotate`, and `scale` properties exist so this never happens.
Open the playground →
fetchpriority — interactive playground
Your hero image is losing a bandwidth fight against a web font and a chat-widget script — fetchpriority tells the browser which request actually matters first.
Open the playground →
Next.js Instant Navigations — interactive playground
Next.js 16.3 shipped Instant Navigations: Partial Prefetching plus the App Shell. Learn the model, the Suspense gotcha, and a copy-paste cheat sheet.
Open the playground →
Intl.NumberFormat vs. hand-rolled formatMoney()
A hand-rolled formatMoney() with toFixed() and a comma regex looks fine in a US demo and quietly breaks the moment a real user, a negative balance, or a non-dollar locale shows up. Intl.NumberFormat has handled all of it, built into every modern browser, since before most teams' codebases existed.
Open the playground →
Vue 3.6 notify buffer & flush() — interactive playground
A Vue 3.6 reactivity regression let a throwing watcher silently stall its siblings. The exact flush() mechanism, the fix, and a copy-paste cheat sheet.
Open the playground →
Layout thrashing — interactive playground
An 'expand all' click that stutters isn't a slow CPU — it's layout thrashing, a loop that forces the browser to recalculate layout once per row instead of once per click. Here's how to spot it and the two-line fix.
Open the playground →
Nuxt useSession — seal, tamper & wrong-secret playground
Nuxt 4.6 ships useSession and runtimeConfig.appSecret — real, sealed-cookie sessions with no database or session store. How it works, plus a cheat sheet.
Open the playground →
forced-colors mode — interactive playground
Windows High Contrast Mode doesn't just boost contrast — it strips your backgrounds, shadows, and colors outright. Here's what `forced-colors` actually does, why a styled <div> vanishes while a real <button> survives, and the fix.
Open the playground →
useEffectEvent vs the deps array — interactive playground
React's useEffectEvent (stable in 19.2) kills stale closures in Effects without a ref trick — but it's not a deps-array shortcut. Guide + cheat sheet.
Open the playground →
Inferred type predicates — interactive playground
TypeScript 5.5 added inferred type predicates, and the internet decided that meant filter(Boolean) finally narrows. It doesn't. Here's exactly what the feature fixed, why the mix-up happened, and the one-line pattern that actually gets you type-safe filtering.
Open the playground →
CSS contain — draw the boundary
A live counter or chat widget shouldn't make the rest of your page recompute layout every time it updates. The CSS contain property draws a hard boundary the browser can actually trust — here's what it promises, and the one gotcha that breaks pages when people misuse it.
Open the playground →
SharedWorker — interactive playground
Electing a leader tab to own one shared WebSocket works great — until the leader is the tab someone closes. SharedWorker skips the election: the connection lives in the worker, not in any tab, so there's no leader to lose.
Open the playground →
CLS session windows — interactive playground
The web-vitals npm package gets credit for data your browser already computes. Here's what three PerformanceObserver calls give you for free — and the one piece of math it quietly saves you from getting wrong.
Open the playground →
Tab leader election — interactive playground
Six open tabs means six live connections to your server, six duplicate pushes, six timers draining the battery. navigator.locks elects a single leader tab to hold the real connection — the rest just listen.
Open the playground →
Next.js 16 Image pipeline — interactive playground
Next.js 16 quietly deprecated Image's priority for preload and restricts quality to an allowlist (default: 75). What breaks, plus a copy-paste cheat sheet.
Open the playground →
Vue watch vs watchEffect — race condition playground
Vue's watch() and watchEffect() look interchangeable but track dependencies, run timing, and cleanup differently. The exact rules, verified against Vue 3.5.
Open the playground →
Service worker deploy — interactive playground
A critical bug fix went out, and support tickets kept coming in from people who swore they'd refreshed. The code was fine. The service worker's cache-first strategy was doing its job perfectly — which was the whole problem.
Open the playground →
Nuxt 4 Singleton Data Fetching Layer — interactive model
Nuxt 3 reached end-of-life on July 31, 2026. Here's exactly what breaks moving to Nuxt 4 — directories, data fetching, TypeScript — plus a cheat sheet.
Open the playground →
Long Animation Frames — interactive playground
Lighthouse says 100 and CI is green, but a user still says the filter button feels sluggish. The Long Animation Frames API names the exact script and phase that blocked the frame — here's how to read it instead of squinting at a flame chart.
Open the playground →
React Fragment Refs — interactive playground
React 19.3 Fragment Refs let you ref a sibling group with no wrapper div. Learn the FragmentInstance API, its limits, and get a copy-paste cheat sheet.
Open the playground →
will-change — interactive playground
will-change: transform looks like a free performance switch. Applied broadly or left on permanently, it does the opposite — here's the narrow, temporary pattern that actually works.
Open the playground →
prefers-reduced-motion — interactive playground
Most animated UIs never check whether the visitor asked for less motion. `prefers-reduced-motion` is the CSS media feature that tells you — and a fail-closed pattern keeps you honest even when a browser doesn't support it.
Open the playground →
unhandledrejection — interactive playground
A rejected promise with no .catch doesn't crash and doesn't show up in your error tracker — it just disappears. The unhandledrejection event is the global safety net most apps never wire up.
Open the playground →
Exponential backoff — interactive playground
Retrying a failed fetch() right away feels responsible — until the server that failed was already overloaded, and five instant retries per client turn a blip into an outage. Exponential backoff with jitter is the fix.
Open the playground →
storage event — cross-tab playground
A cross-tab 'log out everywhere' feature built on the storage event worked in every tab except the one the user actually clicked in. The storage event never fires in the tab that made the change — and that's spec, not a bug.
Open the playground →
Next.js streaming metadata — interactive playground
Next.js 16 streaming metadata sends users a page before generateMetadata resolves, but blocks crawlers for a complete head. How it works, plus a cheat sheet.
Open the playground →
Vue defineModel & the v-model contract — interactive playground
Vue's defineModel macro replaces the modelValue prop and update:modelValue event with one ref. The exact v-model contract behind it, verified against Vue 3.5.
Open the playground →
bfcache eligibility — interactive playground
A `beforeunload` listener you left mounted forever can still quietly cost you bfcache eligibility — and an `unload` listener reliably will. Here's the pagehide/pageshow fix, and why 'mount it only when there's something to lose' is the durable rule.
Open the playground →
Nuxt SSR streaming — route rule & response-timeline playground
Nuxt 4.5's experimental SSR streaming flushes HTML early, but cache, isr, swr, redirect, and ssr:false route rules silently fall back to buffering. Cheat sheet included.
Open the playground →
<details name> — native accordion playground
You've probably shipped an accordion with a hand-rolled 'close the other panels' loop in JavaScript. The `name` attribute on <details> does it natively — no JS, no ARIA plumbing.
Open the playground →
React ViewTransition — interactive playground
React 19.3's ViewTransition component animates state changes, not just page swaps — the mental model, enter/exit/update/share, and a cheat sheet.
Open the playground →
useTransition vs. blocking re-renders — interactive playground
A big list re-render was blocking every keystroke — debouncing just moved the freeze. useTransition tells React which update can wait.
Open the playground →
NestJS Standard Schema validation — pipe playground
NestJS 12 adds Standard Schema validation for @Body(), @Query(), and @Param() — validate with Zod or Valibot, no class-validator DTO. Cheat sheet included.
Open the playground →
text-box-trim — the headline gap playground
Line-height reserves space for accent marks your headline never uses — a hand-tuned negative margin only fixes it for one font at one size. text-box-trim does, natively, from the font's own metrics.
Open the playground →
:nth-child(of) — interactive playground
nth-child(even) counts every element in the DOM, including the ones you just hid with display:none. The fix isn't JavaScript — it's a CSS selector most people have never had a reason to use.
Open the playground →