[{"data":1,"prerenderedAt":241},["ShallowReactive",2],{"sanity-LevEgKvCUg3Ul3GKyhTsfZIfaGswLQ-qsmdjo9-lWe4":3,"sanity-DbWHLUezkOABC0rfbLUIU9g2bOoa5hleeH7vDbPO3Jo":42,"shiki-block-v-0-0-0-0-0-2-0-1":240},{"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":58,"body":60,"categories":146,"excerpt":157,"footer":26,"layout":158,"mainImage":162,"navigation":26,"publishedAt":166,"readTime":167,"relatedPosts":168,"routeOptions":229,"seo":26,"showOnWebsite":231,"slug":234,"tags":235,"title":239},"post-preview-without-token","post",{"avatar":48,"bio":53,"name":54,"role":55,"sameAs":56},{"_type":49,"alt":50,"asset":51},"image","Portrait of Jordan Hale",{"_ref":52,"_type":15},"image-3a10e41064c69525bf602e7eb0d241fe88c6c9f7-512x512-jpg","Jordan builds front ends that stay fast after launch, and spends most of that time deleting work the browser was never asked to do.","Jordan Hale","Front-end Engineer",[57],"https:\u002F\u002Fexample.com\u002Fjordan-hale",{"_ref":59,"_type":15},"author-jordan-hale",[61,72,81,89,98,106,123,130,138],{"_key":62,"_type":63,"children":64,"markDefs":70,"style":71},"b0182","block",[65],{"_key":66,"_type":67,"marks":68,"text":69},"s0183","span",[],"Previewing unpublished content on a statically generated site looks like it needs a server. There is no request to read a draft through, so the obvious fix is a token in the client bundle — which is to say a token published to everybody who visits.",[],"normal",{"_key":73,"_type":63,"children":74,"markDefs":79,"style":80},"b0184",[75],{"_key":76,"_type":67,"marks":77,"text":78},"s0185",[],"Let the authenticated window do the query",[],"h2",{"_key":82,"_type":63,"children":83,"markDefs":88,"style":71},"b0186",[84],{"_key":85,"_type":67,"marks":86,"text":87},"s0187",[],"The Studio is already authenticated as the editor. So the preview page fetches nothing at all: the Studio runs the projection and posts the result into the preview window, re-running it on a subscription so the pane updates as the document is saved.",[],{"_key":90,"_type":63,"children":91,"markDefs":96,"style":97},"b0188",[92],{"_key":93,"_type":67,"marks":94,"text":95},"s0189",[],"The Studio runs the query; the preview page only renders the answer.",[],"blockquote",{"_key":99,"_type":63,"children":100,"markDefs":105,"style":80},"b0190",[101],{"_key":102,"_type":67,"marks":103,"text":104},"s0191",[],"Both ends of a postMessage are untrusted",[],{"_key":107,"_type":63,"children":108,"markDefs":122,"style":71},"b0195",[109,113,118],{"_key":110,"_type":67,"marks":111,"text":112},"s0192",[],"Anything that can reach a window can post to it, so origins are matched exactly in both directions and the payload stays untrusted until it has been validated. Never post to ",{"_key":114,"_type":67,"marks":115,"text":117},"s0193",[116],"code","'*'",{"_key":119,"_type":67,"marks":120,"text":121},"s0194",[]," — the message names a document to serve.",[],{"_key":124,"_type":125,"colorSource":23,"markDefs":26,"snippet":126},"code0196","code.block",{"_type":116,"code":127,"filename":128,"language":129},"\u002F\u002F shared\u002FpreviewChannel.ts — imported by BOTH sides, so the two\n\u002F\u002F cannot disagree about the message shape or the projection.\nexport const PREVIEW_QUERIES: Record\u003Cstring, string> = {\n    page: pageByIdQuery,\n    post: blogPostByIdQuery,\n}","shared\u002FpreviewChannel.ts","typescript",{"_key":131,"_type":63,"children":132,"markDefs":137,"style":80},"b0197",[133],{"_key":134,"_type":67,"marks":135,"text":136},"s0198",[],"The remaining case for a browser token",[],{"_key":139,"_type":63,"children":140,"markDefs":145,"style":71},"b0199",[141],{"_key":142,"_type":67,"marks":143,"text":144},"s0200",[],"There is one, and it is narrow: a private dataset queried from the browser on purpose. That should be an explicit opt-in with its own environment variable — not something that arrives as a side effect of turning previews on.",[],[147,153],{"_createdAt":5,"_id":148,"_rev":149,"_type":150,"_updatedAt":5,"slug":151,"title":152},"category-developer-experience","2d20vp0kUSy7uZjqDieLmb","category","developer-experience","Developer Experience",{"_createdAt":5,"_id":154,"_rev":149,"_type":150,"_updatedAt":5,"slug":155,"title":156},"category-performance","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":159,"layout":160,"pageDesign":161},"post.layout.options","default","design1",{"_type":49,"alt":163,"asset":164},"Abstract magenta gradient suggesting a secure channel",{"_ref":165,"_type":15},"image-9d093d7046bd2c85ee744fbbf5abd458e7e85b75-1600x900-jpg","2026-07-28T09:00:00.000Z",1,[169,191,213],{"_id":170,"authorProfile":171,"categories":178,"excerpt":183,"mainImage":184,"publishedAt":188,"readTime":167,"slug":189,"title":190},"post-generated-types",{"avatar":172,"name":176,"role":177},{"_type":49,"alt":173,"asset":174},"Portrait of Avery Lin",{"_ref":175,"_type":15},"image-7d9d32f0d8cbaa44274ac31144c4acd3b6256c53-512x512-jpg","Avery Lin","Content Architect",[179,180],{"slug":151,"title":152},{"slug":181,"title":182},"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":185,"asset":186},"Abstract cyan gradient suggesting a type graph",{"_ref":187,"_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":192,"authorProfile":193,"categories":200,"excerpt":205,"mainImage":206,"publishedAt":210,"readTime":167,"slug":211,"title":212},"post-scaffolding",{"avatar":194,"name":198,"role":199},{"_type":49,"alt":195,"asset":196},"Portrait of Priya Raman",{"_ref":197,"_type":15},"image-cfc7cc28fea565890fb3a5986f7d299c7704a12a-512x512-jpg","Priya Raman","Design Systems Engineer",[201,202],{"slug":151,"title":152},{"slug":203,"title":204},"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":49,"alt":207,"asset":208},"Abstract green gradient suggesting generated structure",{"_ref":209,"_type":15},"image-d52abf1b9836ea87c4978039efb609149c6c90de-1600x900-jpg","2026-04-08T09:00:00.000Z","a-scaffolder-is-documentation-that-runs","A scaffolder is documentation that runs",{"_id":214,"authorProfile":215,"categories":218,"excerpt":221,"mainImage":222,"publishedAt":226,"readTime":167,"slug":227,"title":228},"post-hydration-cost",{"avatar":216,"name":54,"role":55},{"_type":49,"alt":50,"asset":217},{"_ref":52,"_type":15},[219,220],{"slug":155,"title":156},{"slug":151,"title":152},"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":223,"asset":224},"Abstract blue gradient suggesting a request waterfall",{"_ref":225,"_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":230,"includeInSitemap":231,"slug":232},"page.routing.options",true,{"_type":233,"current":234},"slug","draft-preview-without-shipping-a-token",[236,237,238],"Preview","Security","Static Generation","Draft preview without shipping a token to every visitor","\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>",1788029822584]