[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"tag-javascript-6":44,"search-suggestions":297,"tags-all":327},[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,{"items":45,"meta":292},[46,80,101,120,138,156,174,195,213,233,253,274],{"id":47,"slug":48,"title":49,"subtitle":50,"excerpt":51,"coverUrl":52,"locale":13,"readingMinutes":53,"publishedAt":54,"viewCount":55,"likeCount":19,"commentCount":19,"author":56,"vertical":61,"topic":62,"tags":65,"_count":77,"playground":79,"hasQuiz":17,"hasPlayground":17},"019fe660-b09d-731e-b160-9e45270a5652","css-scope-native-style-scoping","CSS has no native scoping. `@scope` changes that.",null,"BEM, CSS Modules, and scoped component styles all exist because CSS leaks — a rule written for one component can silently affect another. `@scope` gives the cascade a lower boundary so styles stay where you put them, natively, with no build step.","\u002Fmedia\u002Fcovers\u002Fcss-scope-native-style-scoping.png",5,"2026-07-31T08:56:20.507Z",417,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":64},"css","CSS",[66,68,71,74],{"slug":63,"name":67,"color":50},"Css",{"slug":69,"name":70,"color":50},"webdev","Webdev",{"slug":72,"name":73,"color":50},"frontend","Frontend",{"slug":75,"name":76,"color":50},"javascript","Javascript",{"assessments":78},1,{"slug":48},{"id":81,"slug":82,"title":83,"subtitle":50,"excerpt":84,"coverUrl":85,"locale":13,"readingMinutes":53,"publishedAt":86,"viewCount":87,"likeCount":19,"commentCount":19,"author":88,"vertical":89,"topic":90,"tags":92,"_count":99,"playground":100,"hasQuiz":17,"hasPlayground":17},"019fe660-a973-77a9-9820-826bf25fd884","iterator-helpers-lazy-filter-map","Array methods are eager. Iterator helpers are lazy. Here's why that matters.","Every `.map()` and `.filter()` on an array creates a new intermediate array. Iterator helpers — built into JavaScript since 2024 — give you the same pipeline but evaluate one element at a time, with no wasted allocations.","\u002Fmedia\u002Fcovers\u002Fiterator-helpers-lazy-filter-map.png","2026-07-30T08:34:21.684Z",364,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":75,"name":91},"JavaScript",[93,94,95,96],{"slug":75,"name":76,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"slug":97,"name":98,"color":50},"performance","Performance",{"assessments":78},{"slug":82},{"id":102,"slug":103,"title":104,"subtitle":50,"excerpt":105,"coverUrl":106,"locale":13,"readingMinutes":107,"publishedAt":108,"viewCount":109,"likeCount":19,"commentCount":19,"author":110,"vertical":111,"topic":112,"tags":113,"_count":118,"playground":119,"hasQuiz":17,"hasPlayground":17},"019fe660-a1fc-740c-9df4-b60a02de8afa","css-color-mix-native-color-mixing","You reach for Sass to mix colors. `color-mix()` does it natively.","Sass's `darken()`, `lighten()`, and `mix()` functions solved real problems CSS couldn't handle for decades. `color-mix()` is the native answer, and it ships in every modern browser with no build step required.","\u002Fmedia\u002Fcovers\u002Fcss-color-mix-native-color-mixing.png",4,"2026-07-29T08:47:34.803Z",304,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":64},[114,115,116,117],{"slug":63,"name":67,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"slug":75,"name":76,"color":50},{"assessments":78},{"slug":103},{"id":121,"slug":122,"title":123,"subtitle":50,"excerpt":124,"coverUrl":125,"locale":13,"readingMinutes":107,"publishedAt":126,"viewCount":127,"likeCount":19,"commentCount":19,"author":128,"vertical":129,"topic":130,"tags":131,"_count":136,"playground":137,"hasQuiz":17,"hasPlayground":17},"019fe660-9a9b-73dc-87cd-48744e21e671","text-wrap-balance-headline-orphans","You hand-edit headlines to avoid orphaned words. `text-wrap: balance` does it natively.","The classic fix for a headline that breaks awkwardly — a manual `\u003Cbr>`, a `&shy;`, or a max-width tweak — exists because CSS had no way to distribute line breaks evenly. `text-wrap: balance` and `text-wrap: pretty` are the native answers.","\u002Fmedia\u002Fcovers\u002Ftext-wrap-balance-headline-orphans.png","2026-07-28T08:41:41.989Z",320,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":64},[132,133,134,135],{"slug":63,"name":67,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"slug":75,"name":76,"color":50},{"assessments":78},{"slug":122},{"id":139,"slug":140,"title":141,"subtitle":50,"excerpt":142,"coverUrl":143,"locale":13,"readingMinutes":107,"publishedAt":144,"viewCount":145,"likeCount":19,"commentCount":19,"author":146,"vertical":147,"topic":148,"tags":149,"_count":154,"playground":155,"hasQuiz":17,"hasPlayground":17},"019fe660-8482-75bc-ab16-8e86f92efc09","resize-observer-element-size","You're watching `window` to detect element size changes. `ResizeObserver` watches the element itself.","A `window` resize listener only fires when the viewport changes. ResizeObserver fires whenever the element's own box changes — from content loading, parent reflow, container queries, or anything else.","\u002Fmedia\u002Fcovers\u002Fresize-observer-element-size.png","2026-07-26T08:32:44.347Z",371,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":75,"name":91},[150,151,152,153],{"slug":75,"name":76,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"slug":97,"name":98,"color":50},{"assessments":78},{"slug":140},{"id":157,"slug":158,"title":159,"subtitle":50,"excerpt":160,"coverUrl":161,"locale":13,"readingMinutes":107,"publishedAt":162,"viewCount":163,"likeCount":19,"commentCount":19,"author":164,"vertical":165,"topic":166,"tags":167,"_count":172,"playground":173,"hasQuiz":17,"hasPlayground":17},"019fe660-7d17-745b-812d-b1e81a1b2b85","css-starting-style-entry-animations","You use a setTimeout to trigger CSS entry animations. `@starting-style` makes it unnecessary.","Before `@starting-style`, the moment an element entered the DOM was invisible to CSS — transitions had no 'before' state to interpolate from. The at-rule gives you one, natively, with no JavaScript required.","\u002Fmedia\u002Fcovers\u002Fcss-starting-style-entry-animations.png","2026-07-25T08:13:02.298Z",303,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":64},[168,169,170,171],{"slug":63,"name":67,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"slug":75,"name":76,"color":50},{"assessments":78},{"slug":158},{"id":175,"slug":176,"title":177,"subtitle":50,"excerpt":178,"coverUrl":179,"locale":13,"readingMinutes":107,"publishedAt":180,"viewCount":181,"likeCount":19,"commentCount":19,"author":182,"vertical":183,"topic":184,"tags":187,"_count":193,"playground":194,"hasQuiz":17,"hasPlayground":17},"019fe660-75da-727d-a751-32f8723b0b38","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","2026-07-24T08:33:28.459Z",384,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":185,"name":186},"typescript","TypeScript",[188,190,191,192],{"slug":185,"name":189,"color":50},"Typescript",{"slug":75,"name":76,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"assessments":78},{"slug":176},{"id":196,"slug":197,"title":198,"subtitle":50,"excerpt":199,"coverUrl":200,"locale":13,"readingMinutes":107,"publishedAt":201,"viewCount":202,"likeCount":19,"commentCount":19,"author":203,"vertical":204,"topic":205,"tags":206,"_count":211,"playground":212,"hasQuiz":17,"hasPlayground":17},"019fe660-6e7e-72cb-bd34-bc123056cfeb","set-methods-union-intersection","You've been doing Set math by hand. JavaScript finally shipped `.union()`, `.intersection()`, and friends.","Set has always been missing its obvious operations. ES2025 adds `.union()`, `.intersection()`, `.difference()`, `.symmetricDifference()`, and three boolean predicates — native methods that used to require four lines of spread syntax each.","\u002Fmedia\u002Fcovers\u002Fset-methods-union-intersection.png","2026-07-23T08:37:02.144Z",338,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":75,"name":91},[207,208,209,210],{"slug":75,"name":76,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"slug":185,"name":189,"color":50},{"assessments":78},{"slug":197},{"id":214,"slug":215,"title":216,"subtitle":50,"excerpt":217,"coverUrl":218,"locale":13,"readingMinutes":107,"publishedAt":219,"viewCount":220,"likeCount":19,"commentCount":19,"author":221,"vertical":222,"topic":223,"tags":224,"_count":231,"playground":232,"hasQuiz":17,"hasPlayground":17},"019fe660-66d6-71c3-b71a-ed9102b874c8","promise-with-resolvers","You keep escaping the Promise constructor. `Promise.withResolvers` does it right.","The 'deferred promise' pattern — storing resolve and reject outside the constructor so you can call them later — is a daily JavaScript idiom that's always felt awkward. ES2024 added a one-liner for it.","\u002Fmedia\u002Fcovers\u002Fpromise-with-resolvers.png","2026-07-22T08:35:52.029Z",476,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":75,"name":91},[225,226,227,228],{"slug":75,"name":76,"color":50},{"slug":69,"name":70,"color":50},{"slug":185,"name":189,"color":50},{"slug":229,"name":230,"color":50},"asyncjs","Asyncjs",{"assessments":78},{"slug":215},{"id":234,"slug":235,"title":236,"subtitle":50,"excerpt":237,"coverUrl":238,"locale":13,"readingMinutes":107,"publishedAt":239,"viewCount":240,"likeCount":19,"commentCount":19,"author":241,"vertical":242,"topic":243,"tags":244,"_count":251,"playground":252,"hasQuiz":17,"hasPlayground":17},"019fe660-5f55-701e-9cf4-dc0c9f0517b9","error-cause-rethrow-context","You're rethrowing errors and losing context. `Error.cause` fixes that.","Every time you catch an error and rethrow a new one without forwarding the original, you lose the stack trace, the error type, and everything useful about what actually went wrong. ES2022 added `Error.cause` to fix exactly this.","\u002Fmedia\u002Fcovers\u002Ferror-cause-rethrow-context.png","2026-07-21T08:36:02.331Z",408,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":75,"name":91},[245,246,247,250],{"slug":75,"name":76,"color":50},{"slug":69,"name":70,"color":50},{"slug":248,"name":249,"color":50},"node","Node",{"slug":185,"name":189,"color":50},{"assessments":78},{"slug":235},{"id":254,"slug":255,"title":256,"subtitle":50,"excerpt":257,"coverUrl":258,"locale":13,"readingMinutes":259,"publishedAt":260,"viewCount":261,"likeCount":19,"commentCount":19,"author":262,"vertical":263,"topic":264,"tags":265,"_count":272,"playground":273,"hasQuiz":17,"hasPlayground":17},"019fe660-57eb-7258-b452-d66ff04d2380","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",15,"2026-07-20T09:23:23.621Z",388,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":185,"name":186},[266,267,268,271],{"slug":185,"name":189,"color":50},{"slug":75,"name":76,"color":50},{"slug":269,"name":270,"color":50},"tutorial","Tutorial",{"slug":69,"name":70,"color":50},{"assessments":78},{"slug":255},{"id":275,"slug":276,"title":277,"subtitle":50,"excerpt":278,"coverUrl":279,"locale":13,"readingMinutes":107,"publishedAt":280,"viewCount":281,"likeCount":19,"commentCount":19,"author":282,"vertical":283,"topic":284,"tags":285,"_count":290,"playground":291,"hasQuiz":17,"hasPlayground":17},"019fe660-503a-7133-b7b0-7d5ce9587539","intersection-observer-visibility","Your scroll listener fires on every pixel. `IntersectionObserver` fires when visibility actually changes.","Detecting whether an element is in the viewport by listening to scroll events runs an expensive layout calculation on every frame. `IntersectionObserver` is the browser-native alternative — it fires only when visibility changes, off the main thread, with no scroll handler involved.","\u002Fmedia\u002Fcovers\u002Fintersection-observer-visibility.png","2026-07-19T08:25:59.411Z",299,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":75,"name":91},[286,287,288,289],{"slug":75,"name":76,"color":50},{"slug":69,"name":70,"color":50},{"slug":72,"name":73,"color":50},{"slug":97,"name":98,"color":50},{"assessments":78},{"slug":276},{"page":293,"perPage":294,"total":295,"totalPages":296},6,12,93,8,[298,300,301,303,305,307,309,311,315,319,320,323],{"slug":69,"name":70,"articles":299},111,{"slug":75,"name":76,"articles":295},{"slug":72,"name":73,"articles":302},73,{"slug":269,"name":270,"articles":304},39,{"slug":63,"name":67,"articles":306},36,{"slug":185,"name":189,"articles":308},16,{"slug":97,"name":98,"articles":310},14,{"slug":312,"name":313,"articles":314},"react","React",13,{"slug":316,"name":317,"articles":318},"browser","Browser",10,{"slug":248,"name":249,"articles":318},{"slug":321,"name":322,"articles":296},"html","Html",{"slug":324,"name":325,"articles":326},"accessibility","Accessibility",7,[328,329,330,331,332,333,334,335,336,337,338,339,340,343,346,349,352,355,358,361,364,367,370,373,376,379,382,385,388,391,394,397,400,403,406,409],{"slug":69,"name":70,"color":50,"articles":299},{"slug":75,"name":76,"color":50,"articles":295},{"slug":72,"name":73,"color":50,"articles":302},{"slug":269,"name":270,"color":50,"articles":304},{"slug":63,"name":67,"color":50,"articles":306},{"slug":185,"name":189,"color":50,"articles":308},{"slug":97,"name":98,"color":50,"articles":310},{"slug":312,"name":313,"color":50,"articles":314},{"slug":248,"name":249,"color":50,"articles":318},{"slug":316,"name":317,"color":50,"articles":318},{"slug":321,"name":322,"color":50,"articles":296},{"slug":324,"name":325,"color":50,"articles":326},{"slug":341,"name":342,"color":50,"articles":293},"programming","Programming",{"slug":344,"name":345,"color":50,"articles":293},"grammar","Grammar",{"slug":347,"name":348,"color":50,"articles":53},"nestjs","Nestjs",{"slug":350,"name":351,"color":50,"articles":107},"nextjs","Nextjs",{"slug":353,"name":354,"color":50,"articles":107},"apis","Apis",{"slug":356,"name":357,"color":50,"articles":43},"nuxt","Nuxt",{"slug":359,"name":360,"color":50,"articles":43},"ssr","SSR",{"slug":362,"name":363,"color":50,"articles":43},"ai","Ai",{"slug":365,"name":366,"color":50,"articles":43},"vue","Vue",{"slug":368,"name":369,"color":50,"articles":31},"security","Security",{"slug":371,"name":372,"color":50,"articles":31},"async","Async",{"slug":374,"name":375,"color":50,"articles":31},"forms","Forms",{"slug":377,"name":378,"color":50,"articles":31},"api","API",{"slug":380,"name":381,"color":50,"articles":31},"english","English",{"slug":383,"name":384,"color":50,"articles":31},"verbs","Verbs",{"slug":386,"name":387,"color":50,"articles":31},"spanish","Spanish",{"slug":389,"name":390,"color":50,"articles":31},"a1","A1",{"slug":392,"name":393,"color":50,"articles":31},"a2","A2",{"slug":395,"name":396,"color":50,"articles":31},"tenses","Tenses",{"slug":398,"name":399,"color":50,"articles":31},"turkish","Turkish",{"slug":401,"name":402,"color":50,"articles":31},"career","Career",{"slug":404,"name":405,"color":50,"articles":31},"beginners","Beginners",{"slug":407,"name":408,"color":50,"articles":31},"productivity","Productivity",{"slug":410,"name":411,"color":50,"articles":31},"discuss","Discuss"]