<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stéphane LaFlèche</title>
    <description>The latest articles on DEV Community by Stéphane LaFlèche (@slafleche).</description>
    <link>https://dev.to/slafleche</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3945110%2F9f2496df-2161-4a89-b93d-066f91ce5e75.jpeg</url>
      <title>DEV Community: Stéphane LaFlèche</title>
      <link>https://dev.to/slafleche</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/slafleche"/>
    <language>en</language>
    <item>
      <title>Figma-to-code: the real shift happening</title>
      <dc:creator>Stéphane LaFlèche</dc:creator>
      <pubDate>Sat, 04 Jul 2026 12:58:59 +0000</pubDate>
      <link>https://dev.to/slafleche/figma-to-code-the-real-shift-happening-7a3</link>
      <guid>https://dev.to/slafleche/figma-to-code-the-real-shift-happening-7a3</guid>
      <description>&lt;p&gt;&lt;em&gt;If you're shipping static sites, or building on a standard design system, the Figma MCP server is probably doing great work for you, and a lot of what follows will match what you already see. Stay for the &lt;strong&gt;edges&lt;/strong&gt;, though: the moment you need a custom component, or the model edits an existing one, it is guessing again, and nobody is recording why. That is the friction this is about, for anyone trying to make the design-to-code pipeline more modular, maintainable, robust, tool-agnostic, and get better code out the other end.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I started writing this as a takedown. It didn't survive the reporting.&lt;/p&gt;

&lt;p&gt;The plan was simple: Figma-to-code is overhyped, the demos are slick, and on most teams the reality is a mess. I was going to show you how bad it gets: the hard-coded colours, the components the model invents, the output that looks right until you actually read it.&lt;/p&gt;

&lt;p&gt;Then I came across monday.com's design-to-code pipeline&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, and I was &lt;strong&gt;genuinely&lt;/strong&gt; impressed.&lt;/p&gt;

&lt;p&gt;What monday showed me is that it can be done well, even if a developer is still cleaning up the code behind the demo.&lt;/p&gt;

&lt;p&gt;The closer I looked, the more the piece stopped being about tools at all. The tools, the pipelines, the pricing, all of it keeps shifting. But underneath that noise is a quieter shift, the one I did not expect and cannot stop thinking about: a change in who actually does the work, and, perhaps more importantly, who &lt;em&gt;owns&lt;/em&gt; the decisions the tools quietly make for us. That is where this ends up, and I think it raises deeper questions about code quality and responsibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  On the surface, it looks settled
&lt;/h2&gt;

&lt;p&gt;Point a large language model at a Figma file through an MCP server, and it hands you back components. That is the pipeline the whole industry is converging on. Design happens in Figma; the code gets generated by a small set of AI agents: Copilot, Cursor, Claude Code, Codex.&lt;/p&gt;

&lt;p&gt;That convergence is real, and the numbers behind it are lopsided. Figma is the default surface, named by 82.3% of designers as their primary UI-design tool.&lt;sup id="fnref2"&gt;2&lt;/sup&gt; Its own codegen feature, Figma Make, is already used weekly by around 60% of Figma customers who spend over $100k a year.&lt;sup id="fnref3"&gt;3&lt;/sup&gt; The inputs are consolidating onto one tool.&lt;/p&gt;

&lt;p&gt;So is the format. Design tokens reached their first stable standard, DTCG, in late 2025, backed by roughly two dozen of the largest names in the field: Adobe, Google, Microsoft, Meta, Amazon, Figma.&lt;sup id="fnref4"&gt;4&lt;/sup&gt; The build tooling is adopting it. Style Dictionary,&lt;sup id="fnref5"&gt;5&lt;/sup&gt; the most widely used token transformer, now ships first-class DTCG support. Smaller tools like Terrazzo&lt;sup id="fnref6"&gt;6&lt;/sup&gt; are DTCG-native, built around the format from the start. Google publishes DESIGN.md,&lt;sup id="fnref7"&gt;7&lt;/sup&gt; a way to describe a design system to a coding agent. Everyone is pointing the same direction. Even Figma backs the standard. A widely used community token plugin for Figma, Tokens Studio,&lt;sup id="fnref8"&gt;8&lt;/sup&gt; reads and writes the DTCG format too. The incumbent is lining up behind an open format that makes its own tool easier to leave.&lt;/p&gt;

&lt;p&gt;From a distance, the problem looks solved. One tool for design, a converging standard for tokens, a handful of capable agents to write the code. Call this the shift everyone already noticed: the tooling converged. Settled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then you actually run it
&lt;/h2&gt;

&lt;p&gt;Point an unscaffolded model at a real Figma file and the output is plausible until you read it. It reaches for components that are not in your system, hard-codes colours that should be tokens, and mixes conventions across versions (Tailwind v3 patterns dropped into a v4 project).&lt;sup id="fnref9"&gt;9&lt;/sup&gt; Sometimes it invents CSS outright, a value like &lt;code&gt;fit-parent&lt;/code&gt; that no browser understands.&lt;sup id="fnref10"&gt;10&lt;/sup&gt; This is not a skill problem or a bad prompt. It is what the naive pipeline does, to everyone. It is not a model problem either. Output quality varies sharply, by model and by task, and it is improving fast. But a stronger model guesses better; it does not stop guessing, because the information it needs was never in the file for any model to read.&lt;/p&gt;

&lt;p&gt;Figma says so itself. Its own MCP setup guide&lt;sup id="fnref11"&gt;11&lt;/sup&gt; is blunt about the limit: without Code Connect linking your Figma components to your real code, "the model is guessing." Coming from the vendor of the design tool itself, that admission is worth more than any third-party benchmark.&lt;/p&gt;

&lt;p&gt;Why does it guess? Because the file hands it a bare value with no meaning: a &lt;code&gt;FLOAT&lt;/code&gt; of &lt;code&gt;10&lt;/code&gt;, with nothing to say whether that is ten pixels, a z-index, or ten milliseconds. I dug into that failure in &lt;a href="https://dev.to/slafleche/even-figma-isnt-sure-about-its-own-design-tokens-4mko"&gt;Even Figma isn't sure about its own design tokens&lt;/a&gt;; the short version is that the step from raw value to semantic meaning, the resolve step, is unowned and lossy. The model has to infer what the design meant, because the file never says.&lt;/p&gt;

&lt;p&gt;To be fair, Figma is closing part of this. Native DTCG export is rolling out, so you can pull your tokens out as typed JSON where a value finally carries its meaning.&lt;sup id="fnref12"&gt;12&lt;/sup&gt; But that types the tokens you export, not the values a model reads back when it generates code from a component. On that path it often gets a bare resolved number with no token attached, and is left to improvise. That gap is here now, not on some roadmap, and it is the one monday set out to close.&lt;/p&gt;

&lt;p&gt;The token is only the visible edge of it. "Point an LLM at Figma, get UI" looks like one task, but it is a stack of collapsed decisions the model resolves silently in a single pass. Amrutha Kollu&lt;sup id="fnref13"&gt;13&lt;/sup&gt; frames the split well. Some of those decisions are deterministic and have a correct answer: which token, which spacing, which component. Others are genuine judgment calls. The mistake is handing both kinds to the model at once and hoping. By default, nobody owns that deterministic layer, the &lt;a href="https://dev.to/slafleche/were-making-the-dreamweaver-mistake-again-on-purpose-this-time-ema"&gt;missing middle&lt;/a&gt; I wrote about before, so the model fills it in.&lt;/p&gt;

&lt;p&gt;You do not have to take my word for it. When Yi Gui and colleagues built Figma2Code,&lt;sup id="fnref14"&gt;14&lt;/sup&gt; a benchmark for turning real Figma files into code, the strongest proprietary models produced visually faithful output but stayed weak on layout responsiveness and maintainability, because they map the primitive values straight out of the Figma metadata without recovering the structure. Faithful pixels, guessed architecture.&lt;/p&gt;

&lt;p&gt;If this were a prompting problem, the vendor that owns the entire stack would have solved it. Figma didn't. Figma Make, its own generator, produces standalone code by default; to make it build against your design system, you first have to author "Make kits"&lt;sup id="fnref15"&gt;15&lt;/sup&gt; that package your components, tokens, and guidelines so the generator has something real to work from. So even the company that owns the whole stack cannot make its generator fit your design system for you. It hands you some tooling, but as it stands today that tooling is thin. You still author and maintain the kits yourself, and that is not free. It is real, ongoing work, heaviest on the small or mid-size team just trying to get up and running. Worse, those kits are Figma-specific, so the effort ties you tightly to one vendor instead of leaving you portable.&lt;/p&gt;

&lt;p&gt;None of this is a technical wall. DTCG is a standard, and any model can read agnostic tokens from any system that exports them cleanly. What keeps you locked in is not the tech; it is that every vendor has a reason to keep you inside its walls. That could change. Right now it has not, and that is the tell. The problem is not the prompt. It is the architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What monday built instead
&lt;/h2&gt;

&lt;p&gt;The teams I've seen who have solid design-to-code pipelines stopped tinkering with prompts and rebuilt the pipeline itself. The team at monday.com hit exactly this problem, and instead of prompting harder, they built the sharpest version of the standard pipeline I have found anywhere publicly. It is not a new kind of thing. It is a far better-engineered version of what everyone is already reaching for: a real multi-agent pipeline, and a simple but effective workaround for the token problem. Their engineering team wrote it up&lt;sup id="fnref1"&gt;1&lt;/sup&gt;: the naive version failed the same way it fails everyone. "The problem wasn't that the model was bad," they note. "It's that the model had no understanding of what the design system actually was... Without that context, it guessed." So they gave it the understanding.&lt;/p&gt;

&lt;p&gt;There is one detail that amuses me. Figma hands over bare values (the &lt;code&gt;FLOAT&lt;/code&gt; &lt;code&gt;10&lt;/code&gt; problem from earlier), so monday makes the spacing and token values visible inside the design itself, laid out for the model to read. The spec, they say, is written for AI, not for a person.&lt;sup id="fnref16"&gt;16&lt;/sup&gt; It is a workaround for sure, not elegant. However, sometimes the low-tech fix is the easiest one, even when the rest of what they built is this advanced.&lt;/p&gt;

&lt;p&gt;The shape is a pipeline of eleven small nodes, each with one job, orchestrated with LangGraph. It pulls the raw design out of Figma, then resolves it: raw values become semantic tokens, components get matched against the real library, examples get retrieved. What comes out the far end is not code. It is structured context, everything the model needs to know about the design, handed to whatever agent the developer already runs in Cursor.&lt;/p&gt;

&lt;p&gt;That last choice is the clever one. Internally, monday runs hundreds of microfrontends on different React and design-system versions, so forcing a single generated code style would break ownership. By returning context instead of code, they kept the codegen model-agnostic and left authority with each team. They even exposed the whole agent as an MCP tool, so from Cursor's side it is just another tool call. In their words, this is "orchestration, not magic."&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;There is a second thing I appreciate, further down the flow. What the developer ends up with is not a bare component but a full Storybook entry. The stories, the tests, and the documentation are generated alongside it, and the props table is drawn from the real component rather than filled in by hand.&lt;sup id="fnref17"&gt;17&lt;/sup&gt; The deliverable is a documented, tested component, not code that merely renders.&lt;/p&gt;

&lt;p&gt;It works for one reason: someone owns the resolve step that almost everyone else leaves to chance. It also took a mature design system to resolve against, a dedicated pipeline, and the engineers to build and run it. &lt;em&gt;Hold onto that, because it is where the story turns.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where even monday stops
&lt;/h2&gt;

&lt;p&gt;For all that, it is still not hands-off. The honest part is that they say so themselves.&lt;/p&gt;

&lt;p&gt;In their walkthrough talk,&lt;sup id="fnref18"&gt;18&lt;/sup&gt; Elad Mizrahi, monday's design-systems lead, puts the number at 70 to 90 percent of a component's code generated, higher for the simple ones, lower for the complex, and then "our developers take it from there." Impressive, and a long way from automatic. Someone still writes the last 10 to 30 percent.&lt;/p&gt;

&lt;p&gt;Notice what that number costs, too. The 70 to 90 percent is what a mature design system, a dedicated pipeline, and a team of engineers buys you, not to mention an AI bill they have never put a number on. It is the ceiling for the best-resourced setup in the room, not the starting line for everyone else.&lt;/p&gt;

&lt;p&gt;One of Mizrahi's observations points ahead. The model does better on &lt;strong&gt;new components&lt;/strong&gt; than on edits to old ones.&lt;sup id="fnref19"&gt;19&lt;/sup&gt; He does not say why. My guess is that the old components carry incomplete recorded reasoning to edit against, so the model is back to guessing what the original decision was.&lt;/p&gt;

&lt;p&gt;You can watch the ceiling on camera. Asked to flip a component to an inverted colour scheme live, the model missed; he fed it an example; it missed again. This component, he explained, "we need to do some overrides to make it work," and he was candid: "when you show it to somebody it's not always working."&lt;sup id="fnref20"&gt;20&lt;/sup&gt; So he fixed it himself, by hand, applying the override the model could not. The pipeline got him close; a person closed the last gap.&lt;/p&gt;

&lt;p&gt;Even with its faults, you could argue this will only keep getting better with time. The real strength here is not the last mile of code; it is the shape of the multi-agent pipeline and the guardrails and rules they have built around their ecosystem. Every feature still gets a manual design review and a manual code review; the changes "still need to be approved by a person." As he puts it, "we don't want to just rely blindly on AI."&lt;sup id="fnref21"&gt;21&lt;/sup&gt; This is a very good head start, not an autopilot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The wall isn't a monday problem
&lt;/h2&gt;

&lt;p&gt;The wall is not a monday problem. The same ceiling shows up across setups that could not be more different. At Shopify, designers prototype in a code-connected clone of the actual admin. A designer there described the handoff plainly: the generated code gets an engineer to about 80 percent,&lt;sup id="fnref22"&gt;22&lt;/sup&gt; and the rest is the tightening, the internationalization of strings, the polish, the slop code, the parts that are not production-aligned. At Ramp, a designer using an off-the-shelf prototyping tool with rough approximations of the design system gets to about 70 percent, then goes back into Figma for the real handoff.&lt;sup id="fnref23"&gt;23&lt;/sup&gt; Line the self-reported numbers up and they cluster tight: monday's 70 to 90 percent,&lt;sup id="fnref18"&gt;18&lt;/sup&gt; Shopify's 80, Ramp's 70. Optimistic, self-reported figures.&lt;sup id="fnref24"&gt;24&lt;/sup&gt; Whether it is monday's bespoke pipeline or Ramp's off-the-shelf tool, the number lands in the same place.&lt;/p&gt;

&lt;p&gt;There is a stranger shift buried in those setups. Here is what I expected. With seemingly every company now hiring full-stack developers, I assumed the developers would be the ones vibe-coding the UI, reaching for AI to get their own work done faster. What I found is the reverse: it is the designers building the prototypes, and the dev team reuses and finishes them. That inversion blurs the line between designer and developer, the same pendulum I &lt;a href="https://dev.to/slafleche/were-making-the-dreamweaver-mistake-again-on-purpose-this-time-ema"&gt;wrote about&lt;/a&gt; with the Dreamweaver era.&lt;/p&gt;

&lt;p&gt;I will be honest: I am skeptical of that number as a measure of code quality. Even 70 percent seems high unless the component is very simple. Pointing Cursor and Claude at a Figma file through the MCP server, I have had output that looked 70 percent done and turned out closer to 30 once I read it, because the number counts only the visible layer. The layout and the happy path are the cheap part; the states, the edge cases, the accessibility, and the production-alignment are most of the real work, and none of it shows up in the demo that produced the number. That is where a developer comes in. Ramp's designer admits those prototypes are not even functional.&lt;sup id="fnref23"&gt;23&lt;/sup&gt; The prototype is not the product.&lt;/p&gt;

&lt;p&gt;I doubt those percentages count accessibility at all, and it is the clearest thing a static Figma file cannot carry: no focus order, no ARIA role, no announced state, so the model guesses. Where it has been measured, the default fails: a 2025 benchmark that put four leading models, Claude and GPT-4o among them, through eleven standard components found all of them producing accessibility violations that took follow-up prompting to clear,&lt;sup id="fnref25"&gt;25&lt;/sup&gt; and even shadcn/ui, a library sold as accessible by default, ships an example component missing three required ARIA attributes.&lt;sup id="fnref26"&gt;26&lt;/sup&gt; This is less about the model being weak than about a decision no one owns, the least-measured layer because it is the least recorded.&lt;/p&gt;

&lt;p&gt;None of that makes the prototype worthless. Getting a designer to a clickable version of the real thing is genuinely useful. They feel how it behaves, they catch what a static mockup hides, and they can put it in front of a stakeholder to win sign-off before anyone writes production code. The generation earns its keep. It just earns it as a prototype, not as the product.&lt;/p&gt;

&lt;p&gt;The field beyond them is crowded. Some generate from scratch (v0, Lovable, Bolt, Figma Make);&lt;sup id="fnref27"&gt;27&lt;/sup&gt; some do vendor codegen (Builder.io, Anima, Figma's own Dev Mode and Code Connect);&lt;sup id="fnref28"&gt;28&lt;/sup&gt; some make the canvas the code (Subframe, Paper).&lt;sup id="fnref29"&gt;29&lt;/sup&gt; Others work the edges: Google's DESIGN.md&lt;sup id="fnref7"&gt;7&lt;/sup&gt; and Christine Vallaure&lt;sup id="fnref30"&gt;30&lt;/sup&gt; improve the input, Brad Frost&lt;sup id="fnref31"&gt;31&lt;/sup&gt; constrains generation to the system, Romina Kavcic&lt;sup id="fnref32"&gt;32&lt;/sup&gt; detects and heals drift, and Amrutha Kollu's Fixel&lt;sup id="fnref13"&gt;13&lt;/sup&gt; verifies the generated code against live Figma on every pull request, blocking the merge when it drifts and posting the difference back onto the canvas. I can't do justice to any of them here; the point is to document a snapshot of the current shape of the field.&lt;/p&gt;

&lt;p&gt;Step back and the gap is clear: we are trying plenty of ways to generate the code, but no one is fully mapping the decisions that need to be made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results will vary
&lt;/h2&gt;

&lt;p&gt;The pipeline that looks settled is not settled, and it is unsettled in two separate ways. Getting started is easy; getting good results is not, and that takes a foundation most teams do not have. Then there is an external market that will not sit still. They are not the same problem, and blaming the tools for the first one is a mistake.&lt;/p&gt;

&lt;p&gt;Start with the prerequisite. Even monday's pipeline presupposes a mature, documented design system to resolve against, and most teams do not have one. Romina Kavcic analyzed 158 public design systems&lt;sup id="fnref33"&gt;33&lt;/sup&gt; and the drop-off is steep: 89 percent ship code examples, but only 37 percent document usage guidelines, 21 percent accessibility, and 13 percent the content inside components. The systems that score full marks are Polaris,&lt;sup id="fnref34"&gt;34&lt;/sup&gt; Paste,&lt;sup id="fnref35"&gt;35&lt;/sup&gt; and eBay's Playbook,&lt;sup id="fnref36"&gt;36&lt;/sup&gt; the ones run by companies with dedicated infrastructure teams and years behind them. Her conclusion is the one that lands here: "agents can only work with what's documented... many systems aren't ready for a human to use properly, let alone a machine. Fix the layers first." This part is not a failure of the AI. It is a mirror held up to how most design systems are actually run. Point an agent at a chaotic system and it does not fix the chaos; it automates it at scale. Garbage in, garbage out, faster.&lt;/p&gt;

&lt;p&gt;There is a fair objection here: just adopt a standard design system like MUI or shadcn and inherit a documented, mature foundation. For a small team starting out, that is genuinely the better move. But it stops covering you the moment you need custom work, and then you are back to authoring and documenting the decisions the model cannot make on its own, the exact foundation most teams were just found to be missing. A standard system is a great place to start. It is not a place most real products get to stay.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ground keeps moving
&lt;/h2&gt;

&lt;p&gt;Clear that barrier, build a pristine foundation, and you are still not on solid ground. This is the only part of the piece with a dollar sign in it, and you do not need to care about stocks to read it. But the economics underneath these tools are brittle, and that matters for your pipeline.&lt;/p&gt;

&lt;p&gt;Start with the bill. The AI coding underneath all of this is sold below what it costs to run, funded by investors betting demand catches up.&lt;sup id="fnref37"&gt;37&lt;/sup&gt; It might. But the gap is stark: Anthropic, whose Claude models most of these tools run on,&lt;sup id="fnref38"&gt;38&lt;/sup&gt; just committed to pay xAI $1.25 billion a month for GPUs, per SpaceX's own SEC filing,&lt;sup id="fnref39"&gt;39&lt;/sup&gt; while its CFO testified in court that the company has earned a little over $5 billion across its whole existence.&lt;sup id="fnref40"&gt;40&lt;/sup&gt; A capital-fuelled buildout running ahead of its revenue is a shape we have seen before.&lt;sup id="fnref41"&gt;41&lt;/sup&gt; The price you build against today is not the price you are promised tomorrow. GitHub already moved Copilot to metered billing;&lt;sup id="fnref42"&gt;42&lt;/sup&gt; monday can absorb a reprice, but the three-person team running the same agents is exactly who gets caught when the meter turns on. The deeper you build on it, the worse the exposure: a pipeline scaffolded to one model does not swap out cleanly.&lt;/p&gt;

&lt;p&gt;The ground under the tools is moving too. Figma peaked near $142 a share after its 2025 IPO and trades in the low $20s now; Adobe, still posting record revenue, is down more than a third on the year.&lt;sup id="fnref43"&gt;43&lt;/sup&gt; You do not need to call where any of it lands to plan around it.&lt;/p&gt;

&lt;p&gt;So what do you do while all of this keeps moving? You keep your project as loosely coupled to any one tool as you can. The pull is always toward the single integrated vendor that does everything, and it is a real pull, because one place to design, generate, and deploy is genuinely easier. Resist it anyway, because the dominant design tool has already turned over twice in about fifteen years, Photoshop to Sketch to Figma,&lt;sup id="fnref44"&gt;44&lt;/sup&gt; and betting your whole pipeline on today's leader is a bet. Treat any one vendor as a swappable adapter, and keep the parts you own (the resolve step, the token layer, the codegen) open, decoupled, and portable. In times this uncertain, the decoupled project is the one that survives the next shift.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shift I didn't see coming
&lt;/h2&gt;

&lt;p&gt;The shift I did not see coming is not in the tooling. It is in &lt;em&gt;who&lt;/em&gt; does the work, and it is already happening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designer ownership spreads up
&lt;/h3&gt;

&lt;p&gt;On one side, designer ownership spreads up the pipeline into code. They vibe-code the prototype now, they feel the real thing behave, they win the stakeholder sign-off, and they do it in a running interface instead of a static mockup. That is a genuine expansion of the job. It is also bounded: the prototypes are "not functional," the demo is not the product, and the layer they own stops at the prototype. I would call this role &lt;strong&gt;prototyping designer&lt;/strong&gt;: a designer who now designs or validates their work in code, up to the edge of production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer ownership shrinks down
&lt;/h3&gt;

&lt;p&gt;On the other side, a developer's role shrinks down, farther in the pipeline. They pick the work up later now, cleaning and finishing the code after its shape is already set, and they are less involved in the early structural decisions they used to own. That leaves a gap. The decisions that need the most engineering judgment are the ones no human is clearly making anymore, so the model guesses them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The missing middle: decisions
&lt;/h2&gt;

&lt;p&gt;Here is where I stop reporting and start speculating. I do not think the gap is mainly about resources or model quality; resources get you to this ceiling, and better models will keep nudging the percentage up. I think it is about what the pipeline actually carries. Concretely, monday's pipeline resolves values: it turns a raw Figma value into the right semantic token. What it does not carry is decisions, the recorded reasoning for why a component was built the way it was. When the model edits an old component, it has no record of that reasoning, so it is left to assume. Kavcic, who has built one of these systems herself, names the cost of that plainly: "when a human expert fails, they come back with a reason... with agents, 25 failures land on your desk, and none of them come with insight. No ownership, no explanation, no learning."&lt;sup id="fnref32"&gt;32&lt;/sup&gt; A pipeline that cannot explain itself cannot really be trusted to maintain itself. Or, as she puts it, AI cannot fix taste.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Design Engineer
&lt;/h3&gt;

&lt;p&gt;Someone has to own that gap, and there is already a name for the person who sits between design and engineering: a &lt;strong&gt;Design Engineer&lt;/strong&gt;.&lt;sup id="fnref45"&gt;45&lt;/sup&gt; What is new is how they spend their time. Part of it is making the decisions the pipeline leaves unmade, mapping the design into terms the code and the model can both act on. Those decisions run a wide range: at the simple end, a design token to a code variable, where the designer's "x" becomes the code's "y"; in between, a relationship, where a new component is really a variation of an existing one to import and reuse; at the hard end, major architecture decisions, splitting one screen into ten microfrontends across separate repos, frameworks, and design systems. Beyond the mapping, I am speculating. A Design Engineer might also push prototypes the last stretch toward production. My impression is that the role works best when they sit close to the designers as they prototype, not only downstream once the code needs finishing. Close to both sides is where they would keep finding new ways to make the system itself better. Write the decision down and a model can execute it. It still cannot reliably make it for you.&lt;/p&gt;

&lt;p&gt;Maybe one day a model does that mapping too, if it gets good enough. But someone or something still has to own it, and the ownership is the durable part, not the person doing it. &lt;/p&gt;

&lt;p&gt;What monday built, by hand and in private, is the closest thing to closing that gap I have found, a real step in the right direction. What it still lacks is the mapping: its context resolves values and is regenerated from the design on every run, not a record of the decisions that a team owns and re-enters.&lt;/p&gt;

&lt;p&gt;There is a harder edge to owning that last mile. Companies want to move fast, and something that looks 80 percent done looks 80 percent done to a boss, who cannot see that most of the real work is the part that never shows. So the pressure is to ship: the demo convinces, and the person who says "not yet" becomes the visible bottleneck. Organizations are being told to treat AI as a multiplier, and they are learning to count the output: components shipped, pull requests merged. Against that scoreboard, holding the line on quality does not look like protecting the product. It looks like slowing it down. &lt;strong&gt;Owning the work now means owning that pressure too.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Now what?
&lt;/h2&gt;

&lt;p&gt;Here is the anticlimax; the fix is boring: decoupling. Keeping the parts of a system independent so you can swap one without breaking the rest has been a foundation of good software for decades. We already know how to do this.&lt;/p&gt;

&lt;p&gt;This is not a call to go back. The roles are shifting, and they will keep shifting. AI is part of that, and the speed is real. But we are still in the hype phase, and the fear of missing out is pushing teams to collapse every boundary at once, before the industry has settled. Keep the discipline we already have while the ground is still moving. The lines will move; move them with purpose, not because a demo felt fast.&lt;/p&gt;

&lt;p&gt;Whatever stack you are on, start by recording the decisions, not just the tokens: write down the reasoning the pipeline is otherwise left to assume, so the next edit works from a record instead of inventing one. Keep the resolve step, the token layer, and the codegen modular and portable. The decisions are the part to hold onto, precisely because they are the part the model is worst at.&lt;/p&gt;

&lt;p&gt;Right now everyone is rebuilding that layer in private. Custom pipelines will always exist, and that is fine. I just wish we had a good open-source option too, decoupled enough that no one is locked to a single vendor, LLM, or tool. It is modular, so no one needs to build the whole thing. Working on a piece? A resolve step, a token layer, &lt;a href="https://github.com/css-bookends/css-bookends" rel="noopener noreferrer"&gt;typed CSS inputs&lt;/a&gt;, a codegen, a way to record the decisions? Tell me about it in the comments. A decoupled system comes together one part at a time. I would like to build it with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;A few of the people and teams whose work informed this piece, or who are circling the same problem, all worth following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://sneakpeek.design" rel="noopener noreferrer"&gt;Sneak Peek&lt;/a&gt; by Jayneil (&lt;a href="https://x.com/jayneildalal" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/jayneil/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;), the interview series where designers screen-share their actual AI workflows on camera. The monday, Shopify, and Ramp walkthroughs in this piece come from there, which is why I could point at specific numbers and on-camera moments instead of vibes. Rare, generous access to how these teams actually work; go subscribe.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.thedesignsystem.guide/" rel="noopener noreferrer"&gt;Romina Kavcic&lt;/a&gt;, The Design System Guide, on agentic design systems and the 158-system study.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/akollu72/why-ai-keeps-generating-the-wrong-design-tokens-and-how-i-fixed-it-with-figmas-api-17o4"&gt;Amrutha Kollu&lt;/a&gt;, on resolving tokens deterministically before the model ever sees them.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://christinevallaure.substack.com/p/agentic-ai-design-systems-and-figma" rel="noopener noreferrer"&gt;Christine Vallaure&lt;/a&gt;, on designing Figma files a machine can actually read.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://bradfrost.com/blog/post/agentic-design-systems-in-2026/" rel="noopener noreferrer"&gt;Brad Frost&lt;/a&gt;, on constraining generation to the design system.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://engineering.monday.com/how-we-use-ai-to-turn-figma-designs-into-production-code/" rel="noopener noreferrer"&gt;monday.com Engineering&lt;/a&gt;, the case study at the centre of this piece.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://samiamdesigns.substack.com/p/design-tokens-arent-enough-architecture" rel="noopener noreferrer"&gt;Sam I am Designs&lt;/a&gt;, on Architecture Decision Records for design systems: tokens capture what a decision is, not why it was made.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/@aliafsah1988/your-ai-coding-agent-is-only-as-good-as-your-design-system-6055e4667fa9" rel="noopener noreferrer"&gt;Ali Afsah-Noudeh&lt;/a&gt;, on giving an AI agent a typed, validated token contract to build against.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/southleft/figma-console-mcp" rel="noopener noreferrer"&gt;Southleft&lt;/a&gt;, whose open-source Figma Console MCP keeps token identity stable across renames, preserving Figma variable IDs in the DTCG &lt;code&gt;$extensions&lt;/code&gt; field.&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;monday.com Engineering, "&lt;a href="https://engineering.monday.com/how-we-use-ai-to-turn-figma-designs-into-production-code/" rel="noopener noreferrer"&gt;How We Use AI to Turn Figma Designs into Production Code.&lt;/a&gt;"&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;UX Tools 2024 Design Tools Survey, interface-design segment, where Figma leads at 82.3%, roughly 46:1 over Sketch. &lt;a href="https://uxtools.co/survey" rel="noopener noreferrer"&gt;uxtools.co/survey&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Figma Q1 FY2026 earnings call: roughly 60% of customers spending over $100k a year used Figma Make weekly, up from over 50% the prior quarter.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;The Design Tokens Community Group is a W3C community group; its format module reached first-stable (v2025.10) on 28 October 2025, with 20+ editor organizations and two dozen-plus participating companies including Adobe, Google, Microsoft, Meta, Amazon, Shopify, Salesforce, and Figma. &lt;a href="https://w3.org/community/design-tokens" rel="noopener noreferrer"&gt;w3.org/community/design-tokens&lt;/a&gt; and &lt;a href="https://designtokens.org" rel="noopener noreferrer"&gt;designtokens.org&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;Style Dictionary v4 ships first-class DTCG support. &lt;a href="https://styledictionary.com/info/dtcg" rel="noopener noreferrer"&gt;styledictionary.com/info/dtcg&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;Terrazzo is a DTCG-native design-token toolchain: its CLI is "for managing design tokens using the Design Tokens Community Group (DTCG) standard and generating code for any platform via plugins" (&lt;code&gt;@terrazzo/cli&lt;/code&gt;). &lt;a href="https://terrazzo.app" rel="noopener noreferrer"&gt;terrazzo.app&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn7"&gt;
&lt;p&gt;Google's DESIGN.md, a spec for describing a design system to a coding agent. &lt;a href="https://github.com/google-labs-code/design.md" rel="noopener noreferrer"&gt;github.com/google-labs-code/design.md&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn8"&gt;
&lt;p&gt;Tokens Studio for Figma (300k+ users) is a community plugin for managing design tokens; it supports the W3C Design Tokens Community Group (DTCG) format. &lt;a href="https://www.figma.com/community/plugin/843461159747178978/tokens-studio-for-figma" rel="noopener noreferrer"&gt;Figma Community plugin&lt;/a&gt;; DTCG support documented at &lt;a href="https://docs.tokens.studio/manage-settings/token-format" rel="noopener noreferrer"&gt;docs.tokens.studio&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn9"&gt;
&lt;p&gt;AI models routinely apply Tailwind v3 conventions to v4 projects; Tailwind documents the breaking changes in its upgrade guide (&lt;a href="https://tailwindcss.com/docs/upgrade-guide" rel="noopener noreferrer"&gt;tailwindcss.com/docs/upgrade-guide&lt;/a&gt;). Reported example: Prathit, "AI Models Still Can't Configure Tailwind Correctly."&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn10"&gt;
&lt;p&gt;&lt;code&gt;fit-parent&lt;/code&gt; is not a real CSS value; the valid keyword is &lt;code&gt;fit-content&lt;/code&gt; (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/width" rel="noopener noreferrer"&gt;developer.mozilla.org/en-US/docs/Web/CSS/width&lt;/a&gt;). The hallucination is documented in Shahid Pattani, "Design-to-Code AI Is Not Magic."&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn11"&gt;
&lt;p&gt;Figma's MCP server setup guide: "Link components to your codebase via Code Connect. This is the best way to get consistent component reuse in code. Without it, the model is guessing." &lt;a href="https://github.com/figma/mcp-server-guide" rel="noopener noreferrer"&gt;github.com/figma/mcp-server-guide&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn12"&gt;
&lt;p&gt;Figma announced native DTCG variable export at Schema 2025 and it is rolling out gradually: right-click a variable collection and Export to JSON in DTCG-aligned form. Primitive tokens (colour, dimension) export cleanly; the composite types and the &lt;code&gt;description&lt;/code&gt; field still trail, though a composite that comes out as its constituent primitives is trivial to reassemble (&lt;a href="https://forum.figma.com/suggest-a-feature-11/dtcg-composite-token-export-support-51314" rel="noopener noreferrer"&gt;open community request&lt;/a&gt;). Either way, this is the token-export path, separate from what the Figma MCP hands a model when it reads a component to generate code. I dug into the underlying variables data model in &lt;a href="https://dev.to/slafleche/even-figma-isnt-sure-about-its-own-design-tokens-4mko"&gt;Even Figma isn't sure about its own design tokens&lt;/a&gt;. Rollout status as of July 2026.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn13"&gt;
&lt;p&gt;Amrutha Kollu, "&lt;a href="https://dev.to/akollu72"&gt;Why AI Keeps Generating the Wrong Design Tokens, and How I Fixed It with Figma's API.&lt;/a&gt;"&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn14"&gt;
&lt;p&gt;Yi Gui, Jiawan Zhang, Yina Wang, Tianran Ma, Yao Wan, Shilin He, Dongping Chen, Zhou Zhao, Wenbin Jiang, Xuanhua Shi, Hai Jin, and Philip S. Yu, "Figma2Code: Automating Multimodal Design to Code in the Wild" (arXiv 2604.13648, ICLR 2026). Benchmarking ten leading models on real Figma files, they find proprietary models achieve superior visual fidelity but stay limited in layout responsiveness and code maintainability, mapping primitive visual attributes straight from the Figma metadata. &lt;a href="https://arxiv.org/abs/2604.13648" rel="noopener noreferrer"&gt;arxiv.org/abs/2604.13648&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn15"&gt;
&lt;p&gt;Figma Make produces standalone code by default; aligning it to a design system requires authoring "Make kits." &lt;a href="https://figma.com/blog/introducing-make-kits-and-make-attachments" rel="noopener noreferrer"&gt;figma.com/blog/introducing-make-kits-and-make-attachments&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn16"&gt;
&lt;p&gt;Same walkthrough: the spacing and token values are surfaced inside the design for the model to read, a spec written for AI rather than a person, "instead of writing for a person we write for AI... all the spacings are visible. It helps the AI to see the spacing in cursor" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=16s" rel="noopener noreferrer"&gt;0:16&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn17"&gt;
&lt;p&gt;Same walkthrough: the flow produces a full Storybook entry, not just code, "it's available already in storybook and all the documentations are generated all the props are generated" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=691s" rel="noopener noreferrer"&gt;11:31&lt;/a&gt;); "at the end of the flow it's creating all the stories all the tests for the developers" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=725s" rel="noopener noreferrer"&gt;12:05&lt;/a&gt;). The engineering blog separately notes the pipeline "resolved valid variants and props" for system components (&lt;a href="https://engineering.monday.com" rel="noopener noreferrer"&gt;engineering.monday.com&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn18"&gt;
&lt;p&gt;Elad Mizrahi, monday.com's design-systems lead, Sneak Peek walkthrough: 70 to 90 percent generated, then "our developers take it from there" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=2581s" rel="noopener noreferrer"&gt;43:01&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn19"&gt;
&lt;p&gt;Same walkthrough: the model does better on new components than edits to old ones (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=1954s" rel="noopener noreferrer"&gt;32:34&lt;/a&gt;). The reason is my own hypothesis, not his.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn20"&gt;
&lt;p&gt;Same walkthrough, the live colour-flip stumble: "we need to do some overrides to make it work" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=1924s" rel="noopener noreferrer"&gt;32:04&lt;/a&gt;); "when you show it to somebody it's not always working" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=1936s" rel="noopener noreferrer"&gt;32:16&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn21"&gt;
&lt;p&gt;Same walkthrough: changes "still need to be approved by a person" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=2459s" rel="noopener noreferrer"&gt;40:59&lt;/a&gt;); "we don't want to just rely blindly on AI" (&lt;a href="https://youtube.com/watch?v=7jeocy9IN1M&amp;amp;t=2643s" rel="noopener noreferrer"&gt;44:03&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn22"&gt;
&lt;p&gt;Shopify product designer Kazden Cattapan, Sneak Peek: a code-connected clone of the admin; generated code gets an engineer to about 80 percent (&lt;a href="https://youtube.com/watch?v=aVDAhJ3PtLg&amp;amp;t=2611s" rel="noopener noreferrer"&gt;43:31&lt;/a&gt;), with the internationalization of strings, polish, and "slop code" (&lt;a href="https://youtube.com/watch?v=aVDAhJ3PtLg&amp;amp;t=2595s" rel="noopener noreferrer"&gt;43:15&lt;/a&gt;) left over.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn23"&gt;
&lt;p&gt;Ramp product designer George Visan, Sneak Peek: asked what share of the design he targets in Magic Patterns, "0 to 70ish", then "I am going back to Figma" for the real handoff (&lt;a href="https://youtube.com/watch?v=mH5qIPx47jw&amp;amp;t=1086s" rel="noopener noreferrer"&gt;18:06&lt;/a&gt;); the prototypes are "not functional" (&lt;a href="https://youtube.com/watch?v=mH5qIPx47jw&amp;amp;t=2214s" rel="noopener noreferrer"&gt;36:54&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn24"&gt;
&lt;p&gt;These are each team's own numbers, and self-reported bests round up, so read them as a ceiling, not a measurement.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn25"&gt;
&lt;p&gt;Abu Doush and Kassem had four leading models (ChatGPT 4o, Copilot Pro, Claude 3.7 Sonnet, Grok 3) generate eleven standard WCAG components and found they "frequently fail to meet full accessibility compliance without further prompting and human interventions," with Claude 3.7 and ChatGPT 4o strongest (&lt;em&gt;Universal Access in the Information Society&lt;/em&gt;, 2025, &lt;a href="https://link.springer.com/article/10.1007/s10209-025-01250-2" rel="noopener noreferrer"&gt;link.springer.com&lt;/a&gt;). A separate benchmark, A11YN, put a smaller base model at a 0.38 inaccessibility rate on generated web UI (&lt;a href="https://arxiv.org/abs/2510.13914" rel="noopener noreferrer"&gt;arxiv.org/abs/2510.13914&lt;/a&gt;). Both track the web the models learned from: WebAIM's 2025 scan of the top million home pages found WCAG 2 failures on 94.8 percent of them (&lt;a href="https://webaim.org/projects/million/2025" rel="noopener noreferrer"&gt;webaim.org/projects/million/2025&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn26"&gt;
&lt;p&gt;A WCAG 2.2 AA audit of shadcn/ui found 34 of 48 components pass out of the box, but the documented Combobox example ships without &lt;code&gt;aria-haspopup&lt;/code&gt;, &lt;code&gt;aria-expanded&lt;/code&gt;, or &lt;code&gt;aria-controls&lt;/code&gt; (Gaurav Guha, "shadcn/ui Accessibility Audit," TheFrontKit, April 2026, &lt;a href="https://thefrontkit.com/blogs/shadcn-ui-accessibility-audit-2026" rel="noopener noreferrer"&gt;thefrontkit.com&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn27"&gt;
&lt;p&gt;Generate-from-scratch tools named here: v0 (&lt;a href="https://v0.app" rel="noopener noreferrer"&gt;v0.app&lt;/a&gt;), Lovable (&lt;a href="https://lovable.dev" rel="noopener noreferrer"&gt;lovable.dev&lt;/a&gt;), Bolt (&lt;a href="https://bolt.new" rel="noopener noreferrer"&gt;bolt.new&lt;/a&gt;). Figma Make is covered above.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn28"&gt;
&lt;p&gt;Vendor codegen tools named here: Builder.io (&lt;a href="https://builder.io" rel="noopener noreferrer"&gt;builder.io&lt;/a&gt;), Anima (&lt;a href="https://animaapp.com" rel="noopener noreferrer"&gt;animaapp.com&lt;/a&gt;), Figma's Dev Mode (&lt;a href="https://figma.com/dev-mode" rel="noopener noreferrer"&gt;figma.com/dev-mode&lt;/a&gt;). Code Connect is covered in the MCP note above.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn29"&gt;
&lt;p&gt;Canvas-as-code tools named here: Subframe (&lt;a href="https://subframe.com" rel="noopener noreferrer"&gt;subframe.com&lt;/a&gt;), Paper (&lt;a href="https://paper.design" rel="noopener noreferrer"&gt;paper.design&lt;/a&gt;).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn30"&gt;
&lt;p&gt;Christine Vallaure, on designing Figma files a machine can actually read. &lt;a href="https://christinevallaure.substack.com/p/agentic-ai-design-systems-and-figma" rel="noopener noreferrer"&gt;christinevallaure.substack.com/p/agentic-ai-design-systems-and-figma&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn31"&gt;
&lt;p&gt;Brad Frost, on constraining AI generation to the design system. &lt;a href="https://bradfrost.com/blog/post/agentic-design-systems-in-2026/" rel="noopener noreferrer"&gt;bradfrost.com/blog/post/agentic-design-systems-in-2026/&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn32"&gt;
&lt;p&gt;Romina Kavcic, on self-healing design systems: "when a human expert fails, they come back with a reason... with agents, 25 failures land on your desk, and none of them come with insight. No ownership, no explanation, no learning." Also "AI cannot fix taste."&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn33"&gt;
&lt;p&gt;Romina Kavcic, "&lt;a href="https://learn.thedesignsystem.guide/p/i-analyzed-158-design-systems-heres" rel="noopener noreferrer"&gt;What I Learned from Analyzing 158 Design Systems.&lt;/a&gt;" Figures are self-reported. Three systems scored a perfect 7 (documenting all seven layers): Polaris, Paste, and eBay Playbook.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn34"&gt;
&lt;p&gt;Shopify's Polaris design system. &lt;a href="https://polaris.shopify.com" rel="noopener noreferrer"&gt;polaris.shopify.com&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn35"&gt;
&lt;p&gt;Twilio's Paste, an open-source design system. &lt;a href="https://paste.twilio.design" rel="noopener noreferrer"&gt;paste.twilio.design&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn36"&gt;
&lt;p&gt;eBay's Playbook design system. &lt;a href="https://playbook.ebay.com" rel="noopener noreferrer"&gt;playbook.ebay.com&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn37"&gt;
&lt;p&gt;On AI coding tools priced below what it costs to serve them: Ed Zitron, "&lt;a href="https://wheresyoured.at/ais-economics-dont-make-sense" rel="noopener noreferrer"&gt;AI's Economics Don't Make Sense&lt;/a&gt;", for the framing; Arize, "&lt;a href="https://arize.com/blog/ai-model-subsidies-ending-llm-inference-costs" rel="noopener noreferrer"&gt;AI Model Subsidies Are Ending&lt;/a&gt;", on the subsidy mechanism. Framing, not hard numbers; the hard figures are the xAI-versus-revenue gap below.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn38"&gt;
&lt;p&gt;Menlo Ventures: in surveys of technical leaders, Claude led code generation at roughly 42% share versus OpenAI's 21% by mid-2025 ("&lt;a href="https://menlovc.com/perspective/2025-mid-year-llm-market-update" rel="noopener noreferrer"&gt;2025 Mid-Year LLM Market Update&lt;/a&gt;"), rising to about 54% by late 2025 ("&lt;a href="https://menlovc.com/perspective/2025-the-state-of-generative-ai-in-the-enterprise" rel="noopener noreferrer"&gt;2025: The State of Generative AI in the Enterprise&lt;/a&gt;"), driven by Claude Code.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn39"&gt;
&lt;p&gt;Per SpaceX's SEC S-1 filing, Anthropic committed to pay xAI about $1.25 billion a month for compute through 2029, after a two-month discounted ramp (reported by TechCrunch, 20 May 2026).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn40"&gt;
&lt;p&gt;Anthropic CFO Krishna Rao, sworn declaration (9 March 2026) in Anthropic's suit against the U.S. Department of Defense (now the Department of War; N.D. Cal. No. 3:26-cv-01996), stated the company's revenue to date exceeds $5 billion. &lt;a href="https://www.courtlistener.com/docket/72379655/anthropic-pbc-v-us-department-of-war/" rel="noopener noreferrer"&gt;Docket on CourtListener&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn41"&gt;
&lt;p&gt;The precedent is the late-1990s telecom fibre-optic overbuild: carriers spent hundreds of billions laying capacity ahead of demand and were left with a glut when adoption arrived slower than the buildout. Paul Kedrosky draws the same parallel to today's AI data-centre spending in "&lt;a href="https://paulkedrosky.com/weekend-reading-plus-spvs-meta-and-fiber-buildout-2-0" rel="noopener noreferrer"&gt;SPVs, Credit, and AI Datacenters&lt;/a&gt;" (30 June 2025): "AI data centers, like telecom fiber before them, are highly capital-intensive, and the long-term returns remain speculative."&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn42"&gt;
&lt;p&gt;GitHub moved Copilot to usage-based billing effective 1 June 2026. &lt;a href="https://github.blog" rel="noopener noreferrer"&gt;github.blog&lt;/a&gt;.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn43"&gt;
&lt;p&gt;Stock figures as of early July 2026. Figma peaked near $142 after its 2025 IPO and trades in the low $20s; Adobe is down more than a third year-to-date while still posting record revenue. See &lt;a href="https://stockanalysis.com" rel="noopener noreferrer"&gt;stockanalysis.com&lt;/a&gt; for current prices.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn44"&gt;
&lt;p&gt;The dominant design tool has turned over twice in about fifteen years, Photoshop to Sketch to Figma; Sketch peaked near 70 percent around 2017 and fell below 2 percent by 2024.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn45"&gt;
&lt;p&gt;"Design Engineer" is not my term. Its use for the design-and-engineering intersection traces at least to Natalya Shelburne's 2019 talk "CSS at the intersection"; David Luhr collects the lineage in "&lt;a href="https://luhr.co/blog/2024/02/26/the-origins-of-design-engineering/" rel="noopener noreferrer"&gt;The Origins of Design Engineering&lt;/a&gt;" (Brad Frost's related "front-of-the-front-end", 2021, is a distinct term).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>design</category>
      <category>frontend</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Even Figma isn't sure about its own design tokens</title>
      <dc:creator>Stéphane LaFlèche</dc:creator>
      <pubDate>Thu, 25 Jun 2026 21:32:32 +0000</pubDate>
      <link>https://dev.to/slafleche/even-figma-isnt-sure-about-its-own-design-tokens-4mko</link>
      <guid>https://dev.to/slafleche/even-figma-isnt-sure-about-its-own-design-tokens-4mko</guid>
      <description>&lt;p&gt;&lt;em&gt;The whole industry seems to have agreed on a standard for design tokens. The shift it sets up is still on its way.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Design tokens are not new. The term was coined in 2014, at Salesforce, by Jina Anne and Jon Levine.&lt;sup id="fnref1"&gt;1&lt;/sup&gt; By 2017, Amazon had open-sourced Style Dictionary and the idea had spread well past Salesforce. We have been shipping design tokens for over a decade.&lt;/p&gt;

&lt;p&gt;What we never did, in all that time, was agree on a format. Every tool and every team rolled its own shape. There was never one neutral way to write a token down, its value and its meaning, so that any other tool could read it.&lt;/p&gt;

&lt;p&gt;Have you heard of DTCG? I hadn't, until recently. It is the Design Tokens Community Group, a W3C effort to finally settle that format.&lt;sup id="fnref2"&gt;2&lt;/sup&gt; The repo is quiet, but that is because the spec reached its first stable version in late 2025, not because anyone walked away. The quiet is a thing being finished, not abandoned.&lt;/p&gt;

&lt;p&gt;The list of who is backing it is not quiet at all.&lt;/p&gt;

&lt;p&gt;Adobe. Google. Microsoft. Meta. Amazon. Shopify. Salesforce. Sony. Pinterest. The New York Times. Disney. Framer. Penpot. Figma. Plus a dozen more.&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;That is not a side project. That is most of the industry quietly agreeing on something. One of those names, &lt;strong&gt;Figma&lt;/strong&gt;, is the reason for the title of this piece. We will get to it, because the irony is the whole point.&lt;/p&gt;

&lt;p&gt;Here is my bet, and I will say up front that it is a bet. I think a storm is coming for design tooling. You do not have to believe me about the storm, because the bet does not depend on it. If you are wiring your tokens straight into one vendor's format, you are exposed. Anchor them to the open standard instead and you are not. The downside is lopsided. If I am wrong, you have lost almost nothing. If I am even half right, everyone hard-coded to a single tool is facing a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  The format is young and already fragmenting. That is the point.
&lt;/h2&gt;

&lt;p&gt;The obvious objection is that the standard is too new to bet on, and already splintering. It is splintering. Google's DESIGN.md takes DTCG as inspiration and then forks the schema into its own shape, prose rationale wrapped around DTCG-style tokens.&lt;sup id="fnref3"&gt;3&lt;/sup&gt; Other tools keep their own dialects. This is normal. It is the browser wars again, the old web pattern where everyone agrees on a direction and argues about the details for a few years.&lt;/p&gt;

&lt;p&gt;What matters is &lt;em&gt;where&lt;/em&gt; they argue. The forks agree on the base: the primitive tokens, colours, spacing, radii, and the reference syntax. They diverge at the edge, on composite tokens like typography, shadows, and gradients, which are the youngest part of the spec and where tool support still trails.&lt;sup id="fnref4"&gt;4&lt;/sup&gt; So the disagreement sits in one known place, and it is closing rather than spreading. Style Dictionary, Tokens Studio, and Terrazzo are all converging on the same base, and there is already a joint Style Dictionary and Terrazzo proposal for a shared format.&lt;sup id="fnref5"&gt;5&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;That is the case for anchoring to the standard rather than to any one flavour. DTCG is vendor-neutral and governed in the open under the W3C; a company's fork is governed by that company. The forks are not replacing the standard; they ride on it. The closer analyses call DESIGN.md a wrapper around DTCG tokens, not a competitor.&lt;sup id="fnref3"&gt;3&lt;/sup&gt; You build on the settled base and adapt to whatever flavour wins at the edge.&lt;/p&gt;

&lt;p&gt;One honest caveat. That base is rock-solid for primitive tokens today, and more aspirational for composites. If your tokens are colours and spacing, you can lean on the standard now. If they are type ramps and elevation shadows, you are betting slightly ahead of the tooling. Worth knowing before you wire it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which brings us to Figma
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Figma is on that buy-in list.&lt;/strong&gt; Figma also cannot tell you what its own variables mean.&lt;/p&gt;

&lt;p&gt;Open a Figma variable and you get a bare number. A &lt;code&gt;FLOAT&lt;/code&gt; of &lt;code&gt;10&lt;/code&gt;. Is that &lt;code&gt;10px&lt;/code&gt;, a z-index of &lt;code&gt;10&lt;/code&gt;, or &lt;code&gt;10ms&lt;/code&gt;? The file does not say. You guess from context. So does any tool reading it. So does any LLM you point at it. Getting those values out in clean DTCG form still means reaching for a community plugin today; Figma's native export is rolling out, but it does not cover the composite tokens yet.&lt;sup id="fnref6"&gt;6&lt;/sup&gt; The most valuable design tool in the world has not settled its own token format. That is the irony the title promised.&lt;/p&gt;

&lt;p&gt;It gets sharper. Figma went public in July 2025 as one of the year's hottest IPOs and popped to around $142. A year later it trades near $17, more than 85% below that peak.&lt;sup id="fnref7"&gt;7&lt;/sup&gt; The cause is contested. Frothy valuation, widening losses, AI pressure, take your pick; I will not pretend to know it. The point is narrower. A year ago, betting your token pipeline on Figma's permanence looked safe. It looks different now.&lt;/p&gt;

&lt;p&gt;Here is what makes the bet easy, though: you do not need Figma to fall. Figma is on the DTCG list, and it is already rolling out native DTCG export.&lt;sup id="fnref6"&gt;6&lt;/sup&gt; The rollout is incremental, but the direction is set. Anchor to the standard and you win whether Figma thrives or fades. That is the whole shape of the bet.&lt;/p&gt;

&lt;h2&gt;
  
  
  It is not just Figma
&lt;/h2&gt;

&lt;p&gt;If Figma feels like a special case, look at Adobe. Adobe is the giant that tried to buy Figma for twenty billion dollars, got blocked by European and UK regulators, and paid a record one-billion-dollar fee to walk away.&lt;sup id="fnref8"&gt;8&lt;/sup&gt; Adobe is also on the DTCG list. In 2026, Adobe is making more money than ever and watching its stock fall about 30% anyway.&lt;sup id="fnref9"&gt;9&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;That is the cleaner version of the whole argument. Revenue is up and the AI products are growing, yet the market is marking the company down by a third on a single fear: nobody knows what AI will do to creative software. The fundamentals are fine. The uncertainty is what is being priced. When the most entrenched tool company in the industry gets repriced on "we cannot see what is coming," that uncertainty is not a Figma problem. It is the weather.&lt;/p&gt;

&lt;h2&gt;
  
  
  The standard does not make the hard part easy
&lt;/h2&gt;

&lt;p&gt;None of this makes anchoring to DTCG free. Getting clean tokens out of a messy tool is the &lt;code&gt;FLOAT 10&lt;/code&gt; problem again: something has to decide whether that 10 is a length or a duration, and the standard will not decide it for you. There is no free lunch, which is the same point I made &lt;a href="https://dev.to/slafleche/were-making-the-dreamweaver-mistake-again-on-purpose-this-time-ema"&gt;last time&lt;/a&gt;: the tooling gets you a real step closer; the judgment stays a human's to own. What the standard gives you is a stable target to aim that judgment at, one format instead of a converter per tool.&lt;/p&gt;

&lt;p&gt;You might object that the glue is throwaway: with Figma's native export still incomplete, you build a Figma-to-DTCG adapter now and bin it the day Figma ships full support. True, but that adapter is the only disposable piece. Everything downstream stays aimed at the standard, so when the adapter goes, nothing else moves. Couple to the tool instead and the same change rewrites the whole chain. The loose part today is exactly that Figma-to-token step, so make it the deliberately disposable one. When native support lands, the rest of your app is already built on the standard, and you just start pulling clean tokens straight from Figma.&lt;/p&gt;

&lt;h2&gt;
  
  
  What anchoring actually looks like
&lt;/h2&gt;

&lt;p&gt;Put DTCG in the middle, and build that layer to expect change. The format itself will keep shifting, and depending on the company you work for, your house standard might be a fork of it rather than DTCG proper. A middle layer built to absorb those variants stays resilient today, and it leaves you positioned to adapt the moment the industry consolidates on DTCG. Keep your source of truth there and generate everything downstream from it: your Figma variables, your CSS custom properties, your iOS and Android tokens. The design tool stops owning your tokens and becomes one more consumer of them. That same DTCG source is the input to the typed foundation I argued for in &lt;a href="https://dev.to/slafleche/the-case-for-compiled-typed-css-blame-ai-8m8"&gt;an earlier piece&lt;/a&gt;: the standard upstream, a typed layer downstream.&lt;/p&gt;

&lt;p&gt;Better tokens are not the whole answer. They are one piece of that same larger problem: using AI to turn designs into systems, and who owns the decisions in the middle. A shared format settles where your tokens live. The system they feed is still yours to design.&lt;/p&gt;

&lt;p&gt;The Design Tokens Community Group is doing quiet, unglamorous, genuinely important work, and most developers have never heard of it. If you build tooling in this space, it is worth your attention, and worth building toward. I would like to hear from anyone already betting this way, and from anyone who thinks the bet is wrong. That is the conversation I am trying to start.&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;"Design token" was coined at Salesforce by Jina Anne (with Jon Levine) in 2014, on the Lightning Design System; broad adoption followed around 2017 with Amazon's Style Dictionary. See the design-token histories ("The incomplete history of design tokens", Design Systems Collective; Smashing Magazine's interview with Jina Anne).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;The Design Tokens Community Group is a W3C community group; its Design Tokens Format Module reached first-stable (v2025.10) in October 2025, with 20+ editor organizations and 24+ participating companies (Adobe, Google, Microsoft, Meta, Amazon, Shopify, Salesforce, Figma, Framer, Penpot, and more). See w3.org/community/design-tokens and designtokens.org. Verify the participant list and date at publish.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Google open-sourced DESIGN.md in April 2026; it bases its tokens on DTCG but diverges ("inspired by, not strict compliance"). Independent analysis frames DESIGN.md as a wrapper that contains DTCG tokens plus prose rationale, complementing the standard rather than replacing it.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;DTCG 2025.10 defines composite token types (typography, gradients, shadows), but real-world tool support for composites lags the primitives, and composite-token export is an active area of discussion. The bet is strongest for primitive tokens today and more aspirational for composites. Verify which composite types are normative-stable at publish (Design Tokens Format Module 2025.10; Figma forum "DTCG Composite Token Export Support").&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;Style Dictionary v4 has first-class DTCG support; Tokens Studio and Terrazzo are reference implementations, and there is a joint Style Dictionary and Terrazzo RFC on a shared token-listing format (styledictionary.com/info/dtcg; GitHub style-dictionary discussion #1479).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;Figma announced native DTCG variable export at Schema 2025. Confirmed rolling out as of June 2026: you can right-click a variable collection and Export to JSON in DTCG-aligned form, then run it through Style Dictionary. The rollout is still progressive and spec compliance is incomplete (the &lt;code&gt;description&lt;/code&gt; field is dropped, and composite tokens still trail), so community plugins (Token Press and others) provide the fuller export today. Re-verify exact status at publish.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn7"&gt;
&lt;p&gt;Figma (NYSE: FIG) IPO'd in July 2025 at $33, closed its first day near $115 and peaked around $142 (closing high ~$122 on 1 Aug 2025). By late June 2026 it traded near $17, more than 85% below that peak. Figures move daily; re-verify at publish (stockanalysis.com/stocks/fig; macrotrends.net/stocks/charts/FIG).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn8"&gt;
&lt;p&gt;Adobe agreed to acquire Figma for ~$20B in September 2022; the deal was terminated in December 2023 after European Commission and UK CMA antitrust pushback, with Adobe paying a $1B reverse termination fee (CNBC; Axios; Adobe SEC 8-K).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn9"&gt;
&lt;p&gt;Adobe (NASDAQ: ADBE) was down roughly 30% in 2026 (sources vary, about 23% to 37% by date and baseline, and ~46% from its all-time peak), at a multi-year low despite record revenue and a growing Firefly business, on fears that generative AI commoditizes creative software. One analysis called it "narrative risk being priced as terminal risk, which the fundamentals do not yet confirm." Verify the current figure at publish.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>figma</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>We're making the Dreamweaver mistake again, on purpose this time</title>
      <dc:creator>Stéphane LaFlèche</dc:creator>
      <pubDate>Wed, 24 Jun 2026 20:37:51 +0000</pubDate>
      <link>https://dev.to/slafleche/were-making-the-dreamweaver-mistake-again-on-purpose-this-time-ema</link>
      <guid>https://dev.to/slafleche/were-making-the-dreamweaver-mistake-again-on-purpose-this-time-ema</guid>
      <description>&lt;p&gt;&lt;em&gt;We spent twenty years getting designers out of the code. AI just put the design back in charge of it.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pendulum swings back
&lt;/h2&gt;

&lt;p&gt;Designers used to be in the code. In the Dreamweaver and WYSIWYG era, you laid out a page in a visual tool and it wrote the markup for you. The industry then spent the better part of twenty years undoing that. We drew a line: designers design, developers build, and a human translates between the two.&lt;/p&gt;

&lt;p&gt;AI is swinging the pendulum back. Not by putting designers back in the code, but by handing their design to a machine that writes it. Point the model at the file, get components out. The design drives the code again.&lt;/p&gt;

&lt;p&gt;Here is the part that should give you pause. This is not a clean return to the Dreamweaver days. Back then, however messy the generated markup was, a person still sat in the translation and owned it. Now the design goes straight to code with no one in the driver's seat. That seat is where quality used to get enforced.&lt;/p&gt;

&lt;p&gt;Two quick things before I go further, because this argument gets misread in two predictable ways.&lt;/p&gt;

&lt;p&gt;First, this is not a knock on designers. Designers do &lt;strong&gt;great work&lt;/strong&gt;. The point is a distinction. What makes a great design file is not what makes a great design system, or what makes good code. A file is judged on the design. A system is judged on reuse, on states, on durability. The AI workflow blurs that line, and the blur is the whole subject.&lt;/p&gt;

&lt;p&gt;Second, if you are building a simple static site, pointing AI at the design is genuinely fine. The snapshot is the thing. Ship it. The problem I am describing only bites when the design is meant to become a reusable system: a design system, a custom CMS, a dynamic UI. Keep that scope in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dream is real
&lt;/h2&gt;

&lt;p&gt;I want to be fair to the dream, because it is seductive and it is partly true. Point AI at the design, get working code, one step.&lt;/p&gt;

&lt;p&gt;AI is genuinely valuable. I use it. It has let me do things I could not have done before, and finish projects under tight deadlines in codebases I did not know well. I am not here to tell you the tool is bad.&lt;/p&gt;

&lt;p&gt;But notice where that value lands. It lands at the snapshot level. Real value is not the same thing as a foundation. That gap is the rest of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  A design is not a foundation
&lt;/h2&gt;

&lt;p&gt;Here is the concrete failure, and it is not hypothetical. Teams build entire token pipelines around the variable names a designer chose in Figma. Naming is a design decision, but auto-translation quietly promotes it to a load-bearing contract. Rename one variable in the design file and the pipeline snaps three steps downstream. The design is doing a foundation's job, and breaking, because it was never built for it.&lt;/p&gt;

&lt;p&gt;You can see it in a single pair of names. &lt;code&gt;--blue-500&lt;/code&gt; is a value; &lt;code&gt;--color-primary&lt;/code&gt; is an intent. A system should depend on the intent, and AI cannot reliably tell which one the design meant.&lt;/p&gt;

&lt;p&gt;The obvious fix is to train designers to name things the system-correct way. But that points the effort at the wrong person. I love working with designers, but the answer is not to turn them into systems engineers, negotiating every token name. Translating their vision into a durable system is my job, not theirs. That translation wants to be a pipeline: map the design tokens onto a universal standard, then watch for drift. I will come back to what that standard is.&lt;/p&gt;

&lt;p&gt;Naming is only the first failure mode. Set it aside and a deeper one remains. A design is a static snapshot. It shows one state of one screen. It does not encode reusable versus one-off, the empty, loading, and error states, what is content-driven versus fixed, or how a CMS feeds it. That systemic context lives in the developer's head and in the code. It is not in the file.&lt;/p&gt;

&lt;p&gt;The industry has noticed the input problem, and it is moving on it. Google recently open-sourced DESIGN.md, a format for handing a structured design system to a coding agent instead of a raw file, and a catalogue of them is already forming.&lt;sup id="fnref1"&gt;1&lt;/sup&gt; That is a real step, and it tells you the input was a weak link all along. Hold that thought, because where DESIGN.md stops is exactly the point.&lt;/p&gt;

&lt;p&gt;The deeper limit is not the input format. It is that the design, in any form, is the wrong source for the decisions. The model's best case is the guts of the design file, an artifact optimized for none of the things a foundation needs: not design-system structure, not coding best practices, not the developer or agent experience. Its worst case is a screenshot, pixels with no structure at all. Even a flawless extraction cannot supply the architectural decisions a human makes to accommodate a design.&lt;sup id="fnref2"&gt;2&lt;/sup&gt; The deciding stays human.&lt;/p&gt;

&lt;p&gt;So the verdict. A design is not a foundation. Auto-translating it into code silently promotes it to one, and it was never built for the role.&lt;/p&gt;

&lt;h2&gt;
  
  
  People are working on this
&lt;/h2&gt;

&lt;p&gt;This gap is real, and a lot of people are working on it right now, from the biggest players to solo builders. Google's DESIGN.md is one move. An ecosystem has formed around it almost overnight, and it is already being put to the test in production. My friend Amrutha Kollu is one of the independent builders coming at it. Her tool, Fixel, validates your code against Figma in continuous integration and catches design-system drift before it merges. When it finds drift, it posts the finding back onto the Figma canvas as a comment, so the designer sees it in the place they already work.&lt;sup id="fnref3"&gt;3&lt;/sup&gt; It is promising work on a real problem.&lt;/p&gt;

&lt;p&gt;Where all of this lands is genuinely open. A lot of smart people are coming at the same problem from different angles at once. That open question is the honest state of things, and it is a big part of why I am writing this.&lt;/p&gt;

&lt;p&gt;I want to be precise about where it sits, because the boundaries are the interesting part. Fixel is on the code side, and it does not claim to have solved the whole thing. The limit worth naming, and I mean it as architecture, not criticism: it reads directly from the design tool, so any tool-coupled approach risks going obsolete unless it targets the open standard underneath. That standard is the W3C Design Tokens format, or DTCG, the vendor-neutral spec the major tools are converging on, and it is the durable anchor here.&lt;/p&gt;

&lt;h2&gt;
  
  
  The missing middle
&lt;/h2&gt;

&lt;p&gt;You might think the newest tools already close this. They have gone well past reading a screenshot. Claude Design imports your design system straight from your codebase and checks its output against it before you see it.&lt;sup id="fnref4"&gt;4&lt;/sup&gt; Google's Stitch reads your tokens before it draws a screen. That is real, and it is the convert step getting genuinely good.&lt;/p&gt;

&lt;p&gt;But two things none of it does. It assumes the system already exists and is clean enough to import, which means someone built that foundation and still owns it. It also checks only once, at generation. The harder problem is what happens after the code merges, when the design and the system keep moving and quietly drift apart.&lt;/p&gt;

&lt;p&gt;So that is where this leaves us. Not with the design driving the code, and not with a person hand-translating every screen either. It leaves us with a middle that someone has to own.&lt;/p&gt;

&lt;p&gt;Here is the bet I would make on what the missing middle looks like. I think it starts with &lt;a href="https://dev.to/slafleche/the-case-for-compiled-typed-css-blame-ai-8m8"&gt;typed CSS inputs at build time&lt;/a&gt;: a foundation where a value carries a type and a meaning, not just a string the model can get wrong. On top of that, the AI does what it is good at. It pulls the variables out of the design and proposes how they map onto the system you already have. Then the Design Engineer does what only they can. They shape that proposal into the system they actually want, decide what each value means, and set the behaviour and the success criteria the result has to meet. Typed inputs and automated checks keep the AI's suggestions honest.&lt;/p&gt;

&lt;p&gt;Those decisions do not live in someone's head, or get re-derived on every run. They become an artifact: a committed, versioned record of how this design maps onto the system, owned by the engineer. Fixel already does a version of this. Its overrides registry commits each intentional deviation to git with a reason and a timestamp, an audit trail instead of a silent guess. This is the part DESIGN.md cannot reach. Its prose "why" is re-read and re-interpreted by the model on every run, where a committed artifact is a decision someone made and signed.&lt;/p&gt;

&lt;p&gt;Notice what did not happen there. The design never became the system on its own. Clean variables out of Figma are a real step, but they are not the finish line, because the same tokens can be implemented a hundred ways. Choosing which one is the judgment, and the judgment is the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mistake, named
&lt;/h2&gt;

&lt;p&gt;Here is the irony to leave on. AI makes designers more responsible for code quality than they were back when we actually wanted them writing it. The design becomes the code, and no one is left gatekeeping the translation.&lt;/p&gt;

&lt;p&gt;So the real mistake is not that we use AI to get there. It is that we are writing the Design Engineer out of the loop, right when that judgment most needs an owner. The role is not going away. It is changing into the person who owns this middle: the system the design feeds into, the mapping, the contract that keeps a design from quietly becoming the foundation.&lt;/p&gt;

&lt;p&gt;The durable anchor under all of it is a standard with the mapping in your hands, and that standard is where I am headed in my next article.&lt;/p&gt;

&lt;p&gt;If you are building this middle, I would genuinely like to hear how you draw the line between what the AI proposes and what stays yours to decide. That is the conversation I am trying to start.&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;DESIGN.md is a Markdown file that describes a design system to an AI coding agent in a structured way: machine-readable tokens plus human-readable prose. Google Labs open-sourced it in April 2026. See the Google Labs announcement (blog.google, "Stitch DESIGN.md") and the spec repo (github.com/google-labs-code/design.md). A community catalogue at getdesign.md (maintained by VoltAgent) already lists 75 DESIGN.md files built on the spec (as of June 2026).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;This limit shows up in practice. When Atlassian benchmarked DESIGN.md against their own design-system tooling, they reported it was more likely to re-create existing components than to import the ones already in their system. A faithful description of how a component looks does not carry the decision to reuse the component that already exists. See Atlassian, "Atlassian's DESIGN.md is here: what we learned testing portable design context in practice" (atlassian.com, June 2026).&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Amrutha Kollu's writing on this gap: &lt;a href="https://dev.to/akollu72/how-we-shipped-60-design-system-components-in-5-weeks-using-figma-as-the-single-source-of-truth-1lkc"&gt;How I shipped 60+ design system components in 5 weeks using Figma as the single source of truth&lt;/a&gt;, &lt;a href="https://dev.to/akollu72/why-ai-keeps-generating-the-wrong-design-tokens-and-how-i-fixed-it-with-figmas-api-17o4"&gt;Why AI keeps generating the wrong design tokens and how I fixed it with Figma's API&lt;/a&gt;, and &lt;a href="https://dev.to/akollu72/check-designs-validates-your-figma-what-validates-your-code-38c2"&gt;Check Designs validates your Figma. What validates your code?&lt;/a&gt;. Fixel validates code against Figma in CI to catch design-system drift.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;Claude Design, Anthropic Labs (anthropic.com/news/claude-design-anthropic-labs). A June 2026 update added importing a design system from a repository or files and checking generated output against it.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>design</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Most of the web is touch. We still don't save handedness.</title>
      <dc:creator>Stéphane LaFlèche</dc:creator>
      <pubDate>Fri, 19 Jun 2026 01:02:51 +0000</pubDate>
      <link>https://dev.to/slafleche/most-of-the-web-is-touch-we-still-dont-save-handedness-5ea0</link>
      <guid>https://dev.to/slafleche/most-of-the-web-is-touch-we-still-dont-save-handedness-5ea0</guid>
      <description>&lt;p&gt;How is there still no OS setting to save your handedness preference?&lt;/p&gt;

&lt;p&gt;We can detect a surprising amount about how someone wants to use a page. Dark mode, reduced motion, higher contrast, reduced data: the &lt;code&gt;prefers-*&lt;/code&gt; media features expose all of it. There is one obvious preference the platform never exposes: which hand you are using.&lt;/p&gt;

&lt;p&gt;On a touchscreen, your hand is the interface. It is the cursor. Yet a designer building for that screen has no way to know whether the thumb in play is on the left or the right. So I &lt;a href="https://github.com/w3c/csswg-drafts/issues/13215" rel="noopener noreferrer"&gt;opened a proposal with the CSS Working Group&lt;/a&gt; for a new media feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-handedness&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* layout tuned for a left thumb */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-handedness&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* layout tuned for a right thumb */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like the rest of the family, this is a &lt;strong&gt;declared preference&lt;/strong&gt;, not a guess about your body: the user sets it the way they set dark mode. And because it would live at the OS level, flipping it could be a one-tap control, the same quick toggle we already use for things like Bluetooth. The web already reflows an entire layout when you rotate the screen, so a left-to-right flip is a smaller version of a shift the platform has handled for years.&lt;/p&gt;

&lt;p&gt;Here is why I think it earns a place in the family.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Most of the web is touch now
&lt;/h3&gt;

&lt;p&gt;Touch is no longer the secondary surface. As of Statcounter's May 2026 figures&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, mobile sits at 50.29% of global page views and tablets add another 1.48%. Phones alone have edged past desktop. The majority of the web now happens on a screen you hold in one hand and drive with the other.&lt;/p&gt;

&lt;h3&gt;
  
  
  And about 1 in 10 of those users are left-handed
&lt;/h3&gt;

&lt;p&gt;The best estimate from the largest meta-analysis of handedness&lt;sup id="fnref2"&gt;2&lt;/sup&gt;, 200 studies and over 2.3 million people, is that roughly 10% of people are left-handed. Stack that on top of a touch-majority web and you get a real population, not an edge case: a tenth of the dominant surface, using it the mirror image of how it was likely designed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apps already solve it, one at a time
&lt;/h3&gt;

&lt;p&gt;This is not hypothetical. Creative apps already ship handedness settings by hand. Procreate has a Right-hand interface preference&lt;sup id="fnref3"&gt;3&lt;/sup&gt; that flips its sidebar, because the default sits under the left hand while you paint with the right. SketchUp for iPad has a left-handed mode. Note apps tune palm rejection around which hand is resting on the glass. The mechanic differs (occlusion on a tablet, reach on a phone), but the missing signal is the same, and any of these apps could take its default straight from the OS instead of asking again.&lt;/p&gt;

&lt;p&gt;Every one of these reinvented the same toggle, because the platform exposes no shared signal. That is the argument for standardizing one: a user should set this once and have everything honour it, not hunt for the same preference in every app. It is the same reason dark mode lives at the OS level instead of in a hundred separate settings screens.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's a UX choice, and it goes beyond placement
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Not just flipping the menu
&lt;/h3&gt;

&lt;p&gt;To be clear, this is not "put the menu on the left." Designers already place navigation on either side freely, and both are fine. Which hand is holding the device is a different thing: a deliberate decision about what sits where, and that map depends on the hand. On a phone it is reach: a primary action belongs under the resting thumb, and a destructive action is often placed out of easy reach on purpose so it is hard to hit by accident. On a tablet it is occlusion: the dominant hand and forearm rest over the screen, so a control on the wrong side ends up under the very hand that is covering it. Without a handedness signal, that intent silently inverts for left-handers: the action you tucked away becomes the easiest one to hit, and the content you meant to keep clear sits under their hand. You never know it happened.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gestures and interaction, not just layout
&lt;/h3&gt;

&lt;p&gt;It also reaches past static layout. &lt;code&gt;prefers-*&lt;/code&gt; features are readable from JavaScript through &lt;code&gt;window.matchMedia&lt;/code&gt;, so handedness would drive interaction, not only styling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftHanded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(prefers-handedness: left)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That opens up things CSS alone cannot reach: inverting a swipe or gesture direction, choosing which edge a swipe action lives on, deciding where a context menu opens so the hand does not cover it. This is an interaction signal, not a styling toggle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The objections
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "Too niche, too much work"
&lt;/h3&gt;

&lt;p&gt;The feature itself is trivial: a single value a stylesheet or a script can read. The family already includes &lt;code&gt;prefers-reduced-motion&lt;/code&gt;, which is more involved both to define and to honour, and it shipped. Dark mode is the cleaner precedent. &lt;code&gt;prefers-color-scheme&lt;/code&gt; went from nothing to shipping across every major browser by early 2020&lt;sup id="fnref4"&gt;4&lt;/sup&gt;, fast, and it is arguably a more frivolous preference than how you physically hold the device. It is low-hanging fruit: easy to implement, and a real improvement for a substantial share of users. Hard to beat that return on effort.&lt;/p&gt;

&lt;h3&gt;
  
  
  "It needs platform buy-in"
&lt;/h3&gt;

&lt;p&gt;True, and that is the point of proposing it as a standard. The signal would be an OS setting, the same origin as dark mode. Both &lt;code&gt;prefers-color-scheme&lt;/code&gt; and &lt;code&gt;prefers-reduced-motion&lt;/code&gt; needed operating systems to expose a setting, and both got it. Handedness only differs in that the toggle does not exist yet. The honest part: that is a heavier ask than a normal CSS feature, because it needs device makers, not just browsers. But the incentive is there. Handedness support is a real selling point on phones and tablets, and the stylus world already tracks it for palm rejection. The people who would benefit from shipping it are the same people who would ship it.&lt;/p&gt;

&lt;h3&gt;
  
  
  "It's a fingerprinting vector"
&lt;/h3&gt;

&lt;p&gt;This is the serious objection, and it was the first thing raised on the proposal. The answer is to scope it. Handedness is meaningless on desktop, where the pointer is decoupled from grip, so the query can carry a value only in touch contexts and add no entropy where it would be useless anyway. And because it is a declared preference that ships off by default, like the rest of the family, it is a single low-entropy bit the user controls, not something inferred behind their back. It can also be restricted to first-party contexts, so the page you are visiting can read it but embedded third-party scripts cannot. That closes the cross-site tracking path without an opt-out checkbox or a permission prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weigh in
&lt;/h2&gt;

&lt;p&gt;The proposal is live and open. If you have a use case, a concern, or a good argument against it, that is exactly what the thread is for: &lt;a href="https://github.com/w3c/csswg-drafts/issues/13215" rel="noopener noreferrer"&gt;csswg-drafts #13215&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if you think this should exist, say so there. A thumbs-up or a short comment with your own use case is the kind of signal that helps a working group tell a real need from a passing idea.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Statcounter Global Stats, Desktop vs Mobile vs Tablet Market Share Worldwide, May 2026: &lt;a href="https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet" rel="noopener noreferrer"&gt;https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet&lt;/a&gt;&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Papadatou-Pastou et al. (2020), Human handedness: A meta-analysis, Psychological Bulletin: &lt;a href="https://doi.org/10.1037/bul0000229" rel="noopener noreferrer"&gt;https://doi.org/10.1037/bul0000229&lt;/a&gt;&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Procreate Handbook, Interface (Right-hand interface preference): &lt;a href="https://help.procreate.com/procreate/handbook/interface-gestures/interface" rel="noopener noreferrer"&gt;https://help.procreate.com/procreate/handbook/interface-gestures/interface&lt;/a&gt;&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;MDN, prefers-color-scheme (Baseline since early 2020): &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme&lt;/a&gt;&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>css</category>
      <category>discuss</category>
      <category>mobile</category>
      <category>ux</category>
    </item>
    <item>
      <title>The case for compiled, typed CSS (blame AI)</title>
      <dc:creator>Stéphane LaFlèche</dc:creator>
      <pubDate>Wed, 27 May 2026 10:38:44 +0000</pubDate>
      <link>https://dev.to/slafleche/the-case-for-compiled-typed-css-blame-ai-8m8</link>
      <guid>https://dev.to/slafleche/the-case-for-compiled-typed-css-blame-ai-8m8</guid>
      <description>&lt;p&gt;We spent years getting TypeScript to where it is. It already checks your APIs, your components, your state. Your CSS values are still strings that nothing compiles. Why wait for a new tool when the one you have can do this today?&lt;/p&gt;

&lt;p&gt;A 2025 academic study &lt;sup&gt;[1]&lt;/sup&gt; found that 94% of LLM-generated compilation errors were type-check failures. GitHub's Octoverse report &lt;sup&gt;[2]&lt;/sup&gt; cited the same stat to explain TypeScript's rise to the most-used language on the platform. In typed languages, the compiler catches most of what AI gets wrong. CSS has no compiler.&lt;/p&gt;

&lt;p&gt;Two claims follow, and they're separable. First: CSS lacks a verification layer, and AI makes that gap expensive. Second: build-time typed styles are the fix I've landed on. TypeScript is already in the stack. Anything else is another dependency and another source of drift. You can accept the first claim and argue with the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI fails at CSS
&lt;/h2&gt;

&lt;p&gt;Write &lt;code&gt;var(--spacign-md)&lt;/code&gt; and nothing fails. The browser silently falls back. Write &lt;code&gt;padding: 12px&lt;/code&gt; when your design token says 16px. It renders. Ship it.&lt;/p&gt;

&lt;p&gt;AI has generated &lt;code&gt;width: fit-parent&lt;/code&gt; &lt;sup&gt;[3]&lt;/sup&gt;, a value that does not exist (the real one is &lt;code&gt;fit-content&lt;/code&gt;). It writes &lt;code&gt;padding: 12px&lt;/code&gt; when the design token is &lt;code&gt;spacing-md&lt;/code&gt; at 16px &lt;sup&gt;[4]&lt;/sup&gt;, because it doesn't check your token file, it approximates. It applies Tailwind v3 logic to v4 projects &lt;sup&gt;[5]&lt;/sup&gt;, importing deprecated packages and breaking styles. As one writer put it: "AI didn't create this problem. It scaled it." &lt;sup&gt;[4]&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Human developers hesitate when uncertain. AI does not. It generates code with the same confidence whether implementing a known pattern or hallucinating something that has never existed &lt;sup&gt;[3]&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Linters like PostCSS and Stylelint catch syntax errors, not semantic ones. They verify grammar. What's missing is something that verifies meaning. And yes, AI writes better plain CSS than CSS-in-JS: more training data. But better unchecked CSS is still unchecked.&lt;/p&gt;

&lt;h2&gt;
  
  
  "AI will just get better"
&lt;/h2&gt;

&lt;p&gt;Maybe. But we still need to ship code today.&lt;/p&gt;

&lt;p&gt;Web-Bench &lt;sup&gt;[6]&lt;/sup&gt; (ByteDance, 2025), a benchmark of real-world web development tasks, showed the then-leading model (Claude 3.7 Sonnet) at 25.1% first-pass accuracy. GitClear's 2025 analysis &lt;sup&gt;[7]&lt;/sup&gt; of 211 million changed lines (2020-2024) found copy-pasted code rose from 8.3% to 12.3% while refactoring collapsed from 25% to under 10%. The benchmark scores go up. The real-world quality metrics go the other direction.&lt;/p&gt;

&lt;p&gt;Simon Willison argued &lt;sup&gt;[8]&lt;/sup&gt; that code hallucinations are the least dangerous kind, because compilers catch them. He's right, except CSS has no compiler. His optimism has a CSS-shaped hole.&lt;/p&gt;

&lt;p&gt;"AI will get better" is a bet. A type system is a guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Tailwind stands
&lt;/h2&gt;

&lt;p&gt;Tailwind is dominant for new projects at ~12 million weekly downloads &lt;sup&gt;[9]&lt;/sup&gt;. Its LSP flags invalid classes, ESLint plugins enforce scale usage.&lt;/p&gt;

&lt;p&gt;But Tailwind v4 moved configuration from JavaScript (&lt;code&gt;tailwind.config.ts&lt;/code&gt;) to native CSS (&lt;code&gt;@theme {}&lt;/code&gt; blocks). Simpler, yes. But the default path now authors tokens directly as CSS strings, outside any type system. You can still generate &lt;code&gt;@theme&lt;/code&gt; from a typed source, that is exactly the move I'll argue for below, but nothing in v4 pushes you there. The path of least resistance lost its types. If AI writes &lt;code&gt;@theme { --color-brand: #3b82f6 }&lt;/code&gt; when the designer specified &lt;code&gt;#2563eb&lt;/code&gt;, the CSS build passes fine. Both are valid hex. The problem isn't syntax, it's that there's no contract between your styles and your TypeScript components. Meanwhile, Tailwind Labs itself is under AI pressure: revenue down 80%, three engineers laid off &lt;sup&gt;[10]&lt;/sup&gt;. The framework thrives while the company scrambles. AI is reshaping even the most popular CSS framework's ecosystem in ways nobody planned for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build-time typed styles
&lt;/h2&gt;

&lt;p&gt;Not runtime CSS-in-JS. styled-components, Emotion, runtime style injection: that's dead for good reasons &lt;sup&gt;[11]&lt;/sup&gt;, and it should stay dead.&lt;/p&gt;

&lt;p&gt;This is something different. Values live in TypeScript, get checked by the compiler, and emit static CSS. Zero runtime. The output is plain CSS. The verification happens before it reaches the browser. The AI has to satisfy the TypeScript spec to produce output at all.&lt;/p&gt;

&lt;p&gt;You can write custom validation on top: assert that a color pair meets contrast requirements, that a measurement doesn't exceed a bound. If your values already live in TypeScript, why maintain a parallel set in Sass?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why maintain two sets of values?
&lt;/h2&gt;

&lt;p&gt;TypeScript is the most-used language on GitHub &lt;sup&gt;[2]&lt;/sup&gt; as of August 2025. Your spacing scale, your breakpoints, your theme config: they're already in &lt;code&gt;.ts&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;The question isn't "should I put CSS in JavaScript?" It's "should I type the values that are already there?"&lt;/p&gt;

&lt;p&gt;If you maintain CSS variables separately from your TypeScript tokens, you have two sets of values to keep in sync. That's where drift creeps in. Define your tokens once in TS, output to CSS variables, a Tailwind theme, responsive helpers, whatever your project needs. One source, no sync problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS variables are great. They're not a contract.
&lt;/h2&gt;

&lt;p&gt;I used to dismiss CSS variables. Then I found a real use for them: responsive values from Figma design tokens that replaced a React context for window sizes. Huge simplification. I'm strict about keeping usage limited to where they genuinely earn it.&lt;/p&gt;

&lt;p&gt;But CSS variables have specific weaknesses with AI. &lt;code&gt;var(--spacign-md)&lt;/code&gt; is valid syntax that silently fails. When a variable is set at the root, overridden in a layout component, overridden again in a card, and consumed in a button several layers deep, AI has no way to reason about which level set it. &lt;code&gt;@property&lt;/code&gt; adds native type checking, but it validates at render time, not build time. The wrong value still ships. Going the other direction, reading CSS vars in JavaScript with &lt;code&gt;getComputedStyle&lt;/code&gt; is runtime string parsing. No type safety going in, no type safety coming out.&lt;/p&gt;

&lt;p&gt;And native CSS features always lag behind in browser support. When your values live in TypeScript and compile to static CSS, you control the output. Browser compatibility becomes a build concern, not an architecture concern.&lt;/p&gt;

&lt;p&gt;You can still output CSS variables from your typed tokens. That's not a tradeoff, it's the point. One typed source, visible to both CSS at runtime and TypeScript at build time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification, not authoring
&lt;/h2&gt;

&lt;p&gt;The argument is about verification, not authoring. AI made authoring effortless: it produces CSS as fast as you can ask for it. Producing correct CSS is a different problem, and nobody solved the checking part. "Design systems solve the vocabulary problem. They do not solve the verification problem." &lt;sup&gt;[4]&lt;/sup&gt; Types are the verification layer.&lt;/p&gt;

&lt;p&gt;The strongest counter is "just give AI better context." It's partially right. Sachin Patel's team &lt;sup&gt;[12]&lt;/sup&gt; aligned Figma tokens with CSS variables and got reliable output. I use context engineering myself: I've written &lt;a href="https://lafleche.dev/" rel="noopener noreferrer"&gt;Claude Code skills and Cursor rules&lt;/a&gt; to keep AI aligned with codebase standards. These approaches work.&lt;/p&gt;

&lt;p&gt;But context is a conversation. The next developer, or the next AI session without the rules loaded, can ignore it. Types are a contract. You can't compile past them. Or as a Builder.io blog post &lt;sup&gt;[13]&lt;/sup&gt; framed it: "Without types, the AI is guessing. With types, it's reading a spec."&lt;/p&gt;

&lt;p&gt;Off-scale is fine, as long as it's visible. An explicit &lt;a href="https://www.npmjs.com/package/css-calipers" rel="noopener noreferrer"&gt;&lt;code&gt;m(17)&lt;/code&gt;&lt;/a&gt; is different from a magic &lt;code&gt;p-[17px]&lt;/code&gt; buried in a Tailwind class string. And because it's structurally distinct, you can lint for it. A CI rule that flags off-scale density is trivial when escape hatches have their own syntax. When off-scale and on-scale look identical, that rule is impossible.&lt;/p&gt;

&lt;p&gt;In practice, visual regression testing, human review, checking layouts across viewports: that work exists whether you use typed styles or not. What typed styles change is what you spend your review time on. Without them, reviewers catch both mechanical errors and visual ones. With them, the mechanical layer is handled before the code reaches review. What's left is the judgment work. There's a taxonomist quality to writing good CSS: classifying values, deciding where things belong. That part stays human. Types clear the noise so you can focus on it.&lt;/p&gt;

&lt;p&gt;I've been building the typed-measurement piece of this with &lt;a href="https://www.npmjs.com/package/css-calipers" rel="noopener noreferrer"&gt;CSS-Calipers&lt;/a&gt;. That layer is solid: compile-time unit safety, immutable values, off-scale values that are explicit rather than invisible. The broader framework around it is not solved, and I'm not claiming it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use what your project needs
&lt;/h2&gt;

&lt;p&gt;This is not an all-or-nothing proposition. Nobody is asking you to rewrite your project in CSS-in-JS. Maybe you type your entire spacing scale. Maybe you type one mission-critical token that keeps breaking. Maybe you don't need any of this. You know your project best.&lt;/p&gt;

&lt;p&gt;I'm resistant to change myself. I had a visceral reaction to CSS-in-JS when I first encountered it. Had the same reaction to CSS variables. Both times, a specific use case changed my mind. Not hype. A real problem the tool solved better than the alternatives.&lt;/p&gt;

&lt;p&gt;The industry was right to leave runtime CSS-in-JS. Native CSS is more powerful than ever. Tailwind dominates for real reasons. The point isn't to replace any of that. It's that a verification layer should exist for the parts that matter, and you should know the tradeoff when you skip it.&lt;/p&gt;

&lt;p&gt;The output is still the full CSS spec. Nothing is restricted. What changes is how many guardrails you put between your values and that output. One project might need strict token enforcement across every component. Another might need a single typed measurement in a critical layout. The point is you choose the constraint level, not the framework.&lt;/p&gt;

&lt;p&gt;CSS should fail silently in the browser. That's a feature. It should fail loudly in the build. That's what's missing. I wrote about &lt;a href="https://dev.to/slafleche/we-still-dont-have-proper-css-frameworks-18dk"&gt;what a real CSS framework could look like&lt;/a&gt; if you want the longer version of that argument.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] Mündler et al., "Type-Constrained Code Generation with Language Models" (2025) - &lt;a href="https://arxiv.org/abs/2504.09246" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2504.09246&lt;/a&gt;&lt;br&gt;
[2] GitHub Octoverse 2025 - &lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/&lt;/a&gt;&lt;br&gt;
[3] Shahid Pattani, "Design-to-Code AI Is Not Magic" - &lt;a href="https://medium.com/aimonks/design-to-code-ai-is-not-magic-heres-why-it-fails-sometimes-7740051f3580" rel="noopener noreferrer"&gt;https://medium.com/aimonks/design-to-code-ai-is-not-magic-heres-why-it-fails-sometimes-7740051f3580&lt;/a&gt;&lt;br&gt;
[4] Emilia BiblioKit, "3 Design System Bugs That Survive Every Code Review" - &lt;a href="https://medium.com/design-bootcamp/3-design-system-bugs-that-survive-every-code-review-and-why-ai-makes-them-worse-55272372ee6a" rel="noopener noreferrer"&gt;https://medium.com/design-bootcamp/3-design-system-bugs-that-survive-every-code-review-and-why-ai-makes-them-worse-55272372ee6a&lt;/a&gt;&lt;br&gt;
[5] Prathit, "AI Models Still Can't Configure Tailwind Correctly" - &lt;a href="https://prathit.vercel.app/blog/ai-models-still-can%27t-configure-tailwind" rel="noopener noreferrer"&gt;https://prathit.vercel.app/blog/ai-models-still-can%27t-configure-tailwind&lt;/a&gt;&lt;br&gt;
[6] Web-Bench (ByteDance, 2025) - &lt;a href="https://arxiv.org/html/2505.07473v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2505.07473v1&lt;/a&gt;&lt;br&gt;
[7] GitClear, "AI Code Quality 2025" - &lt;a href="https://www.gitclear.com/ai_assistant_code_quality_2025_research" rel="noopener noreferrer"&gt;https://www.gitclear.com/ai_assistant_code_quality_2025_research&lt;/a&gt;&lt;br&gt;
[8] Simon Willison, "Hallucinations in code are the least dangerous form of LLM mistakes" - &lt;a href="https://simonwillison.net/2025/Mar/2/hallucinations-in-code/" rel="noopener noreferrer"&gt;https://simonwillison.net/2025/Mar/2/hallucinations-in-code/&lt;/a&gt;&lt;br&gt;
[9] PkgPulse, "The State of CSS-in-JS in 2026" - &lt;a href="https://www.pkgpulse.com/guides/state-of-css-in-js-2026" rel="noopener noreferrer"&gt;https://www.pkgpulse.com/guides/state-of-css-in-js-2026&lt;/a&gt;&lt;br&gt;
[10] devclass, "Tailwind Labs layoffs" - &lt;a href="https://devclass.com/2026/01/08/tailwind-labs-lays-off-75-percent-of-its-engineers-thanks-to-brutal-impact-of-ai/" rel="noopener noreferrer"&gt;https://devclass.com/2026/01/08/tailwind-labs-lays-off-75-percent-of-its-engineers-thanks-to-brutal-impact-of-ai/&lt;/a&gt;&lt;br&gt;
[11] React 18 Working Group Discussion #110 (Sebastian Markbage) - &lt;a href="https://github.com/reactwg/react-18/discussions/110" rel="noopener noreferrer"&gt;https://github.com/reactwg/react-18/discussions/110&lt;/a&gt;&lt;br&gt;
[12] Sachin Patel, "Cursor Isn't the Problem. Your Design Tokens Are." - &lt;a href="https://medium.com/@sachin88/how-we-fixed-design-tokens-to-make-cursor-generate-reliable-ui-code-74d699e72e38" rel="noopener noreferrer"&gt;https://medium.com/@sachin88/how-we-fixed-design-tokens-to-make-cursor-generate-reliable-ui-code-74d699e72e38&lt;/a&gt;&lt;br&gt;
[13] Builder.io, "TypeScript vs JavaScript: Why AI Coding Tools Work Better with TypeScript" - &lt;a href="https://www.builder.io/blog/typescript-vs-javascript" rel="noopener noreferrer"&gt;https://www.builder.io/blog/typescript-vs-javascript&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>css</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>We still don't have proper CSS frameworks</title>
      <dc:creator>Stéphane LaFlèche</dc:creator>
      <pubDate>Fri, 22 May 2026 12:58:55 +0000</pubDate>
      <link>https://dev.to/slafleche/we-still-dont-have-proper-css-frameworks-18dk</link>
      <guid>https://dev.to/slafleche/we-still-dont-have-proper-css-frameworks-18dk</guid>
      <description>&lt;p&gt;We have utility libraries, class-naming conventions, and methodologies dressed up in framework branding. What we don't have is a CSS layer that behaves like a framework does in any other ecosystem: typed input, defined output, a contract a compiler can actually enforce.&lt;/p&gt;

&lt;p&gt;This is the long version of a complaint I've been making in private for years. It also names what I think a real CSS framework would do, and shows the working sketch I've been building in that direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind is useful, but it's not really a framework
&lt;/h2&gt;

&lt;p&gt;The current heavyweight is Tailwind, with &lt;a href="https://www.npmjs.com/package/tailwindcss" rel="noopener noreferrer"&gt;over 400 million npm downloads a month as of May 2026&lt;/a&gt;, so let's start with what it actually is. Strip the build step away and the utility-first methodology isn't new. Object-Oriented CSS, popularized by &lt;a href="https://github.com/stubbornella/oocss" rel="noopener noreferrer"&gt;Nicole Sullivan&lt;/a&gt; in 2008, was already making the same case: small, single-purpose classes you compose at the markup layer.&lt;/p&gt;

&lt;p&gt;Before Tailwind existed, plenty of teams generated their own utility scales using SCSS loops. You can rebuild a meaningful slice of Tailwind's spacing utilities in a few lines of SCSS that would've worked in 2012:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define the design system tokens&lt;/span&gt;
&lt;span class="nv"&gt;$spacing-map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.25rem&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;
  &lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.5rem&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;
  &lt;span class="s2"&gt;"4"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;
  &lt;span class="s2"&gt;"8"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;     &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="m"&gt;32px&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Loop to generate padding and margin utilities&lt;/span&gt;
&lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$spacing-map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.p-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.pt-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.m-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.mt-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Compiles to:&lt;/span&gt;
&lt;span class="c1"&gt;// .p-1  { padding: 0.25rem; }&lt;/span&gt;
&lt;span class="c1"&gt;// .pt-1 { padding-top: 0.25rem; } ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What Tailwind genuinely adds is the build step. The JIT compiler scans your codebase and emits only the utility classes you actually use, with arbitrary-value support (&lt;code&gt;p-[17px]&lt;/code&gt;) for one-offs. That's a real ergonomic win. Bundle sizes shrank and authoring speed went up.&lt;/p&gt;

&lt;p&gt;The downstream cost is harder to talk about, because it shows up in maintenance, not authoring. In a Tailwind codebase, when something looks off on a page and you go searching for what styled it, you often can't. The class you'd search for (&lt;code&gt;flex&lt;/code&gt;, &lt;code&gt;text-center&lt;/code&gt;, &lt;code&gt;p-4&lt;/code&gt;) appears a thousand times across the project. Layout decisions become string fragments scattered across every component file, not declarations you can grep, jump-to, or rename in one place. The tools that normally help you navigate a codebase mostly don't.&lt;/p&gt;

&lt;p&gt;What we have, then: utility classes that were doable in SCSS in 2012, a build step that makes them ergonomic, and a search-and-rename problem that gets worse the bigger the project gets. Is that really what we want from a framework?&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this breaks
&lt;/h2&gt;

&lt;p&gt;AI didn't break Tailwind, even though &lt;a href="https://lobste.rs/s/dzcugr/tailwind_labs_loses_80_revenue_75" rel="noopener noreferrer"&gt;January's layoffs at Tailwind Labs&lt;/a&gt; (the "AI killed Tailwind" framing) read that way in headlines. It exposed a contract Tailwind never had.&lt;/p&gt;

&lt;p&gt;For most of the Tailwind era, humans wrote the class names. There was an implicit social contract: you stayed mostly on the spacing scale, you didn't use arbitrary values without a reason, you noticed when a string was getting absurd and broke it into a component. The framework didn't enforce any of that. It just trusted you.&lt;/p&gt;

&lt;p&gt;The trust assumption is breaking. AI now writes a meaningful share of production CSS, and AI has no implicit social contract. It generates plausible-looking utility strings that pass a glance review and then break across a viewport, or duplicate themselves, or quietly drift off the scale. The class attribute runs to thirty utilities, half of them redundant (&lt;code&gt;p-4 pt-4 pb-4 px-4 mt-2 mb-2&lt;/code&gt; for what should have been &lt;code&gt;p-4 my-2&lt;/code&gt;), and nothing in the stack catches the drift. Reviewing the output by hand becomes the bottleneck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The arbitrary-value escape hatch.&lt;/strong&gt; &lt;code&gt;p-[17px]&lt;/code&gt; was tolerable when a senior dev would push back in review. Now it's a default behavior of the code generator, and there's no contract for anyone to point at. "Use the scale" is a vibe, not a rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The systematic-looking string.&lt;/strong&gt; &lt;code&gt;p-[var(--spacing-3)]&lt;/code&gt; looks systematic. There's a token name in there, the convention seems followed, reviewers wave it through. But the framework's scanning step doesn't actually understand it. The var lives inside a string fragment, not in the helper API. You can typo the variable name and ship it. Nothing catches that. Hardcoding is honest dishonesty. &lt;strong&gt;Token-wrapped strings are dishonest dishonesty.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tailwind users will point to the fixes: &lt;code&gt;@apply&lt;/code&gt; and component extraction for the grep problem, ESLint plugins and a theme-only config for the off-scale problem. These help, but they are external constraints layered on top, not a contract the type system enforces. A linter you can disable per line is a convention with tooling, not a compiler that refuses to emit invalid output. That distinction is the whole argument.&lt;/p&gt;

&lt;p&gt;The fix isn't to ban AI from CSS, or to ban arbitrary values. The fix is to give the codebase a contract the AI can actually run inside: typed inputs that the build can verify, helpers that emit valid CSS, off-scale values visible rather than indistinguishable from on-scale ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a framework should mean for CSS
&lt;/h2&gt;

&lt;p&gt;In any other ecosystem, a framework gives you a contract. You hand it inputs in a defined shape, it does the work inside, you get a defined output. Rails takes route definitions and gives you a request lifecycle. React takes components and props and gives you a reconciled tree. The framework owns the implementation; you own the configuration and composition.&lt;/p&gt;

&lt;p&gt;A CSS framework, by that standard, would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Take typed design tokens in and emit valid CSS out.&lt;/strong&gt; Every value (length, color, string) becomes data the build can see, not strings to scan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail at compile time on mismatched units.&lt;/strong&gt; Off-scale values stay possible, but visibly off-scale, not laundered into the same syntax as everything else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cover the full CSS spec, not a subset.&lt;/strong&gt; New properties land in browsers all the time (&lt;code&gt;@container&lt;/code&gt;, &lt;code&gt;view-timeline&lt;/code&gt;, &lt;code&gt;field-sizing&lt;/code&gt;); a framework that gates which features you can use restricts the work to whatever its authors had time to model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay opinionated at the edges, loose in the middle.&lt;/strong&gt; Strict on typed input and valid emission. Composition, file organization, helper depth: all yours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offer opt-in helpers, never mandatory ones.&lt;/strong&gt; A team could write a &lt;code&gt;borders&lt;/code&gt; helper that groups width, color, and radius the way designers think about them; another team could skip that layer entirely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That shape (strict edges, loose middle, full spec) is the &lt;strong&gt;inverse&lt;/strong&gt; of how most CSS frameworks work. Tailwind owns the middle (every class is theirs); the edges stay loose (any string can land in a class attribute). CSS-in-JS libraries own a template syntax in the middle, with values inside the template still untyped. Typed CSS-in-JS libraries like vanilla-extract type the output but not the input. A framework with strict edges in both directions, and a loose middle, is rare in CSS, but it's how typed systems work everywhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  A working sketch: CSS-Calipers
&lt;/h2&gt;

&lt;p&gt;This is the principle in code. &lt;a href="https://www.npmjs.com/package/css-calipers" rel="noopener noreferrer"&gt;CSS-Calipers&lt;/a&gt; is a small TypeScript library I wrote last year. The ideas behind it go back to my Vanilla Forums days. It covers the measurement-and-math piece of the framework I keep wanting. &lt;strong&gt;Tokens in, typed CSS out.&lt;/strong&gt; The helpers are the contract. Best to use at build time, but occasional runtime possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjjlw8agszlu20005ien.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjjlw8agszlu20005ien.png" alt="CSS-Calipers code example showing the m() constructor, typed math via .add() and .multiply(), a deliberate unit-mismatch error (px + deg), and the final .css() emission step" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The measurements stay opaque through composition. Nothing emits a string until you call &lt;code&gt;.css()&lt;/code&gt; at the boundary. The math is checked at every step, not just at the end.&lt;/p&gt;

&lt;p&gt;Mismatched units fail fast. As the snippet above shows, &lt;code&gt;paddingBase.add(rotation)&lt;/code&gt; throws a clear error with px vs. deg named in the message. You don't find out in production that you added pixels to degrees.&lt;/p&gt;

&lt;p&gt;The measurement core is the foundation. On top of it I've built a helpers layer in my &lt;a href="https://lafleche.dev/" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;: borders, paddings, margins, shadows. Each helper consumes measurements and emits typed style objects. Here's the borders helper in actual use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Use defaults from the token layer&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardBase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;borders&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Override specific values inline&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardEmphasis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;borders&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;south&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// compass-style: south = bottom&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Or pass a full token config&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardThemed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;borders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cardBorders&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three calling shapes, all valid: defaults, inline overrides, full token configs. The third one is where this starts to feel like a framework. Imagine you import the token from a tokens file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tokens/cardBorders.ts — today&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardBorders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;surface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/Card.styles.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cardBorders&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/tokens/cardBorders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;borders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cardBorders&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now design wants a thicker accent top and rounded bottom corners. You edit only the tokens file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tokens/cardBorders.ts — after the design tweak&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cardBorders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;surface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;south&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component file is &lt;strong&gt;unchanged&lt;/strong&gt;. The helper accepts the new token shape and emits more CSS; if you remove keys later, it emits less. Adding a &lt;code&gt;borderTopWidth&lt;/code&gt; to the design means a new key in the token object, not a new class in your markup. &lt;strong&gt;The call site is invariant; the design tokens are where the change happens.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spacing helpers work the same way: &lt;code&gt;paddings(m(16))&lt;/code&gt; for uniform, &lt;code&gt;paddings({ vertical: m(8), horizontal: m(16) })&lt;/code&gt; for axis-intent, &lt;code&gt;paddings(theme.cardPadding)&lt;/code&gt; to delegate the shape entirely to tokens. Same calling pattern across the layer.&lt;/p&gt;

&lt;p&gt;Helper names are deliberately the plural of the CSS property they emit: &lt;code&gt;paddings&lt;/code&gt;, &lt;code&gt;borders&lt;/code&gt;, &lt;code&gt;margins&lt;/code&gt;, &lt;code&gt;shadows&lt;/code&gt;. Grep-able, visually distinct from a raw &lt;code&gt;padding&lt;/code&gt; property in a style object, consistent across the layer.&lt;/p&gt;

&lt;p&gt;The same pattern extends through the rest of the helpers layer: &lt;code&gt;@supports&lt;/code&gt; fallbacks as typed objects, accessibility variants typed against the actual CSS feature set, color manipulation through typed methods, typed media-query factories, typed &lt;code&gt;clamp&lt;/code&gt; and other math primitives. CSS values get type-checking in places they almost never do in normal CSS-in-JS work.&lt;/p&gt;

&lt;p&gt;You can opt in or out at any boundary. Use measurements for high-stakes spacing math; write raw Tailwind classes for layout primitives where utility-first wins; drop into a CSS Module or styled-components for component-scoped work. CSS-Calipers itself is compiler-agnostic: it produces typed CSS strings that work with any of those, or with bare style objects, or wherever else you want valid CSS to land. The library doesn't try to own the middle. The contract is the function signatures, not the entire styling story.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Missing Framework Layer
&lt;/h2&gt;

&lt;p&gt;We still don't have proper CSS frameworks. The pieces exist in different places: typed CSS-in-TS, design tokens, scanning compilers, agent-aware tooling. None of them are wired together into a single thing that takes typed input from your token layer, emits valid CSS to the spec, and stays out of the way in between.&lt;/p&gt;

&lt;p&gt;Getting there isn't a single project. It's a shift in how the category is defined: what we call "frameworks" today are vocabularies and methodologies. What a real one would be is a contract.&lt;/p&gt;

&lt;p&gt;It's hard. The CSS spec is complex: edge cases, shorthand properties, overrides, the cascade itself. A real framework can't simplify those away by giving you a subset; it has to absorb the mess and stay faithful to it. CSS is the spec, and the spec is messy.&lt;/p&gt;

&lt;p&gt;A real CSS framework is opinionated at the edges where types matter, loose in the middle where you compose, and covers the whole CSS spec rather than a subset. We don't have one yet. We could.&lt;/p&gt;

</description>
      <category>development</category>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
