[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"blog-topics":44,"topics-all":183,"search-suggestions":263,"articles-all-16---":276,"articles-total":503},[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,[45,50,54,58,62,66,70,74,78,82,85,89,93,97,100,104,107,111,114,117,121,124,128,132,135,138,141,144,147,150,153,156,159,162,165,168,171,174,177,180],{"slug":46,"name":47,"color":48,"articles":49},"webdev","Webdev",null,171,{"slug":51,"name":52,"color":48,"articles":53},"javascript","Javascript",138,{"slug":55,"name":56,"color":48,"articles":57},"frontend","Frontend",95,{"slug":59,"name":60,"color":48,"articles":61},"tutorial","Tutorial",69,{"slug":63,"name":64,"color":48,"articles":65},"css","Css",50,{"slug":67,"name":68,"color":48,"articles":69},"performance","Performance",30,{"slug":71,"name":72,"color":48,"articles":73},"typescript","Typescript",25,{"slug":75,"name":76,"color":48,"articles":77},"react","React",20,{"slug":79,"name":80,"color":48,"articles":81},"programming","Programming",18,{"slug":83,"name":84,"color":48,"articles":81},"browser","Browser",{"slug":86,"name":87,"color":48,"articles":88},"node","Node",15,{"slug":90,"name":91,"color":48,"articles":92},"html","Html",12,{"slug":94,"name":95,"color":48,"articles":96},"nextjs","Nextjs",10,{"slug":98,"name":99,"color":48,"articles":96},"accessibility","Accessibility",{"slug":101,"name":102,"color":48,"articles":103},"nestjs","Nestjs",9,{"slug":105,"name":106,"color":48,"articles":103},"vue","Vue",{"slug":108,"name":109,"color":48,"articles":110},"nuxt","Nuxt",8,{"slug":112,"name":113,"color":48,"articles":110},"career","Career",{"slug":115,"name":116,"color":48,"articles":110},"discuss","Discuss",{"slug":118,"name":119,"color":48,"articles":120},"beginners","Beginners",7,{"slug":122,"name":123,"color":48,"articles":120},"productivity","Productivity",{"slug":125,"name":126,"color":48,"articles":127},"grammar","Grammar",6,{"slug":129,"name":130,"color":48,"articles":131},"ssr","SSR",4,{"slug":133,"name":134,"color":48,"articles":131},"security","Security",{"slug":136,"name":137,"color":48,"articles":131},"apis","Apis",{"slug":139,"name":140,"color":48,"articles":43},"ai","Ai",{"slug":142,"name":143,"color":48,"articles":43},"api","API",{"slug":145,"name":146,"color":48,"articles":31},"async","Async",{"slug":148,"name":149,"color":48,"articles":31},"forms","Forms",{"slug":151,"name":152,"color":48,"articles":31},"dom","Dom",{"slug":154,"name":155,"color":48,"articles":31},"backend","Backend",{"slug":157,"name":158,"color":48,"articles":31},"english","English",{"slug":160,"name":161,"color":48,"articles":31},"verbs","Verbs",{"slug":163,"name":164,"color":48,"articles":31},"spanish","Spanish",{"slug":166,"name":167,"color":48,"articles":31},"a1","A1",{"slug":169,"name":170,"color":48,"articles":31},"a2","A2",{"slug":172,"name":173,"color":48,"articles":31},"tenses","Tenses",{"slug":175,"name":176,"color":48,"articles":31},"turkish","Turkish",{"slug":178,"name":179,"color":48,"articles":31},"animation","Animation",{"slug":181,"name":182,"color":48,"articles":31},"caching","Caching",[184,190,192,197,199,204,207,211,216,221,223,228,231,235,237,241,243,246,250,252,254,257,259,261],{"id":185,"slug":186,"name":187,"parentId":48,"description":188,"articleCount":189},"0da12d3c-ac33-4b32-859f-9a16877ef255","starting","Starting somewhere new","First days, first weeks, and the part where you do not know anything yet.",1,{"id":191,"slug":105,"name":106,"parentId":48,"description":48,"articleCount":103},"019fe637-3e06-75b8-8a2c-fc350aad7701",{"id":193,"slug":194,"name":195,"parentId":48,"description":196,"articleCount":31},"9ef7e6f6-b287-4ac2-8f56-421d3aafe8cc","meetings","Meetings and rooms","Speaking up, running one, and knowing which kind you are in.",{"id":198,"slug":108,"name":109,"parentId":48,"description":48,"articleCount":110},"019fe637-3e06-75b8-8a2d-0309c35755c6",{"id":200,"slug":201,"name":202,"parentId":48,"description":203,"articleCount":189},"540105e9-ba05-40f3-bdfd-16fb645e978c","interviews","Getting hired","Applications, interviews, offers, and the negotiation nobody rehearses.",{"id":205,"slug":71,"name":206,"parentId":48,"description":48,"articleCount":127},"019fe637-3e06-75b8-8a2d-040994c0d907","TypeScript",{"id":208,"slug":209,"name":210,"parentId":48,"description":48,"articleCount":19},"019fe637-3e06-75b8-8a2d-0956229cd176","architecture","Architecture",{"id":212,"slug":213,"name":214,"parentId":48,"description":215,"articleCount":31},"0cc5bdbb-d6e8-43b0-9cb4-d227aec6aa68","people","The people around you","Colleagues, managers, and the relationships that decide how work feels.",{"id":217,"slug":218,"name":219,"parentId":48,"description":220,"articleCount":189},"545c6bda-b8cf-4905-8056-18c0c4dc7a64","leading","Leading","Becoming the person others rely on, before and after the title.",{"id":222,"slug":67,"name":68,"parentId":48,"description":48,"articleCount":189},"019fe637-3e07-735d-8227-4c34039af2e0",{"id":224,"slug":225,"name":226,"parentId":48,"description":227,"articleCount":189},"cc22e84d-2cac-44ac-a272-5715e4710dc4","company","Company shapes","Why the same behaviour succeeds at five people and fails at five thousand.",{"id":229,"slug":139,"name":230,"parentId":48,"description":48,"articleCount":189},"019fe65f-98ec-773a-8ca8-9a2e971911c1","AI",{"id":232,"slug":63,"name":233,"parentId":48,"description":48,"articleCount":234},"019fe65f-c110-761b-931e-99a2d1280410","CSS",46,{"id":236,"slug":112,"name":113,"parentId":48,"description":48,"articleCount":19},"01a037b3-d685-76cb-9940-6a3f8ce140a0",{"id":238,"slug":239,"name":240,"parentId":48,"description":48,"articleCount":189},"019fe65f-a1cb-74c8-b999-ff353158fce9","designsystems","Design Systems",{"id":242,"slug":157,"name":158,"parentId":48,"description":48,"articleCount":31},"019ff280-9a51-757c-84ce-c941f20371e9",{"id":244,"slug":90,"name":245,"parentId":48,"description":48,"articleCount":131},"019ff19b-f37e-7091-b3cd-5c99e8c005a4","HTML",{"id":247,"slug":51,"name":248,"parentId":48,"description":48,"articleCount":249},"019fe65f-b950-7762-bb1a-d83445281950","JavaScript",79,{"id":251,"slug":101,"name":102,"parentId":48,"description":48,"articleCount":103},"01a03cdb-1ff8-76fa-9fa7-38d9e4eba1e1",{"id":253,"slug":94,"name":95,"parentId":48,"description":48,"articleCount":96},"01a0499d-b263-749a-a3ad-df3cc782e94d",{"id":255,"slug":75,"name":76,"parentId":48,"description":48,"articleCount":256},"019fe65f-b134-725b-bbc7-3e3db8c68675",11,{"id":258,"slug":133,"name":134,"parentId":48,"description":48,"articleCount":31},"019fe660-ce9d-754e-b241-7bccad915b86",{"id":260,"slug":163,"name":164,"parentId":48,"description":48,"articleCount":31},"019ff280-9d5a-77dc-b01d-e2378eaf86cb",{"id":262,"slug":175,"name":176,"parentId":48,"description":48,"articleCount":31},"019ff280-9eea-736d-ad13-4c01f0ddc46e",[264,265,266,267,268,269,270,271,272,273,274,275],{"slug":46,"name":47,"articles":49},{"slug":51,"name":52,"articles":53},{"slug":55,"name":56,"articles":57},{"slug":59,"name":60,"articles":61},{"slug":63,"name":64,"articles":65},{"slug":67,"name":68,"articles":69},{"slug":71,"name":72,"articles":73},{"slug":75,"name":76,"articles":77},{"slug":83,"name":84,"articles":81},{"slug":79,"name":80,"articles":81},{"slug":86,"name":87,"articles":88},{"slug":90,"name":91,"articles":92},{"items":277,"meta":499},[278,301,319,337,356,374,392,410,428,446,464,482],{"id":279,"slug":280,"title":281,"subtitle":48,"excerpt":282,"coverUrl":283,"locale":13,"readingMinutes":284,"publishedAt":285,"viewCount":286,"likeCount":19,"commentCount":19,"author":287,"vertical":292,"topic":293,"tags":294,"_count":299,"playground":300,"hasQuiz":17,"hasPlayground":17},"019fe660-39f9-768b-be22-fcd49b6abf6d","css-subgrid-nested-grid-alignment","Your CSS Grid cards look misaligned. `subgrid` is the fix you didn't know existed.","CSS Grid controls your outer container, but its children can't participate in the same tracks. `subgrid` closes that gap — nested elements align to the parent grid's rows and columns without padding hacks, fixed heights, or JavaScript measurements.","\u002Fmedia\u002Fcovers\u002Fcss-subgrid-nested-grid-alignment.png",5,"2026-07-16T08:21:27.248Z",831,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":233},[295,296,297,298],{"slug":63,"name":64,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":90,"name":91,"color":48},{"assessments":189},{"slug":280},{"id":302,"slug":303,"title":304,"subtitle":48,"excerpt":305,"coverUrl":306,"locale":13,"readingMinutes":284,"publishedAt":307,"viewCount":308,"likeCount":19,"commentCount":19,"author":309,"vertical":310,"topic":311,"tags":312,"_count":317,"playground":318,"hasQuiz":17,"hasPlayground":17},"019fe660-32b6-757d-a975-3860df795f67","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","2026-07-15T08:22:28.270Z",489,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":51,"name":248},[313,314,315,316],{"slug":51,"name":52,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":75,"name":76,"color":48},{"assessments":189},{"slug":303},{"id":320,"slug":321,"title":322,"subtitle":48,"excerpt":323,"coverUrl":324,"locale":13,"readingMinutes":131,"publishedAt":325,"viewCount":326,"likeCount":19,"commentCount":19,"author":327,"vertical":328,"topic":329,"tags":330,"_count":335,"playground":336,"hasQuiz":17,"hasPlayground":17},"019fe660-2b2e-71fb-a0d1-fd1509765d3b","object-groupby-replace-reduce","You've been writing this `reduce` a hundred times. `Object.groupBy` does it in one.","Grouping an array by a key is one of the most common data transforms in frontend code. You've been wiring it by hand with `reduce` for years. `Object.groupBy` is the native version — no helper, no library, no ceremony.","\u002Fmedia\u002Fcovers\u002Fobject-groupby-replace-reduce.png","2026-07-14T08:16:56.309Z",416,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":51,"name":248},[331,332,333,334],{"slug":51,"name":52,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":86,"name":87,"color":48},{"assessments":189},{"slug":321},{"id":338,"slug":339,"title":340,"subtitle":48,"excerpt":341,"coverUrl":342,"locale":13,"readingMinutes":343,"publishedAt":344,"viewCount":345,"likeCount":19,"commentCount":19,"author":346,"vertical":347,"topic":348,"tags":349,"_count":354,"playground":355,"hasQuiz":17,"hasPlayground":17},"019fe660-2335-7652-9e51-7c6f28871874","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.","\u002Fmedia\u002Fcovers\u002Fweekly-javascript-event-loop.png",13,"2026-07-13T09:36:33.464Z",934,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":51,"name":248},[350,351,352,353],{"slug":51,"name":52,"color":48},{"slug":46,"name":47,"color":48},{"slug":59,"name":60,"color":48},{"slug":79,"name":80,"color":48},{"assessments":189},{"slug":339},{"id":357,"slug":358,"title":359,"subtitle":48,"excerpt":360,"coverUrl":361,"locale":13,"readingMinutes":284,"publishedAt":362,"viewCount":363,"likeCount":19,"commentCount":19,"author":364,"vertical":365,"topic":366,"tags":367,"_count":372,"playground":373,"hasQuiz":17,"hasPlayground":17},"019fe660-1be2-74dd-aa56-0c8fd84204fd","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","2026-07-13T09:36:32.501Z",507,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":51,"name":248},[368,369,370,371],{"slug":51,"name":52,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":86,"name":87,"color":48},{"assessments":189},{"slug":358},{"id":375,"slug":376,"title":377,"subtitle":48,"excerpt":378,"coverUrl":379,"locale":13,"readingMinutes":131,"publishedAt":380,"viewCount":381,"likeCount":19,"commentCount":19,"author":382,"vertical":383,"topic":384,"tags":385,"_count":390,"playground":391,"hasQuiz":17,"hasPlayground":17},"019fe660-1462-723e-9605-66ffa7e98f42","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.","\u002Fmedia\u002Fcovers\u002Fpopover-api-native-popovers.png","2026-07-12T08:24:42.323Z",478,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":51,"name":248},[386,387,388,389],{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":51,"name":52,"color":48},{"slug":63,"name":64,"color":48},{"assessments":189},{"slug":376},{"id":393,"slug":394,"title":395,"subtitle":48,"excerpt":396,"coverUrl":397,"locale":13,"readingMinutes":284,"publishedAt":398,"viewCount":399,"likeCount":19,"commentCount":19,"author":400,"vertical":401,"topic":402,"tags":403,"_count":408,"playground":409,"hasQuiz":17,"hasPlayground":17},"019fe660-0d25-72d6-8fd8-3cf3c3592e54","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","2026-07-11T08:03:26.200Z",529,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":71,"name":206},[404,405,406,407],{"slug":71,"name":72,"color":48},{"slug":46,"name":47,"color":48},{"slug":51,"name":52,"color":48},{"slug":55,"name":56,"color":48},{"assessments":189},{"slug":394},{"id":411,"slug":412,"title":413,"subtitle":48,"excerpt":414,"coverUrl":415,"locale":13,"readingMinutes":131,"publishedAt":416,"viewCount":417,"likeCount":19,"commentCount":19,"author":418,"vertical":419,"topic":420,"tags":421,"_count":426,"playground":427,"hasQuiz":17,"hasPlayground":17},"019fe660-0596-7433-9dc2-0fc620be2d0f","structuredclone-deep-clone","You've been deep-cloning objects with a JSON hack. `structuredClone` does it right.","JSON.parse(JSON.stringify(obj)) silently corrupts Dates, Maps, Sets, and undefined values. structuredClone is the native replacement — no library, no import, no surprises.","\u002Fmedia\u002Fcovers\u002Fstructuredclone-deep-clone.png","2026-07-10T09:43:33.966Z",492,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":51,"name":248},[422,423,424,425],{"slug":51,"name":52,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":86,"name":87,"color":48},{"assessments":189},{"slug":412},{"id":429,"slug":430,"title":431,"subtitle":48,"excerpt":432,"coverUrl":433,"locale":13,"readingMinutes":284,"publishedAt":434,"viewCount":435,"likeCount":19,"commentCount":19,"author":436,"vertical":437,"topic":438,"tags":439,"_count":444,"playground":445,"hasQuiz":17,"hasPlayground":17},"019fe65f-fe39-767c-9ce8-da4db5144b1d","css-nesting-sass-replaced","You kept Sass for one reason. Native CSS nesting just ended it.","CSS has supported nesting natively since 2023 — pseudo-classes, pseudo-elements, and @media queries nested inside the rules they belong to. No compiler required.","\u002Fmedia\u002Fcovers\u002Fcss-nesting-sass-replaced.png","2026-07-09T09:48:41.505Z",386,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":233},[440,441,442,443],{"slug":63,"name":64,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":51,"name":52,"color":48},{"assessments":189},{"slug":430},{"id":447,"slug":448,"title":449,"subtitle":48,"excerpt":450,"coverUrl":451,"locale":13,"readingMinutes":284,"publishedAt":452,"viewCount":453,"likeCount":19,"commentCount":19,"author":454,"vertical":455,"topic":456,"tags":457,"_count":462,"playground":463,"hasQuiz":17,"hasPlayground":17},"019fe65f-f67a-7038-9c0d-874d6c8ece3c","css-property-registered-custom-properties","You can't transition a CSS variable. @property says otherwise.","CSS custom properties are string substitution — the browser doesn't know a number from a color. Register one with @property and it gains a real type, an initial value, and the ability to animate.","\u002Fmedia\u002Fcovers\u002Fcss-property-registered-custom-properties.png","2026-07-08T08:36:23.824Z",606,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":233},[458,459,460,461],{"slug":63,"name":64,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":51,"name":52,"color":48},{"assessments":189},{"slug":448},{"id":465,"slug":466,"title":467,"subtitle":48,"excerpt":468,"coverUrl":469,"locale":13,"readingMinutes":127,"publishedAt":470,"viewCount":471,"likeCount":19,"commentCount":19,"author":472,"vertical":473,"topic":474,"tags":475,"_count":480,"playground":481,"hasQuiz":17,"hasPlayground":17},"019fe65f-ef22-765a-97c7-cdfdbb168024","scroll-driven-animations","Your scroll listener is doing CSS's job","Reading progress bars, reveal-on-scroll effects, parallax — you've been writing these in JavaScript. CSS scroll-driven animations bind them directly to scroll position, off the main thread, in a handful of lines.","\u002Fmedia\u002Fcovers\u002Fscroll-driven-animations.png","2026-07-06T10:47:02.014Z",447,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":233},[476,477,478,479],{"slug":63,"name":64,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":51,"name":52,"color":48},{"assessments":189},{"slug":466},{"id":483,"slug":484,"title":485,"subtitle":48,"excerpt":486,"coverUrl":487,"locale":13,"readingMinutes":131,"publishedAt":488,"viewCount":489,"likeCount":19,"commentCount":19,"author":490,"vertical":491,"topic":492,"tags":493,"_count":498,"playground":48,"hasQuiz":18,"hasPlayground":18},"019fe65f-e7b8-7175-a185-34775c370bcf","abort-controller-async-cancellation","Your fetch() Is Still Running After the User Left","Stale requests, race conditions in search boxes, state updates on unmounted components — these are all the same bug: async work you forgot to cancel. AbortController is the fix.","\u002Fmedia\u002Fcovers\u002Fabort-controller-async-cancellation.png","2026-07-05T09:12:47.873Z",316,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":51,"name":248},[494,495,496,497],{"slug":51,"name":52,"color":48},{"slug":46,"name":47,"color":48},{"slug":55,"name":56,"color":48},{"slug":75,"name":76,"color":48},{"assessments":19},{"page":500,"perPage":92,"total":501,"totalPages":502},16,202,17,{"items":504,"meta":523},[505],{"id":506,"slug":507,"title":508,"subtitle":48,"excerpt":509,"coverUrl":510,"locale":13,"readingMinutes":284,"publishedAt":511,"viewCount":512,"likeCount":19,"commentCount":19,"author":513,"vertical":514,"topic":515,"tags":516,"_count":521,"playground":522,"hasQuiz":17,"hasPlayground":17},"01a19abd-c743-729e-8f0e-b3cb1dcc0ef5","commandfor-invoker-commands-api","Stop Writing JavaScript to Open Dialogs. `commandfor` Fixes It.","Every \u003Cdialog> 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.","\u002Fmedia\u002Fcovers\u002Fcommandfor-invoker-commands-api.png","2026-11-08T18:35:26.332Z",78,{"id":288,"name":289,"username":290,"avatarUrl":48,"headline":291},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":90,"name":245},[517,518,519,520],{"slug":46,"name":47,"color":48},{"slug":90,"name":91,"color":48},{"slug":51,"name":52,"color":48},{"slug":55,"name":56,"color":48},{"assessments":189},{"slug":507},{"page":189,"perPage":189,"total":501,"totalPages":501}]