[{"data":1,"prerenderedAt":212},["ShallowReactive",2],{"sanity-LevEgKvCUg3Ul3GKyhTsfZIfaGswLQ-qsmdjo9-lWe4":3,"sanity-8a0WewRnAJnMsRUIAmx3wZS61LEwSGA5bu81csNo5Hc":42},{"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","6nvKuEL9zc4dBn99tbDSIo","2026-09-15T23:28:13Z",{"_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":122,"excerpt":134,"footer":26,"layout":135,"mainImage":139,"navigation":26,"publishedAt":143,"readTime":144,"relatedPosts":145,"routeOptions":202,"seo":26,"showOnWebsite":204,"slug":207,"tags":208,"title":211},"post-design-tokens","post",{"avatar":48,"bio":53,"name":54,"role":55,"sameAs":56},{"_type":49,"alt":50,"asset":51},"image","Portrait of Avery Lin",{"_ref":52,"_type":15},"image-7d9d32f0d8cbaa44274ac31144c4acd3b6256c53-512x512-jpg","Avery designs content models for teams moving off page-builder CMSes, and writes about keeping structured content structured.","Avery Lin","Content Architect",[57,58],"https:\u002F\u002Fexample.com\u002Favery-lin","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fexample-avery-lin",{"_ref":60,"_type":15},"author-avery-lin",[62,73,82,90,98,106,114],{"_key":63,"_type":64,"children":65,"markDefs":71,"style":72},"b0041","block",[66],{"_key":67,"_type":68,"marks":69,"text":70},"s0042","span",[],"A colour picker in a CMS looks like a small feature. It is not. One hex value from an editor has to produce a legible accent, a surface tint, a hover state, a border and a glow — on light and dark backgrounds — without anyone checking each combination by hand.",[],"normal",{"_key":74,"_type":64,"children":75,"markDefs":80,"style":81},"b0043",[76],{"_key":77,"_type":68,"marks":78,"text":79},"s0044",[],"Derive, do not enumerate",[],"h2",{"_key":83,"_type":64,"children":84,"markDefs":89,"style":72},"b0045",[85],{"_key":86,"_type":68,"marks":87,"text":88},"s0046",[],"The temptation is to add fields: accent, accentHover, accentBorder, accentSurface. Now the editor owns five decisions instead of one, four of them are wrong, and none of them are checked for contrast. Take the seed colour and derive the rest, nudging toward the page background only far enough to stay readable.",[],{"_key":91,"_type":64,"children":92,"markDefs":97,"style":72},"b0047",[93],{"_key":94,"_type":68,"marks":95,"text":96},"s0048",[],"Expose the results as custom properties on the block root. Hover and open states then work in class-land, which is where they are easiest to reason about, and a block that opts out falls back to the current text colour and simply renders neutral.",[],{"_key":99,"_type":64,"children":100,"markDefs":105,"style":81},"b0049",[101],{"_key":102,"_type":68,"marks":103,"text":104},"s0050",[],"Watch the portals",[],{"_key":107,"_type":64,"children":108,"markDefs":113,"style":72},"b0051",[109],{"_key":110,"_type":68,"marks":111,"text":112},"s0052",[],"Anything teleported out of the tree — dropdowns, calendars, dialogs — leaves the element that defined your custom properties behind. A variable that resolves to nothing paints transparent rather than falling back, so a select panel becomes an invisible rectangle over the page. Resolve those colours to concrete values before handing them to a portal.",[],{"_key":115,"_type":64,"children":116,"markDefs":121,"style":72},"b0053",[117],{"_key":118,"_type":68,"marks":119,"text":120},"s0054",[],"Derived tokens are worth the arithmetic. They turn a support question — why is this text unreadable on our brand colour — into something the system simply cannot produce.",[],[123,130],{"_createdAt":5,"_id":124,"_rev":125,"_type":126,"_updatedAt":127,"slug":128,"title":129},"category-design-systems","fb4cU9w5jE41W7xStm8DMV","category","2026-09-15T23:28:10Z","design-systems","Design Systems",{"_createdAt":5,"_id":131,"_rev":125,"_type":126,"_updatedAt":127,"slug":132,"title":133},"category-content-modelling","content-modelling","Content Modelling","When an editor picks a brand colour, half a dozen derived values have to stay legible. Here is how to derive them once instead of hard-coding them everywhere.",{"_type":136,"layout":137,"pageDesign":138},"post.layout.options","default","design1",{"_type":49,"alt":140,"asset":141},"Abstract magenta gradient representing a derived colour palette",{"_ref":142,"_type":15},"image-c96efd6b55a465dcb615ad80af90714207b25dbc-1600x900-jpg","2026-06-21T09:00:00.000Z",1,[146,168,186],{"_id":147,"authorProfile":148,"categories":155,"excerpt":160,"mainImage":161,"publishedAt":165,"readTime":144,"slug":166,"title":167},"post-dark-mode-axis",{"avatar":149,"name":153,"role":154},{"_type":49,"alt":150,"asset":151},"Portrait of Priya Raman",{"_ref":152,"_type":15},"image-cfc7cc28fea565890fb3a5986f7d299c7704a12a-512x512-jpg","Priya Raman","Design Systems Engineer",[156,157],{"slug":128,"title":129},{"slug":158,"title":159},"performance","Performance","The server cannot know which colour scheme a visitor prefers. Anything you render that depends on it will hydrate differently than it painted.",{"_type":49,"alt":162,"asset":163},"Abstract indigo gradient split between light and dark",{"_ref":164,"_type":15},"image-96db9eded5277118c54a29e63593a6d24a382797-1600x900-jpg","2026-07-09T09:00:00.000Z","dark-mode-is-a-second-axis","Dark mode is a second axis, not a second stylesheet",{"_id":169,"authorProfile":170,"categories":173,"excerpt":178,"mainImage":179,"publishedAt":183,"readTime":144,"slug":184,"title":185},"post-scaffolding",{"avatar":171,"name":153,"role":154},{"_type":49,"alt":150,"asset":172},{"_ref":152,"_type":15},[174,177],{"slug":175,"title":176},"developer-experience","Developer Experience",{"slug":128,"title":129},"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":180,"asset":181},"Abstract green gradient suggesting generated structure",{"_ref":182,"_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":187,"authorProfile":188,"categories":191,"excerpt":194,"mainImage":195,"publishedAt":199,"readTime":144,"slug":200,"title":201},"post-type-scale",{"avatar":189,"name":153,"role":154},{"_type":49,"alt":150,"asset":190},{"_ref":152,"_type":15},[192,193],{"slug":128,"title":129},{"slug":132,"title":133},"Every scale looks balanced against three words of placeholder. The test is a heading an editor actually wrote, on a phone, in two languages.",{"_type":49,"alt":196,"asset":197},"Abstract amber gradient suggesting stepped type sizes",{"_ref":198,"_type":15},"image-aa3a1dd55ed9709d36bafe8f5715c90b8906166f-1600x900-jpg","2026-02-24T09:00:00.000Z","a-type-scale-has-to-survive-real-content","A type scale has to survive real content",{"_type":203,"includeInSitemap":204,"slug":205},"page.routing.options",true,{"_type":206,"current":207},"slug","theme-colours-belong-to-the-content",[129,209,210],"Theming","Accessibility","Theme colours belong to the content, not the stylesheet",1790674588299]