[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"path-frontend-developer":44,"search-suggestions":627,"checkpoint-frontend-developer-html":667},[4,20,32],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Read it. Run it. Prove it.","A post a day on modern web development — most with an editable playground and a quiz that explains every answer. Free, no account needed.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Grammar explained the way good documentation explains an API — one idea at a time, each with a quiz.","amber-400","⌘",[13,15,29],"es",{"courses":18,"paths":18,"articles":17,"exams":18,"flashcards":17,"packages":18,"community":17,"certificates":17,"teams":18,"commerce":18},2,{"id":33,"slug":34,"name":35,"tagline":36,"description":37,"accentFrom":38,"accentTo":39,"icon":40,"defaultLocale":13,"locales":41,"features":42,"position":43},"7b3c16f2-931d-410e-802e-e1fa4edab7de","soft","Soft Skills","The half of the job nobody wrote documentation for.","Weekly, on the parts of working life that decide more than your code does — first weeks, meetings, interviews, promotions, and the people around you. Written from what actually happens, and recorded as a podcast you can listen to on the walk.","emerald-400","teal-300","◉",[13],{"courses":18,"paths":18,"articles":17,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":18},3,{"id":45,"slug":46,"title":47,"summary":48,"level":49,"estimatedHours":50,"accentFrom":10,"accentTo":11,"publishedAt":51,"updatedAt":52,"vertical":53,"zones":54},"019fe637-5509-7339-bbc2-527fe921588b","frontend-developer","Frontend Developer","HTML and CSS first, then JavaScript, then Vue or React — every level an article and a quiz, every zone a checkpoint that opens the next.","BEGINNER",16,"2026-10-14T13:14:20.175Z","2026-10-14T13:14:20.192Z",{"slug":6,"name":7},[55,118,185,261,337,401,462,523,567],{"slug":56,"tier":57,"title":58,"summary":59,"icon":60,"accent":61,"unlockedBy":62,"checkpoint":63,"levels":68},"html",1,"HTML","The document under every page — elements that mean something, and the native ones that replace a JavaScript library.","i-simple-icons-html5","orange-500",[],{"id":64,"slug":65,"questionCount":66,"passScorePct":67},"01a13a8c-adcd-7308-9c1f-787e803094cd","frontend-developer--html-checkpoint",10,70,[69,73,85,97,108],{"id":70,"label":71,"soon":17,"article":72,"quiz":72},"01a13a8c-af08-7228-a6be-8e3a9a101d43","HTML from zero",null,{"id":74,"label":75,"soon":18,"article":76,"quiz":82},"01a13a8c-af08-7228-a6be-928a0c118889","Native \u003Cdialog>",{"slug":77,"title":78,"excerpt":79,"readingMinutes":80,"coverUrl":81},"dialog-element-native-modal","You built your modal with a `\u003Cdiv>` and a focus trap library. The native `\u003Cdialog>` does all of that.","The `\u003Cdialog>` element ships with focus trapping, Escape-to-close, backdrop rendering, and correct ARIA semantics — no library, no boilerplate. It's been Baseline since 2022.",5,"\u002Fmedia\u002Fcovers\u002Fdialog-element-native-modal.png",{"id":83,"slug":77,"questionCount":84},"019ff19b-f3ba-73aa-9313-c2d3237b0363",8,{"id":86,"label":87,"soon":18,"article":88,"quiz":94},"01a13a8c-af08-7228-a6be-96b69ebff266","Exclusive accordions",{"slug":89,"title":90,"excerpt":91,"readingMinutes":92,"coverUrl":93},"details-name-exclusive-accordion","Stop Hand-Rolling an Exclusive Accordion. `\u003Cdetails name>` Does It","You've probably shipped an accordion with a hand-rolled 'close the other panels' loop in JavaScript. The `name` attribute on \u003Cdetails> does it natively — no JS, no ARIA plumbing.",6,"\u002Fmedia\u002Fcovers\u002Fdetails-name-exclusive-accordion.png",{"id":95,"slug":89,"questionCount":96},"01a0ec73-28e1-74cf-85ab-6b161a962d6d",7,{"id":98,"label":99,"soon":18,"article":100,"quiz":106},"01a13a8c-af09-70dc-990e-837615bd5c63","Popover API",{"slug":101,"title":102,"excerpt":103,"readingMinutes":104,"coverUrl":105},"popover-api-native-popovers","Your dropdown is a div. The browser has a native popover now.","Custom dropdowns, tooltips, and menus built with stacked divs and click-outside listeners — the Popover API landed in every browser in 2024, and the baseline version is two HTML attributes.",4,"\u002Fmedia\u002Fcovers\u002Fpopover-api-native-popovers.png",{"id":107,"slug":101,"questionCount":92},"019fe776-3af6-756b-9681-39d9647f7091",{"id":109,"label":110,"soon":18,"article":111,"quiz":116},"01a13a8c-af09-70dc-990e-87efd56ed87b","The inert attribute",{"slug":112,"title":113,"excerpt":114,"readingMinutes":92,"coverUrl":115},"inert-attribute-disable-interaction","The Modal Was Open. So Was Everything Behind It.","A keyboard-only pass found a background button still worked while a modal was open — aria-hidden had hidden it from screen readers but never touched focus or clicks. One boolean attribute, inert, closes that gap in a single line.","\u002Fmedia\u002Fcovers\u002Finert-attribute-disable-interaction.png",{"id":117,"slug":112,"questionCount":96},"01a00e88-ab11-755d-af3b-98caa9199cc8",{"slug":119,"tier":31,"title":120,"summary":121,"icon":122,"accent":123,"unlockedBy":124,"checkpoint":125,"levels":128},"css","CSS","The box model, the cascade, layout and responsive type — the parts of CSS that decide whether a page holds together.","i-simple-icons-css","blue-500",[56],{"id":126,"slug":127,"questionCount":66,"passScorePct":67},"01a13a8c-af54-766e-9649-28226faa3d0b","frontend-developer--css-checkpoint",[129,132,135,145,155,165,175],{"id":130,"label":131,"soon":17,"article":72,"quiz":72},"01a13a8c-b063-733f-91e0-251d48bc1b78","Box model & cascade",{"id":133,"label":134,"soon":17,"article":72,"quiz":72},"01a13a8c-b063-733f-91e0-2985218a51cc","Flexbox",{"id":136,"label":137,"soon":18,"article":138,"quiz":143},"01a13a8c-b063-733f-91e0-2cc952705ce9","Specificity with :where()",{"slug":139,"title":140,"excerpt":141,"readingMinutes":80,"coverUrl":142},"css-where-is-specificity-control","The CSS Selector Built to Lose Every Fight","You keep reaching for !important to override a component's styles. There's a selector that fixes this by contributing zero specificity, on purpose.","\u002Fmedia\u002Fcovers\u002Fcss-where-is-specificity-control.png",{"id":144,"slug":139,"questionCount":84},"01a018ca-5a2f-7303-93e4-3d47d70b34fd",{"id":146,"label":147,"soon":18,"article":148,"quiz":153},"01a13a8c-b063-733f-91e0-33c5a731bd0a","Grid: auto-fit vs auto-fill",{"slug":149,"title":150,"excerpt":151,"readingMinutes":80,"coverUrl":152},"css-grid-auto-fit-vs-auto-fill","Your Grid Has Invisible Columns: auto-fill vs auto-fit","A responsive card grid that works perfectly with twelve items breaks with two — not from a bug, but from one word in a repeat() you copy-pasted without reading.","\u002Fmedia\u002Fcovers\u002Fcss-grid-auto-fit-vs-auto-fill.png",{"id":154,"slug":149,"questionCount":84},"01a02d61-1a1e-76db-8406-a973a6965950",{"id":156,"label":157,"soon":18,"article":158,"quiz":163},"01a13a8c-b063-733f-91e0-359edbcaac27","Fluid type with clamp()",{"slug":159,"title":160,"excerpt":161,"readingMinutes":80,"coverUrl":162},"css-clamp-fluid-typography","Stop Writing Media Queries for Font Size","A design system audit found five breakpoints for one heading. clamp() replaces all of them with one line that never jumps.","\u002Fmedia\u002Fcovers\u002Fcss-clamp-fluid-typography.png",{"id":164,"slug":159,"questionCount":84},"01a0042a-85ad-75ae-bd1f-c727da9a8f79",{"id":166,"label":167,"soon":18,"article":168,"quiz":173},"01a13a8c-b063-733f-91e0-399027db471f","Viewport units: dvh, svh, lvh",{"slug":169,"title":170,"excerpt":171,"readingMinutes":92,"coverUrl":172},"css-dynamic-viewport-units-dvh-svh-lvh","Stop Writing JavaScript To Fix `100vh` On Mobile","Your full-screen hero looks perfect in the simulator and cuts off the CTA on a real phone. It's not a bug in your code — it's `vh` answering a question you didn't ask. Three new units fix it with zero JavaScript.","\u002Fmedia\u002Fcovers\u002Fcss-dynamic-viewport-units-dvh-svh-lvh.png",{"id":174,"slug":169,"questionCount":96},"01a0af18-2529-7212-bebc-55f06913a310",{"id":176,"label":177,"soon":18,"article":178,"quiz":183},"01a13a8c-b063-733f-91e0-3e895353d707","Focus rings that work",{"slug":179,"title":180,"excerpt":181,"readingMinutes":104,"coverUrl":182},"css-focus-visible-keyboard-focus-rings","Stop Using outline: none. Use :focus-visible Instead.","A designer flags the ugly blue focus ring in review. An engineer deletes it with outline: none. Nobody notices the keyboard-only user who now can't tell where they are on the page.","\u002Fmedia\u002Fcovers\u002Fcss-focus-visible-keyboard-focus-rings.png",{"id":184,"slug":179,"questionCount":92},"01a03297-a328-752b-8d64-3b72182313bb",{"slug":186,"tier":43,"title":187,"summary":188,"icon":189,"accent":26,"unlockedBy":190,"checkpoint":191,"levels":194},"javascript","JavaScript","How the language actually runs: scope and closures, the event loop, promises, and not mutating what you do not own.","i-simple-icons-javascript",[119],{"id":192,"slug":193,"questionCount":66,"passScorePct":67},"01a13a8c-b0a6-753c-a6e4-691cd005fe38","frontend-developer--javascript-checkpoint",[195,198,209,221,231,241,251],{"id":196,"label":197,"soon":17,"article":72,"quiz":72},"01a13a8c-b1b4-74aa-b784-0764b13fc529","JavaScript from zero",{"id":199,"label":200,"soon":18,"article":201,"quiz":207},"01a13a8c-b1b4-74aa-b784-0b65daadf8dc","Closures",{"slug":202,"title":203,"excerpt":204,"readingMinutes":205,"coverUrl":206},"weekly-javascript-closures","JavaScript Closures: The Complete Guide (with Cheat Sheet)","Learn how JavaScript closures really work — lexical scope, private state, memoization, and the classic loop bug — with worked examples and a cheat sheet.",14,"\u002Fmedia\u002Fcovers\u002Fweekly-javascript-closures.png",{"id":208,"slug":202,"questionCount":84},"019fe776-de6c-7405-a6f8-ad7095176a46",{"id":210,"label":211,"soon":18,"article":212,"quiz":218},"01a13a8c-b1b4-74aa-b784-0d89e4f45c1d","The event loop",{"slug":213,"title":214,"excerpt":215,"readingMinutes":216,"coverUrl":217},"weekly-javascript-event-loop","JavaScript Event Loop Explained: The Complete Guide","Learn how the JavaScript event loop really works — call stack, microtasks, and macrotasks — with worked examples, edge cases, and a cheat sheet.",13,"\u002Fmedia\u002Fcovers\u002Fweekly-javascript-event-loop.png",{"id":219,"slug":213,"questionCount":220},"019fe776-44c6-72df-b609-831c84cffcf6",9,{"id":222,"label":223,"soon":18,"article":224,"quiz":229},"01a13a8c-b1b4-74aa-b784-1389022105b1","Promise concurrency",{"slug":225,"title":226,"excerpt":227,"readingMinutes":80,"coverUrl":228},"promise-concurrency-all-settled-any-race","You reach for `Promise.all` for every concurrent request. Here's when to use the other three.","`Promise.all` fails the moment any one request fails. `allSettled`, `any`, and `race` each solve a different concurrency problem — dashboard partial results, CDN failover, and timeouts. Here's the taxonomy.","\u002Fmedia\u002Fcovers\u002Fpromise-concurrency-all-settled-any-race.png",{"id":230,"slug":225,"questionCount":92},"019fe776-3f54-779c-9eda-d4fc6ef32b0a",{"id":232,"label":233,"soon":18,"article":234,"quiz":239},"01a13a8c-b1b4-74aa-b784-17d8baccd60a","Immutable array methods",{"slug":235,"title":236,"excerpt":237,"readingMinutes":80,"coverUrl":238},"immutable-array-methods","Your `.sort()` is mutating state. JavaScript finally gave you the fix.","The classic array methods — sort, reverse, splice — mutate the original array, silently breaking React state updates and surprising anyone who forgot to spread first. ES2023 added four immutable counterparts: toSorted, toReversed, toSpliced, and with.","\u002Fmedia\u002Fcovers\u002Fimmutable-array-methods.png",{"id":240,"slug":235,"questionCount":92},"019fe776-4d12-75fc-b42d-9375ffd5fe8c",{"id":242,"label":243,"soon":18,"article":244,"quiz":249},"01a13a8c-b1b4-74aa-b784-195516ff3d4d","Debounce & throttle",{"slug":245,"title":246,"excerpt":247,"readingMinutes":205,"coverUrl":248},"weekly-debounce-and-throttle","Debounce and Throttle in JavaScript: The Complete Guide","Learn debounce and throttle in JavaScript step by step, with worked examples, edge cases, and a copy-paste cheat sheet for search, scroll, and resize.","\u002Fmedia\u002Fcovers\u002Fweekly-debounce-and-throttle.png",{"id":250,"slug":245,"questionCount":84},"019ff73a-fb9f-7786-9533-1f17ba3783af",{"id":252,"label":253,"soon":18,"article":254,"quiz":259},"01a13a8c-b1b4-74aa-b784-1e20ca438436","Retries with backoff",{"slug":255,"title":256,"excerpt":257,"readingMinutes":92,"coverUrl":258},"fetch-retry-exponential-backoff","Stop Retrying Immediately. Exponential Backoff Fixes It.","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.","\u002Fmedia\u002Fcovers\u002Ffetch-retry-exponential-backoff.png",{"id":260,"slug":255,"questionCount":84},"01a0fb3c-4ed5-749b-8bd5-67e5a44a923c",{"slug":262,"tier":104,"title":263,"summary":264,"icon":265,"accent":266,"unlockedBy":267,"checkpoint":268,"levels":271},"vue","Vue","Reactivity is the whole framework. What Vue tracks, when it updates the DOM, and the traps that only look like Vue bugs.","i-simple-icons-vuedotjs","emerald-500",[186],{"id":269,"slug":270,"questionCount":66,"passScorePct":67},"01a13a8c-b1f5-706d-86ae-ee6bc1e8272f","frontend-developer--vue-checkpoint",[272,275,285,296,307,317,327],{"id":273,"label":274,"soon":17,"article":72,"quiz":72},"01a13a8c-b308-728b-a55a-e66f4fd0a489","Vue from zero",{"id":276,"label":277,"soon":18,"article":278,"quiz":283},"01a13a8c-b308-728b-a55a-e86ebc627ec1","ref vs reactive",{"slug":279,"title":280,"excerpt":281,"readingMinutes":205,"coverUrl":282},"vue-weekly-reactivity-ref-vs-reactive","Vue Reactivity Explained: ref vs reactive (+ Cheat Sheet)","A complete guide to Vue reactivity: how ref and reactive really work, why destructuring breaks updates, when to use each, and a copy-paste cheat sheet.","\u002Fmedia\u002Fcovers\u002Fvue-weekly-reactivity-ref-vs-reactive.png",{"id":284,"slug":279,"questionCount":84},"01a03410-2e39-77b0-b6fc-7e6bfc919301",{"id":286,"label":287,"soon":18,"article":288,"quiz":294},"01a13a8c-b309-72e6-9a52-ca90ce8a20a9","computed() caching",{"slug":289,"title":290,"excerpt":291,"readingMinutes":292,"coverUrl":293},"vue-weekly-computed-caching-invalidation","Vue computed(): What It Caches and When It Reruns","Vue's computed() caches its result and only reruns when a tracked dependency changes, not on every read. The exact caching and invalidation model, verified against Vue 3.5.",12,"\u002Fmedia\u002Fcovers\u002Fvue-weekly-computed-caching-invalidation.png",{"id":295,"slug":289,"questionCount":84},"01a08af7-9e26-778b-b5d7-af0317eabe59",{"id":297,"label":298,"soon":18,"article":299,"quiz":305},"01a13a8c-b309-72e6-9a52-cc885a6b60e7","watch vs watchEffect",{"slug":300,"title":301,"excerpt":302,"readingMinutes":303,"coverUrl":304},"vue-weekly-watch-vs-watcheffect","Vue watch vs watchEffect: The Complete Guide","Vue's watch() and watchEffect() look interchangeable but track dependencies, run timing, and cleanup differently. The exact rules, verified against Vue 3.5.",15,"\u002Fmedia\u002Fcovers\u002Fvue-weekly-watch-vs-watcheffect.png",{"id":306,"slug":300,"questionCount":220},"01a0ec73-2f40-7369-a7f5-edde626bf628",{"id":308,"label":309,"soon":18,"article":310,"quiz":315},"01a13a8c-b309-72e6-9a52-d2623683c64e","nextTick & batching",{"slug":311,"title":312,"excerpt":313,"readingMinutes":216,"coverUrl":314},"vue-weekly-nexttick-batching-dom-updates","Vue nextTick Explained: How DOM Updates Are Batched","How Vue batches reactive writes into one DOM update, why the DOM looks stale right after a change, and how nextTick and watch's flush option fix it.","\u002Fmedia\u002Fcovers\u002Fvue-weekly-nexttick-batching-dom-updates.png",{"id":316,"slug":311,"questionCount":84},"01a04446-5aa3-7645-92d4-1f30c918311a",{"id":318,"label":319,"soon":18,"article":320,"quiz":325},"01a13a8c-b309-72e6-9a52-d71ea0f7fa11","defineModel",{"slug":321,"title":322,"excerpt":323,"readingMinutes":216,"coverUrl":324},"vue-weekly-definemodel-v-model-contract","Vue defineModel: The v-model Contract, Explained","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.","\u002Fmedia\u002Fcovers\u002Fvue-weekly-definemodel-v-model-contract.png",{"id":326,"slug":321,"questionCount":220},"01a0af18-2e09-770d-907e-a11709e4d355",{"id":328,"label":329,"soon":18,"article":330,"quiz":335},"01a13a8c-b309-72e6-9a52-dbb4575d4969","Composables & shared state",{"slug":331,"title":332,"excerpt":333,"readingMinutes":216,"coverUrl":334},"vue-weekly-composables-shared-state-trap","Vue Composables: The Shared State Trap (+ Cheat Sheet)","Why two Vue components using the same composable can end up sharing state by accident, the mental model that explains it, and how to fix or embrace it.","\u002Fmedia\u002Fcovers\u002Fvue-weekly-composables-shared-state-trap.png",{"id":336,"slug":331,"questionCount":96},"01a066ea-30d4-77af-87a7-5118d8a617a1",{"slug":338,"tier":104,"title":339,"summary":340,"icon":341,"accent":342,"unlockedBy":343,"checkpoint":344,"levels":347},"react","React","Rendering is the whole framework. When React re-renders, what it keeps between renders, and the state bugs it makes easy.","i-simple-icons-react","sky-400",[186],{"id":345,"slug":346,"questionCount":66,"passScorePct":67},"01a13a8c-b34a-7622-94de-58b16d96660e","frontend-developer--react-checkpoint",[348,351,361,371,381,391],{"id":349,"label":350,"soon":17,"article":72,"quiz":72},"01a13a8c-b452-710f-9980-027a85cf0060","React from zero",{"id":352,"label":353,"soon":18,"article":354,"quiz":359},"01a13a8c-b452-710f-9980-04f57b7c8578","Re-render vs remount",{"slug":355,"title":356,"excerpt":357,"readingMinutes":216,"coverUrl":358},"react-weekly-rerender-vs-remount","React Re-render vs Remount: What Actually Triggers Each","A practical guide to React re-render vs remount: what type, position, and key decide, why state resets unexpectedly, and how to force a remount.","\u002Fmedia\u002Fcovers\u002Freact-weekly-rerender-vs-remount.png",{"id":360,"slug":355,"questionCount":84},"01a04446-3790-705e-b277-63c77b05dc22",{"id":362,"label":363,"soon":18,"article":364,"quiz":369},"01a13a8c-b452-710f-9980-0889129c636d","Derived state",{"slug":365,"title":366,"excerpt":367,"readingMinutes":205,"coverUrl":368},"react-weekly-derived-state-bug","React Derived State: Why That useState Is Probably a Bug","React derived state explained: why syncing a computed value into useState with an Effect causes extra renders and drift, and what to write instead.","\u002Fmedia\u002Fcovers\u002Freact-weekly-derived-state-bug.png",{"id":370,"slug":365,"questionCount":96},"01a0ab57-ddfa-7328-8b07-065eb9829fae",{"id":372,"label":373,"soon":18,"article":374,"quiz":379},"01a13a8c-b452-710f-9980-0f1ebc4341f0","useTransition",{"slug":375,"title":376,"excerpt":377,"readingMinutes":80,"coverUrl":378},"input-lag-bug-debounce-cant-fix","Your Search Box Lags. Debounce Hides It; `useTransition` Fixes It","A big list re-render was blocking every keystroke — debouncing just moved the freeze. useTransition tells React which update can wait.","\u002Fmedia\u002Fcovers\u002Finput-lag-bug-debounce-cant-fix.png",{"id":380,"slug":375,"questionCount":84},"01a0ec73-24c9-7353-9430-b7449aabd6ac",{"id":382,"label":383,"soon":18,"article":384,"quiz":389},"01a13a8c-b452-710f-9980-100e4a9134e4","React Compiler",{"slug":385,"title":386,"excerpt":387,"readingMinutes":216,"coverUrl":388},"react-weekly-compiler-memoization","React Compiler 1.0: What useMemo You Can Delete","React Compiler 1.0 is stable. Here's the re-render model it automates, which useMemo\u002FuseCallback\u002Fmemo calls you can delete, and what still needs you.","\u002Fmedia\u002Fcovers\u002Freact-weekly-compiler-memoization.png",{"id":390,"slug":385,"questionCount":84},"01a0632c-72a3-71f4-8bea-318b4b6711fb",{"id":392,"label":393,"soon":18,"article":394,"quiz":399},"01a13a8c-b452-710f-9980-164059fd3cf4","Form actions",{"slug":395,"title":396,"excerpt":397,"readingMinutes":216,"coverUrl":398},"react-weekly-form-actions-pending-state","React Form Actions: useActionState & useFormStatus Guide","How React 19 form Actions manage pending state automatically — useActionState, useFormStatus, and useOptimistic explained with the bug they replace.","\u002Fmedia\u002Fcovers\u002Freact-weekly-form-actions-pending-state.png",{"id":400,"slug":395,"questionCount":96},"01a08734-5cdd-743d-adec-d6ba65e75fb4",{"slug":402,"tier":80,"title":403,"summary":404,"icon":405,"accent":406,"unlockedBy":407,"checkpoint":408,"levels":411},"nuxt","Nuxt","Vue on the server: data fetching that does not double up, hydration that matches, and state that does not leak between requests.","i-simple-icons-nuxt","teal-400",[262],{"id":409,"slug":410,"questionCount":66,"passScorePct":67},"01a13a8c-b492-7081-ad3e-4dff00a37962","frontend-developer--nuxt-checkpoint",[412,422,432,442,452],{"id":413,"label":414,"soon":18,"article":415,"quiz":420},"01a13a8c-b5a1-749b-96b8-965b557d6f53","useAsyncData keys",{"slug":416,"title":417,"excerpt":418,"readingMinutes":303,"coverUrl":419},"nuxt-weekly-useasyncdata-keys-dedupe","useAsyncData Keys in Nuxt: Caching, Dedupe & the Sharing Bug","Learn how Nuxt's useAsyncData and useFetch generate cache keys, how dedupe (cancel vs defer) really works, and why wrapper composables silently share data.","\u002Fmedia\u002Fcovers\u002Fnuxt-weekly-useasyncdata-keys-dedupe.png",{"id":421,"slug":416,"questionCount":84},"01a08c59-46d0-746c-ac04-5fcfd7f8521a",{"id":423,"label":424,"soon":18,"article":425,"quiz":430},"01a13a8c-b5a1-749b-96b8-9b2076340b18","Hydration mismatches",{"slug":426,"title":427,"excerpt":428,"readingMinutes":205,"coverUrl":429},"nuxt-weekly-hydration-mismatch","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.","\u002Fmedia\u002Fcovers\u002Fnuxt-weekly-hydration-mismatch.png",{"id":431,"slug":426,"questionCount":220},"01a0b07e-f719-76d9-8da4-de3206a17c01",{"id":433,"label":434,"soon":18,"article":435,"quiz":440},"01a13a8c-b5a1-749b-96b8-9fb031134aac","Cross-request state",{"slug":436,"title":437,"excerpt":438,"readingMinutes":205,"coverUrl":439},"nuxt-weekly-cross-request-state-leak","Nuxt useState vs ref(): Why Server State Leaks Across Users","A module-scope ref() in Nuxt is shared by every request that hits your server. Learn why useState isolates state per user, and how to fix the leak.","\u002Fmedia\u002Fcovers\u002Fnuxt-weekly-cross-request-state-leak.png",{"id":441,"slug":436,"questionCount":84},"01a04446-3f81-726a-bf3e-02e284c2dc13",{"id":443,"label":444,"soon":18,"article":445,"quiz":450},"01a13a8c-b5a1-749b-96b8-a01932a06e5b","Nitro server routes",{"slug":446,"title":447,"excerpt":448,"readingMinutes":216,"coverUrl":449},"nuxt-weekly-nitro-server-routes","Nuxt Server Routes Explained: How Nitro Builds Your API","Nuxt server routes turn server\u002Fapi into a real backend via Nitro and h3. Learn routing rules, defineEventHandler, middleware order, and the useState trap.","\u002Fmedia\u002Fcovers\u002Fnuxt-weekly-nitro-server-routes.png",{"id":451,"slug":446,"questionCount":84},"01a0ec72-fbbc-7637-af2d-e2b95bc8089b",{"id":453,"label":454,"soon":18,"article":455,"quiz":460},"01a13a8c-b5a1-749b-96b8-a7d95511635e","Streaming & route rules",{"slug":456,"title":457,"excerpt":458,"readingMinutes":205,"coverUrl":459},"nuxt-weekly-ssr-streaming-route-rules","Nuxt 4.5 SSR Streaming: The Route Rules That Disable It","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.","\u002Fmedia\u002Fcovers\u002Fnuxt-weekly-ssr-streaming-route-rules.png",{"id":461,"slug":456,"questionCount":220},"01a0f8de-6676-735c-b831-557dc2983403",{"slug":463,"tier":80,"title":464,"summary":465,"icon":466,"accent":467,"unlockedBy":468,"checkpoint":469,"levels":472},"nextjs","Next.js","React on the server: what gets cached, where a server action runs, and which boundary your code is actually on.","i-simple-icons-nextdotjs","slate-400",[338],{"id":470,"slug":471,"questionCount":66,"passScorePct":67},"01a13a8c-b5e1-749f-a98e-491469edd158","frontend-developer--nextjs-checkpoint",[473,483,493,503,513],{"id":474,"label":475,"soon":18,"article":476,"quiz":481},"01a13a8c-b6f0-753c-8232-bde2420b3380","Cache Components",{"slug":477,"title":478,"excerpt":479,"readingMinutes":205,"coverUrl":480},"nextjs-weekly-cache-components-explained","Next.js Cache Components Explained (with Cheat Sheet)","How Next.js Cache Components decide what's static, what's cached, and what streams — the use cache directive, cacheLife, and Suspense explained.","\u002Fmedia\u002Fcovers\u002Fnextjs-weekly-cache-components-explained.png",{"id":482,"slug":477,"questionCount":84},"01a0499d-b5d2-76da-8c1c-672084f98cf3",{"id":484,"label":485,"soon":18,"article":486,"quiz":491},"01a13a8c-b6f0-753c-8232-c218b2355962","Server Actions",{"slug":487,"title":488,"excerpt":489,"readingMinutes":303,"coverUrl":490},"nextjs-weekly-server-actions-mutations-security","Next.js Server Actions: Mutations & Security (Cheat Sheet)","Next.js Server Actions look like plain functions but compile to public POST endpoints. Learn the mutation flow, built-in CSRF checks, and the auth you owe.","\u002Fmedia\u002Fcovers\u002Fnextjs-weekly-server-actions-mutations-security.png",{"id":492,"slug":487,"questionCount":84},"01a06d6c-425d-77fd-a66c-b7a479c8e296",{"id":494,"label":495,"soon":18,"article":496,"quiz":501},"01a13a8c-b6f0-753c-8232-c4d6741b0067","Route Handlers",{"slug":497,"title":498,"excerpt":499,"readingMinutes":303,"coverUrl":500},"nextjs-weekly-route-handlers-caching-streaming","Next.js Route Handlers: GET Stopped Caching in 15 — How to Cache in 16","Next.js 15 made GET Route Handlers dynamic by default. What that changes for code written for 14, how to cache one on purpose in 16, plus a cheat sheet.","\u002Fmedia\u002Fcovers\u002Fnextjs-weekly-route-handlers-caching-streaming.png",{"id":502,"slug":497,"questionCount":84},"01a0ec73-097a-73a9-8a1d-fe9a0510cac1",{"id":504,"label":505,"soon":18,"article":506,"quiz":511},"01a13a8c-b6f0-753c-8232-c9af7b660a8a","Parallel & intercepting routes",{"slug":507,"title":508,"excerpt":509,"readingMinutes":205,"coverUrl":510},"nextjs-weekly-parallel-intercepting-routes-modals","Next.js Parallel & Intercepting Routes: Modals Done Right","How Next.js parallel routes (@slot) and intercepting routes ((.), (..), (...)) combine to build shareable, refreshable modals — verified against Next.js 16.3.","\u002Fmedia\u002Fcovers\u002Fnextjs-weekly-parallel-intercepting-routes-modals.png",{"id":512,"slug":507,"questionCount":84},"01a09181-2f98-7125-8f53-c5833a1abec9",{"id":514,"label":515,"soon":18,"article":516,"quiz":521},"01a13a8c-b6f0-753c-8232-cf8a5183c997","proxy.ts",{"slug":517,"title":518,"excerpt":519,"readingMinutes":292,"coverUrl":520},"nextjs-weekly-middleware-to-proxy-network-boundary","Next.js proxy.ts Explained (with Cheat Sheet)","Next.js 16 renamed middleware.ts to proxy.ts and locked it to the Node.js runtime. Learn the network-boundary model, matcher config, and the migration path.","\u002Fmedia\u002Fcovers\u002Fnextjs-weekly-middleware-to-proxy-network-boundary.png",{"id":522,"slug":517,"questionCount":96},"01a0b58a-801b-777f-bc56-6d6d6e031b6f",{"slug":524,"tier":92,"title":525,"summary":526,"icon":527,"accent":528,"unlockedBy":529,"checkpoint":530,"levels":533},"typescript","TypeScript","Types that describe what your code really does — generics that stay generic, and checks that do not widen what you meant.","i-simple-icons-typescript","indigo-500",[402,463],{"id":531,"slug":532,"questionCount":66,"passScorePct":67},"01a13a8c-b732-777f-9610-eb11d528c3a0","frontend-developer--typescript-checkpoint",[534,544,554,557],{"id":535,"label":536,"soon":18,"article":537,"quiz":542},"01a13a8c-b839-7559-b4b5-071cf0cfe152","Generics",{"slug":538,"title":539,"excerpt":540,"readingMinutes":303,"coverUrl":541},"weekly-typescript-generics","TypeScript Generics: The Complete Guide (with Cheat Sheet)","Learn TypeScript generics from the ground up — generic functions, constraints, defaults, and classes — with worked examples and a copy-paste cheat sheet.","\u002Fmedia\u002Fcovers\u002Fweekly-typescript-generics.png",{"id":543,"slug":538,"questionCount":96},"019fe776-6408-72ff-8ac3-baa2e75b42c6",{"id":545,"label":546,"soon":18,"article":547,"quiz":552},"01a13a8c-b839-7559-b4b5-087943ce45d4","satisfies",{"slug":548,"title":549,"excerpt":550,"readingMinutes":80,"coverUrl":551},"typescript-satisfies-operator","Your TypeScript config objects are losing type information. `satisfies` fixes it.","Type annotations widen your object types and erase the precise values TypeScript inferred. The `satisfies` operator validates against a type without changing what TypeScript keeps — you get the check without the widening.","\u002Fmedia\u002Fcovers\u002Ftypescript-satisfies-operator.png",{"id":553,"slug":548,"questionCount":92},"019fe776-369d-7220-b877-ea29a4dbbcd3",{"id":555,"label":556,"soon":17,"article":72,"quiz":72},"01a13a8c-b839-7559-b4b5-0fc62a052ab2","Inferred type predicates",{"id":558,"label":559,"soon":18,"article":560,"quiz":565},"01a13a8c-b839-7559-b4b5-11e73a388058","using & disposal",{"slug":561,"title":562,"excerpt":563,"readingMinutes":104,"coverUrl":564},"using-explicit-resource-management","You still write `finally { resource.close() }`. The `using` keyword does it automatically.","The Explicit Resource Management proposal adds a `using` declaration that calls cleanup the moment a scope exits — normal return, early return, or throw. No more try\u002Ffinally boilerplate for timers, event listeners, connections, or any other resource you need to release.","\u002Fmedia\u002Fcovers\u002Fusing-explicit-resource-management.png",{"id":566,"slug":561,"questionCount":92},"019fe776-74a5-7729-aa90-9ad15f2ed3a7",{"slug":568,"tier":96,"title":569,"summary":570,"icon":571,"accent":10,"unlockedBy":572,"checkpoint":573,"levels":576},"production","Ship it","What separates a demo from a product: speed you can measure, caches that do not lie, and a back button that works.","i-solar-rocket-2-linear",[524],{"id":574,"slug":575,"questionCount":303,"passScorePct":67},"01a13a8c-b879-7049-af33-75e58ff2e719","frontend-developer--production-checkpoint",[577,587,597,607,617],{"id":578,"label":579,"soon":18,"article":580,"quiz":585},"01a13a8c-b987-7797-9813-e88db6d9f23d","Core Web Vitals",{"slug":581,"title":582,"excerpt":583,"readingMinutes":96,"coverUrl":584},"performanceobserver-core-web-vitals","You Installed a Library for Numbers PerformanceObserver Already Has.","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.","\u002Fmedia\u002Fcovers\u002Fperformanceobserver-core-web-vitals.png",{"id":586,"slug":581,"questionCount":96},"01a11f48-c788-7276-8c70-8076af0f1bc9",{"id":588,"label":589,"soon":18,"article":590,"quiz":595},"01a13a8c-b987-7797-9813-ee3ad7720a8a","Web Workers",{"slug":591,"title":592,"excerpt":593,"readingMinutes":216,"coverUrl":594},"weekly-web-workers","Web Workers in JavaScript: The Complete Guide","Learn JavaScript Web Workers step by step: message passing, transferable objects, error handling, and a copy-paste cheat sheet for offloading work.","\u002Fmedia\u002Fcovers\u002Fweekly-web-workers.png",{"id":596,"slug":591,"questionCount":84},"01a018ca-683e-71ec-b6a5-7b3e09d8aca9",{"id":598,"label":599,"soon":18,"article":600,"quiz":605},"01a13a8c-b987-7797-9813-f3ecf2782ac9","CORS",{"slug":601,"title":602,"excerpt":603,"readingMinutes":303,"coverUrl":604},"weekly-cors-explained","CORS Explained: The Complete Guide (with Cheat Sheet)","A complete guide to CORS: the same-origin policy, preflight requests, and Access-Control-Allow-Origin headers — with worked examples and a cheat sheet.","\u002Fmedia\u002Fcovers\u002Fweekly-cors-explained.png",{"id":606,"slug":601,"questionCount":84},"019fe776-ae7a-739b-933e-671ec814bf30",{"id":608,"label":609,"soon":18,"article":610,"quiz":615},"01a13a8c-b987-7797-9813-f4ff6b0b6308","Service worker updates",{"slug":611,"title":612,"excerpt":613,"readingMinutes":92,"coverUrl":614},"service-worker-stale-cache-deploy","I Shipped a Fix. My Service Worker Kept Serving the Bug.","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.","\u002Fmedia\u002Fcovers\u002Fservice-worker-stale-cache-deploy.png",{"id":616,"slug":611,"questionCount":84},"01a114fb-f19f-74a9-b69e-94217adba56a",{"id":618,"label":619,"soon":18,"article":620,"quiz":625},"01a13a8c-b987-7797-9813-f92c41735f18","The back\u002Fforward cache",{"slug":621,"title":622,"excerpt":623,"readingMinutes":92,"coverUrl":624},"bfcache-beforeunload-back-button","`beforeunload` Can Still Kill Your bfcache. Mount It Only When Dirty.","A `beforeunload` listener you left mounted forever can still quietly cost you bfcache eligibility — and an `unload` listener reliably will. Here's the pagehide\u002Fpageshow fix, and why 'mount it only when there's something to lose' is the durable rule.","\u002Fmedia\u002Fcovers\u002Fbfcache-beforeunload-back-button.png",{"id":626,"slug":621,"questionCount":84},"01a0f0ef-da04-723d-a246-7a9949fac8d5",[628,632,635,639,643,646,650,653,655,658,661,664],{"slug":629,"name":630,"articles":631},"webdev","Webdev",138,{"slug":186,"name":633,"articles":634},"Javascript",113,{"slug":636,"name":637,"articles":638},"frontend","Frontend",83,{"slug":640,"name":641,"articles":642},"tutorial","Tutorial",53,{"slug":119,"name":644,"articles":645},"Css",42,{"slug":647,"name":648,"articles":649},"performance","Performance",21,{"slug":524,"name":651,"articles":652},"Typescript",18,{"slug":338,"name":339,"articles":654},17,{"slug":656,"name":657,"articles":216},"browser","Browser",{"slug":659,"name":660,"articles":292},"node","Node",{"slug":662,"name":663,"articles":66},"programming","Programming",{"slug":665,"name":666,"articles":220},"accessibility","Accessibility",{"id":64,"slug":65,"kind":668,"title":669,"description":670,"config":671,"verticalId":5,"vertical":673,"course":72,"_count":674,"access":676,"attempts":678,"questionCount":675},"PLACEMENT","HTML checkpoint","10 questions drawn from every level of the HTML stage. Pass to clear the stage — or to skip it, if you already know this.",{"questionCount":66,"timeLimitSec":72,"shuffleQuestions":17,"shuffleOptions":17,"negativeMarking":19,"passScorePct":67,"maxAttempts":72,"revealAnswers":672,"allowFlagging":17,"allowBacktracking":17},"AFTER_SUBMIT",{"slug":6,"name":7},{"questions":675},28,{"allowed":17,"reason":677},"FREE",[]]