[{"data":1,"prerenderedAt":256},["ShallowReactive",2],{"sanity-LevEgKvCUg3Ul3GKyhTsfZIfaGswLQ-qsmdjo9-lWe4":3,"sanity-yHh8BT97N2HggqMrFWofSjeGH_8FLYEvhXoU3Wcow9o":42,"shiki-block-v-0-0-0-0-0-2-0-1":255},{"data":4},{"_createdAt":5,"_id":6,"_rev":7,"_type":6,"_updatedAt":8,"acceptAllLink":9,"acceptNecessaryLink":18,"bannerColorSource":23,"bannerDescription":24,"bannerTitle":25,"categories":26,"declineAllLink":27,"managePreferencesLink":31,"modalColorSource":23,"modalTitle":35,"preferencesIconColorSource":23,"provider":36,"savePreferencesLink":37,"thirdPartyEmbedCode":26,"title":41},"2026-08-29T18:46:18Z","cookieSettings","C1Syut0iGaGX58H2hZvChS","2026-08-29T18:46:23Z",{"_type":10,"style":11,"title":16,"type":17},"link",{"_type":12,"stylePreset":13},"link.style",{"_ref":14,"_type":15},"link-style-primary","reference","Accept all","button",{"_type":10,"style":19,"title":22,"type":17},{"_type":12,"stylePreset":20},{"_ref":21,"_type":15},"link-style-tertiary-outline","Accept necessary","inherit","We use cookies to enhance your browsing experience and analyse our traffic. Please choose your cookie preferences below.","We use cookies",null,{"_type":10,"style":28,"title":30,"type":17},{"_type":12,"stylePreset":29},{"_ref":21,"_type":15},"Decline all",{"_type":10,"style":32,"title":34,"type":17},{"_type":12,"stylePreset":33},{"_ref":21,"_type":15},"Manage preferences","Cookie Preferences","custom",{"_type":10,"style":38,"title":40,"type":17},{"_type":12,"stylePreset":39},{"_ref":14,"_type":15},"Save preferences","Cookie Settings",{"data":43,"sourceMap":-1},[44],{"_createdAt":5,"_id":45,"_rev":7,"_type":46,"_updatedAt":8,"authorProfile":47,"authorRef":59,"body":61,"categories":163,"excerpt":174,"footer":26,"layout":175,"mainImage":179,"navigation":26,"publishedAt":183,"readTime":89,"relatedPosts":184,"routeOptions":245,"seo":26,"showOnWebsite":247,"slug":250,"tags":251,"title":254},"post-scaffolding","post",{"avatar":48,"bio":53,"name":54,"role":55,"sameAs":56},{"_type":49,"alt":50,"asset":51},"image","Portrait of Priya Raman",{"_ref":52,"_type":15},"image-cfc7cc28fea565890fb3a5986f7d299c7704a12a-512x512-jpg","Priya works on the seam between design tokens and the components that consume them, and is unreasonably interested in how colour behaves when someone else picks it.","Priya Raman","Design Systems Engineer",[57,58],"https:\u002F\u002Fexample.com\u002Fpriya-raman","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fexample-priya-raman",{"_ref":60,"_type":15},"author-priya-raman",[62,73,82,92,100,108,116,124,131,147,155],{"_key":63,"_type":64,"children":65,"markDefs":71,"style":72},"b0203","block",[66],{"_key":67,"_type":68,"marks":69,"text":70},"s0204","span",[],"Adding a block to a component-driven CMS is never one file. There is a schema, a component, a registration so the renderer can find it, and an entry in whichever arrays decide where an editor may insert it. Miss any one of them and the failure is silent.",[],"normal",{"_key":74,"_type":64,"children":75,"markDefs":80,"style":81},"b0205",[76],{"_key":77,"_type":68,"marks":78,"text":79},"s0206",[],"The failure modes are all quiet",[],"h2",{"_key":83,"_type":64,"children":84,"level":89,"listItem":90,"markDefs":91,"style":72},"b0207",[85],{"_key":86,"_type":68,"marks":87,"text":88},"s0208",[],"No schema registration: the type does not exist, and the block cannot be added at all.",1,"number",[],{"_key":93,"_type":64,"children":94,"level":89,"listItem":90,"markDefs":99,"style":72},"b0209",[95],{"_key":96,"_type":68,"marks":97,"text":98},"s0210",[],"No component registration: the block saves fine and renders as nothing on the page.",[],{"_key":101,"_type":64,"children":102,"level":89,"listItem":90,"markDefs":107,"style":72},"b0211",[103],{"_key":104,"_type":68,"marks":105,"text":106},"s0212",[],"Not in the insert menu: the component works, but no editor can reach it.",[],{"_key":109,"_type":64,"children":110,"markDefs":115,"style":72},"b0213",[111],{"_key":112,"_type":68,"marks":113,"text":114},"s0214",[],"None of these throw. They produce a page that is missing a section nobody can explain.",[],{"_key":117,"_type":64,"children":118,"markDefs":123,"style":81},"b0215",[119],{"_key":120,"_type":68,"marks":121,"text":122},"s0216",[],"One command, every file",[],{"_key":125,"_type":126,"colorSource":23,"markDefs":26,"snippet":127},"code0217","code.block",{"_type":128,"code":129,"language":130},"code","# a page block, with schema, component and every registration\nnpm run scaffold:component -- custom.pricing-table\n\n# or a navigation bar \u002F footer variant\nnpm run scaffold:component -- custom.slim-nav --kind navigation","bash",{"_key":132,"_type":64,"children":133,"markDefs":146,"style":72},"b0221",[134,138,142],{"_key":135,"_type":68,"marks":136,"text":137},"s0218",[],"The generator inserts at marker comments (",{"_key":139,"_type":68,"marks":140,"text":141},"s0219",[128],"[scaffold:*]",{"_key":143,"_type":68,"marks":144,"text":145},"s0220",[],") rather than parsing the files it edits, which is why the markers must survive refactors — and it refuses a type name another schema already declares.",[],{"_key":148,"_type":64,"children":149,"markDefs":154,"style":81},"b0222",[150],{"_key":151,"_type":68,"marks":152,"text":153},"s0223",[],"It also encodes the boundary",[],{"_key":156,"_type":64,"children":157,"markDefs":162,"style":72},"b0224",[158],{"_key":159,"_type":68,"marks":160,"text":161},"s0225",[],"Project work lands under custom\u002F on purpose. Everything the three project kinds touch lives there, so a starter update can never collide with it — a convention that is much easier to follow when the tool follows it for you.",[],[164,170],{"_createdAt":5,"_id":165,"_rev":166,"_type":167,"_updatedAt":5,"slug":168,"title":169},"category-developer-experience","2d20vp0kUSy7uZjqDieLmb","category","developer-experience","Developer Experience",{"_createdAt":5,"_id":171,"_rev":166,"_type":167,"_updatedAt":5,"slug":172,"title":173},"category-design-systems","design-systems","Design Systems","Any component that needs six files in five directories will be built wrong by hand eventually. Generating it is cheaper than writing the guide twice.",{"_type":176,"layout":177,"pageDesign":178},"post.layout.options","default","design1",{"_type":49,"alt":180,"asset":181},"Abstract green gradient suggesting generated structure",{"_ref":182,"_type":15},"image-d52abf1b9836ea87c4978039efb609149c6c90de-1600x900-jpg","2026-04-08T09:00:00.000Z",[185,207,229],{"_id":186,"authorProfile":187,"categories":194,"excerpt":199,"mainImage":200,"publishedAt":204,"readTime":89,"slug":205,"title":206},"post-generated-types",{"avatar":188,"name":192,"role":193},{"_type":49,"alt":189,"asset":190},"Portrait of Avery Lin",{"_ref":191,"_type":15},"image-7d9d32f0d8cbaa44274ac31144c4acd3b6256c53-512x512-jpg","Avery Lin","Content Architect",[195,196],{"slug":168,"title":169},{"slug":197,"title":198},"content-modelling","Content Modelling","Types written by hand describe what you believed the schema said. Types generated from it describe what the schema actually says.",{"_type":49,"alt":201,"asset":202},"Abstract cyan gradient suggesting a type graph",{"_ref":203,"_type":15},"image-17a06078263667a676c81409a6913d585588058a-1600x900-jpg","2026-08-12T09:00:00.000Z","generated-types-are-a-contract","Generated types are a contract, not a convenience",{"_id":208,"authorProfile":209,"categories":216,"excerpt":221,"mainImage":222,"publishedAt":226,"readTime":89,"slug":227,"title":228},"post-preview-without-token",{"avatar":210,"name":214,"role":215},{"_type":49,"alt":211,"asset":212},"Portrait of Jordan Hale",{"_ref":213,"_type":15},"image-3a10e41064c69525bf602e7eb0d241fe88c6c9f7-512x512-jpg","Jordan Hale","Front-end Engineer",[217,218],{"slug":168,"title":169},{"slug":219,"title":220},"performance","Performance","A read token in the browser bundle is readable by everyone who loads the page. Preview does not need one — the Studio is already logged in.",{"_type":49,"alt":223,"asset":224},"Abstract magenta gradient suggesting a secure channel",{"_ref":225,"_type":15},"image-9d093d7046bd2c85ee744fbbf5abd458e7e85b75-1600x900-jpg","2026-07-28T09:00:00.000Z","draft-preview-without-shipping-a-token","Draft preview without shipping a token to every visitor",{"_id":230,"authorProfile":231,"categories":234,"excerpt":237,"mainImage":238,"publishedAt":242,"readTime":89,"slug":243,"title":244},"post-hydration-cost",{"avatar":232,"name":214,"role":215},{"_type":49,"alt":211,"asset":233},{"_ref":213,"_type":15},[235,236],{"slug":219,"title":220},{"slug":168,"title":169},"A component that fetches after it mounts has quietly moved work from your build machine onto a stranger's phone — and taken your read token with it.",{"_type":49,"alt":239,"asset":240},"Abstract blue gradient suggesting a request waterfall",{"_ref":241,"_type":15},"image-d7eee5de5f25ffeb4e27b87a0c3628c89f2cfc12-1600x900-jpg","2026-03-19T09:00:00.000Z","every-query-in-the-browser-is-a-decision","Every query in the browser is a decision you can move",{"_type":246,"includeInSitemap":247,"slug":248},"page.routing.options",true,{"_type":249,"current":250},"slug","a-scaffolder-is-documentation-that-runs",[169,252,253],"Tooling","Sanity Studio","A scaffolder is documentation that runs","\u003Cpre class=\"shiki shiki-themes github-light github-dark nuxion-code__pre\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-dark:#85E89D\">script\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> setup\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> lang\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"ts\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Fetched once, at build time, into the prerendered payload.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">data\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> useSanityContent\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">BlogIndexQueryResult\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    blogIndexQuery\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Paging and search are derived from it — no second request.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> matching\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> computed\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(() \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    (data.value?.posts \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">??\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> []).\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">filter\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(matchesFilters)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-dark:#85E89D\">script\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",1788029822980]