Back to News & Insights
Artificial Intelligence August 13, 2026 · 12 min read

To keep the AI from breaking my design, it only writes JSON. I built that out for real, and the JSON turned into code

While mass-producing web tools with an AI, I've changed how I lock the design in three stages. The...

To keep the AI from breaking my design, it only writes JSON. I built that out for real, and the JSON turned into code

While mass-producing web tools with an AI, I've changed how I lock the design in three stages. The previous post I wrote about that got this comment:

"I'd like to see the JSON approach and the design-system approach side by side."

Taken at face value, I should just put the two side by side. But first, let me add a short preface. I don't want to frame this as "the JSON approach versus the design-system approach." When I called the JSON approach a "failure" in that post, I didn't mean the method is inferior; I meant it didn't suit my particular set of tools.

A page made with the JSON approach does look thin. But where that thinness comes from is easily misread. Whether the design drifts and whether it looks rich are decided separately. What stops the drift is locking the design; whether it looks rich is how much you build out. What locking with JSON removes is drift in the items you specified in the schema. Whether the screen becomes rich, on the other hand, is determined by how much you've built out the machinery that turns that JSON into a screen. So it isn't that locking with JSON is what made it look like a spreadsheet. In the previous post, too, I wrote that fattening the schema and the renderer does increase the expression itself. But that came with a caveat: past a point, it heads toward rebuilding HTML and CSS by hand.

What I really want to check is one step past that. If the template sets the ceiling on expression, then building out the JSON side's template as much as the current one should produce the same screen. So what does that build-out demand? I actually built it and measured. I'll share the result, along with the JSON-approach and design-system-approach screens placed side by side under matched test conditions.

I'll admit up front: at the time, I chose the design system without running this comparison. So this is me building the road I didn't take, after the fact, and measuring what that cost consists of.

So that the comparison reflects the difference between the approaches, I matched everything I could match. I fixed the subject to a BMI calculator. On both sides, generation was a separate Claude Opus 4.8 session, and I handed over only "that approach's toolkit." One write only, no later edits, and to avoid contamination I let neither side read the production BMI calculator.

The one thing I didn't match is the part that amounts to the definition of each approach itself. I told the JSON approach to "write one catalog entry," and the design-system approach to "write the page template." Match even that, and you're no longer comparing the two approaches.

| | JSON approach | Design-system approach | |---|---|---| | Toolkit handed over | the entry schema (4 structure keys, plus 7 string keys the template reads)1 fixed template for BMI | a build guidea pattern collectiona template spec1 reference template | | What the AI wrote | 1 catalog entry (34 lines, fully conformant to the schema) | 1 page template (313 lines) and a dictionary for 5 languages | | What decided the screen's contents | the fixed template I handed over (the AI can't touch it) | the template the AI wrote |

The same BMI calculator, generated one-shot from each era's toolkit alone. Input: 170 cm / 65 kg.

The unit toggle, the disclaimer, and the four-band color coding weren't decided by the AI from nothing either. The parts, the requirements, and the color standard are held by the toolkit side (the build guide, the pattern collection, the template spec), and the AI assembled in line with them.

Placed side by side, the JSON side looks thin. But this thinness isn't due to the approach. Build out that era's machinery as much as the current one and the same look comes out. The fact that the themes split light and dark isn't a difference of approach either. Theme wasn't a condition I matched for the test; it's the result of carrying over each era's actual setup as-is. The current design system's production theme is dark, and the AI used that layout and those tokens as-is. The JSON side is light simply because that era's template is light. Neither look nor theme divides the approaches here.

Where the difference in approach shows is in how each one frays. The JSON side's fixed template hardcodes the WHO four-band labels in English on the JavaScript side, with no corresponding JSON key. So even if the AI writes the entry perfectly, the verdict alone comes out in English on the Japanese and Spanish versions. This isn't because JSON can't be localized; the key simply wasn't there. But adding that key is an extension of the schema and the renderer, and the AI can't reach it from within a one-shot entry. On the design-system side, the AI produced the four-band labels in all five languages on the spot. Prevention-type design locking isn't that flaws don't appear; it's a mechanism where you crush the flaws that do appear by widening the shared schema and renderer.

The design-system side frayed too. Two of them, found in different ways. One bg-white, which is forbidden, had slipped into the class list of the scale marker. It violates the design system's rule of not writing a color like bg-white directly into a class, but letting the theme decide it. But on this screen the bg-white itself has no effect. Since this directive doesn't get into the built CSS, the stray bg-white never surfaces as white. So you can't tell it's a violation by looking; only a machine check that reads the class strings can catch it. The other is a different flaw, and this one you can tell at a glance. That marker looks like nothing more than a notch cutting darkly across the band, and the part that overshoots the band sinks into the background, making it hard to read where on the BMI it's pointing. There's no spec for how the marker should be shown, and no rule binding it. So the machine check passes it by, and this flaw stayed in the output as-is. In real operation, an inspection-and-touch-up step follows generation, and flaws like this get fixed there. This time the condition is one-shot only, without running that step, so this is how it came out. Inspection-type design locking isn't that flaws don't appear; it's a mechanism where you crush the flaws that do appear by adding to the pattern collection, the spec, and the hooks.

Without breaking the JSON approach's rules, I built it out until it reached the same expressive elements as the current one-shot output. I set three rules not to break: the AI writes only the JSON catalog entry; it doesn't get to touch the template or the renderer it isn't allowed to write raw HTML, CSS, or JavaScript into that JSON the renderer doesn't get a BMI-specific branch

At the level of expressive elements, I got there (the remaining compromises are listed at the end). The question is what swelled, and by how much, to get there.

The real thing, extended while staying with the JSON approach until it reached the same expressive elements.

| | Before extension | After extension | |---|---|---| | Catalog entry | 34 lines, 24 values | 343 lines, 258 values | | Schema vocabulary the AI must learn | 11 words | 113 words | | Renderer | 433 lines | 914 lines | | BMI-specific template | 53 lines | 1 line (just inherits the shared template) |

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation