[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"home-articles-all":44,"search-suggestions":172,"home-packages":201,"weekly-game":246,"arcade-strip":261,"code:ts:true:10ilun4":320},[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":168},[46,79,105,126,147],{"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":76,"playground":78,"hasQuiz":17,"hasPlayground":17},"01a066ea-3098-75c9-b7e5-1d5426f773eb","vue-weekly-composables-shared-state-trap","Vue Composables: The Shared State Trap (+ Cheat Sheet)",null,"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",13,"2026-09-22T19:37:11.460Z",54,{"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},"vue","Vue",[66,67,70,73],{"slug":63,"name":64,"color":50},{"slug":68,"name":69,"color":50},"javascript","Javascript",{"slug":71,"name":72,"color":50},"tutorial","Tutorial",{"slug":74,"name":75,"color":50},"webdev","Webdev",{"assessments":77},1,{"slug":48},{"id":80,"slug":81,"title":82,"subtitle":50,"excerpt":83,"coverUrl":84,"locale":13,"readingMinutes":85,"publishedAt":86,"viewCount":87,"likeCount":19,"commentCount":19,"author":88,"vertical":89,"topic":90,"tags":93,"_count":103,"playground":104,"hasQuiz":17,"hasPlayground":17},"01a0a9ea-93a3-7734-b359-6d7cc4df502b","customizable-select-appearance-base-select","The Dropdown You've Been Faking for a Decade","Every hand-built 'custom select' with icons and a styled popup exists because the real \u003Cselect> couldn't do that. appearance: base-select just closed the gap — without you losing the native picker's keyboard nav and mobile UI.","\u002Fmedia\u002Fcovers\u002Fcustomizable-select-appearance-base-select.png",4,"2026-09-22T19:36:39.450Z",49,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":91,"name":92},"css","CSS",[94,96,99,100],{"slug":91,"name":95,"color":50},"Css",{"slug":97,"name":98,"color":50},"html","Html",{"slug":74,"name":75,"color":50},{"slug":101,"name":102,"color":50},"accessibility","Accessibility",{"assessments":77},{"slug":81},{"id":106,"slug":107,"title":108,"subtitle":50,"excerpt":109,"coverUrl":110,"locale":13,"readingMinutes":111,"publishedAt":112,"viewCount":113,"likeCount":19,"commentCount":19,"author":114,"vertical":115,"topic":116,"tags":119,"_count":124,"playground":125,"hasQuiz":17,"hasPlayground":17},"01a0b58a-7f56-736a-babf-1796c7b70c19","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",12,"2026-09-22T19:36:08.416Z",47,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":117,"name":118},"nextjs","Nextjs",[120,121,122,123],{"slug":117,"name":118,"color":50},{"slug":68,"name":69,"color":50},{"slug":71,"name":72,"color":50},{"slug":74,"name":75,"color":50},{"assessments":77},{"slug":107},{"id":127,"slug":128,"title":129,"subtitle":50,"excerpt":130,"coverUrl":131,"locale":13,"readingMinutes":132,"publishedAt":133,"viewCount":134,"likeCount":19,"commentCount":19,"author":135,"vertical":136,"topic":137,"tags":138,"_count":145,"playground":146,"hasQuiz":17,"hasPlayground":17},"01a0af18-24b4-73ad-95ed-c9479ae0e91f","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",6,"2026-09-22T19:35:37.351Z",52,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":91,"name":92},[139,140,141,144],{"slug":91,"name":95,"color":50},{"slug":74,"name":75,"color":50},{"slug":142,"name":143,"color":50},"frontend","Frontend",{"slug":71,"name":72,"color":50},{"assessments":77},{"slug":128},{"id":148,"slug":149,"title":150,"subtitle":50,"excerpt":151,"coverUrl":152,"locale":13,"readingMinutes":153,"publishedAt":154,"viewCount":155,"likeCount":19,"commentCount":19,"author":156,"vertical":157,"topic":158,"tags":161,"_count":166,"playground":167,"hasQuiz":17,"hasPlayground":17},"01a0ab57-dda2-74dd-816b-a0ef7f77aeb3","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",14,"2026-09-20T16:27:07.271Z",166,{"id":57,"name":58,"username":59,"avatarUrl":50,"headline":60},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":159,"name":160},"react","React",[162,163,164,165],{"slug":159,"name":160,"color":50},{"slug":68,"name":69,"color":50},{"slug":71,"name":72,"color":50},{"slug":74,"name":75,"color":50},{"assessments":77},{"slug":149},{"page":77,"perPage":169,"total":170,"totalPages":171},5,123,25,[173,175,177,179,181,183,187,188,191,195,198,200],{"slug":74,"name":75,"articles":174},107,{"slug":68,"name":69,"articles":176},89,{"slug":142,"name":143,"articles":178},72,{"slug":91,"name":95,"articles":180},36,{"slug":71,"name":72,"articles":182},35,{"slug":184,"name":185,"articles":186},"typescript","Typescript",15,{"slug":159,"name":160,"articles":53},{"slug":189,"name":190,"articles":111},"performance","Performance",{"slug":192,"name":193,"articles":194},"browser","Browser",9,{"slug":196,"name":197,"articles":194},"node","Node",{"slug":97,"name":98,"articles":199},7,{"slug":101,"name":102,"articles":199},{"items":202,"meta":245},[203,219,232],{"id":204,"slug":205,"name":205,"scope":50,"registry":206,"tagline":207,"ecosystem":63,"repoUrl":208,"docsUrl":209,"registryUrl":210,"license":211,"isOfficial":18,"weekOf":50,"latestVersion":212,"stars":77,"weeklyDownloads":213,"voteCount":77,"publishedAt":214,"submittedBy":215,"vertical":216,"tags":217,"hasVoted":18},"019fe845-897a-7625-9d65-6d0c7ffe5afa","god-kit","NPM","God Kit — design tokens and Vue 3 primitives for God Plan apps","https:\u002F\u002Fgithub.com\u002Fgod-plans\u002Fgod-kit","https:\u002F\u002Fgodkit.godplans.org\u002F","https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fgod-kit","MIT","0.8.9",20,"2026-05-01T11:34:17.384Z",{"id":57,"name":58,"username":59,"avatarUrl":50},{"slug":6,"name":7},[218],{"slug":63,"name":64},{"id":220,"slug":221,"name":221,"scope":50,"registry":206,"tagline":222,"ecosystem":68,"repoUrl":50,"docsUrl":223,"registryUrl":224,"license":211,"isOfficial":18,"weekOf":50,"latestVersion":225,"stars":19,"weeklyDownloads":226,"voteCount":77,"publishedAt":227,"submittedBy":228,"vertical":229,"tags":230,"hasVoted":18},"019fe845-7fda-7479-bc73-dd73217eba66","cross-framework","Source-to-source converter: React to Vue (and more)","https:\u002F\u002Fcross-framework.netlify.app\u002F","https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fcross-framework","0.1.4",22,"2026-03-25T08:15:50.328Z",{"id":57,"name":58,"username":59,"avatarUrl":50},{"slug":6,"name":7},[231],{"slug":68,"name":69},{"id":233,"slug":234,"name":234,"scope":50,"registry":206,"tagline":235,"ecosystem":63,"repoUrl":236,"docsUrl":50,"registryUrl":237,"license":211,"isOfficial":18,"weekOf":50,"latestVersion":238,"stars":43,"weeklyDownloads":239,"voteCount":19,"publishedAt":240,"submittedBy":241,"vertical":242,"tags":243,"hasVoted":18},"019fe845-82d6-712b-9d51-53e88dff04de","vue-heic-image","Vue 3 HEIC\u002FHEIF image preview and converter for the browser: HeicImage component, useHeicImage composable, PNG\u002FJPEG\u002FGIF output, TypeScript, iOS photos,…","https:\u002F\u002Fgithub.com\u002Fparsajiravand\u002Fvue-heic-image","https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fvue-heic-image","2.0.0",8,"2026-03-24T20:45:24.802Z",{"id":57,"name":58,"username":59,"avatarUrl":50},{"slug":6,"name":7},[244],{"slug":63,"name":64},{"page":77,"perPage":43,"total":186,"totalPages":169},{"id":247,"slug":248,"title":249,"tagline":250,"genre":251,"surface":252,"coverUrl":253,"accentFrom":254,"accentTo":255,"motif":256,"weekKey":257,"featured":18,"sessionSeconds":258,"freeLevels":50,"playCount":19,"playerCount":19,"releaseAt":259,"publishedAt":260},"01a09b23-a070-72da-824c-732950e5dfbe","reaction-time","Reaction Time","Green means click. Everything else is you being too eager.","REFLEX","DOM","\u002Fcovers\u002Fgames\u002Freaction-time.png","rose-400","red-500","pulse","2026-W39",45,"2026-09-22T09:00:00.000Z","2026-09-22T09:00:00.082Z",{"items":262,"meta":318},[263,277,278,289,300,311],{"id":264,"slug":265,"title":266,"tagline":267,"genre":268,"surface":269,"coverUrl":270,"accentFrom":38,"accentTo":11,"motif":271,"weekKey":272,"featured":17,"sessionSeconds":273,"freeLevels":43,"playCount":274,"playerCount":85,"releaseAt":275,"publishedAt":276},"01a09b23-9e30-76d8-8b1d-b3abd9d61c37","neon-snake","Neon Snake","The one everybody already knows how to play.","ARCADE","CANVAS","\u002Fcovers\u002Fgames\u002Fneon-snake.png","snake","2026-W37",90,10,"2026-09-08T09:00:00.000Z","2026-09-13T14:21:47.710Z",{"id":247,"slug":248,"title":249,"tagline":250,"genre":251,"surface":252,"coverUrl":253,"accentFrom":254,"accentTo":255,"motif":256,"weekKey":257,"featured":18,"sessionSeconds":258,"freeLevels":50,"playCount":19,"playerCount":19,"releaseAt":259,"publishedAt":260},{"id":279,"slug":280,"title":281,"tagline":282,"genre":283,"surface":252,"coverUrl":284,"accentFrom":285,"accentTo":10,"motif":286,"weekKey":272,"featured":18,"sessionSeconds":287,"freeLevels":77,"playCount":43,"playerCount":43,"releaseAt":275,"publishedAt":288},"01a09b23-a030-7352-b796-a475b5d99aac","block-fit","Block Fit","Three shapes at a time. No falling, no timer, no mercy.","PUZZLE","\u002Fcovers\u002Fgames\u002Fblock-fit.png","fuchsia-400","blocks",300,"2026-09-13T15:08:36.615Z",{"id":290,"slug":291,"title":292,"tagline":293,"genre":294,"surface":252,"coverUrl":295,"accentFrom":296,"accentTo":297,"motif":298,"weekKey":272,"featured":18,"sessionSeconds":299,"freeLevels":50,"playCount":31,"playerCount":31,"releaseAt":275,"publishedAt":276},"01a09b23-9ff2-74bf-b26c-989fa40d0d4e","daily-word","Daily Word","One five-letter word. Six guesses. Everybody gets the same one.","WORD","\u002Fcovers\u002Fgames\u002Fdaily-word.png","lime-400","emerald-500","letters",180,{"id":301,"slug":302,"title":303,"tagline":304,"genre":283,"surface":252,"coverUrl":305,"accentFrom":306,"accentTo":307,"motif":308,"weekKey":272,"featured":18,"sessionSeconds":309,"freeLevels":31,"playCount":310,"playerCount":169,"releaseAt":275,"publishedAt":276},"01a09b23-9fb2-73cc-9755-81a427f2b7c4","minesweeper","Minesweeper","Thirty years old and still the best logic puzzle on a computer.","\u002Fcovers\u002Fgames\u002Fminesweeper.png","sky-400","indigo-500","grid",240,32,{"id":312,"slug":313,"title":313,"tagline":314,"genre":283,"surface":252,"coverUrl":315,"accentFrom":26,"accentTo":316,"motif":317,"weekKey":272,"featured":18,"sessionSeconds":287,"freeLevels":77,"playCount":19,"playerCount":19,"releaseAt":275,"publishedAt":276},"01a09b23-9f6f-74a5-a27a-21414662f65c","2048","Slide, merge, and try to stop at exactly the wrong moment.","\u002Fcovers\u002Fgames\u002F2048.png","orange-500","tiles",{"total":132,"nextDropAt":319},"2026-09-29T09:00:00.000Z","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> developer \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  learn\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  build\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  ship\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-kwd\">await\u003C\u002Fspan> developer\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">learn\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]