Two essays about the same frustration: we keep rebuilding the same frontend foundations per project, and a component library alone does not fix that.
Part 1 asks what is actually wrong and why a design system by itself is not the answer. Part 2 argues for JSON Schema as the universal layer — and for letting the frontend describe the content model instead of the CMS.
| Fact | Detail |
|---|---|
| Part 1 | “So what's wrong?” — silos, reinvention, and why a design system is not an ecosystem |
| Part 2 | “Finding universality” — JSON Schema, reversed roles, and how AI fits |
| Length | ≈5,200 + ≈6,400 words |
| Published | 2024, on the kickstartDS blog |
What's in it
Classic architectures, the first wave of web ecosystems, and the uncomfortable conclusion that emancipating the frontend takes more than components — there is no frontend ecosystem the way there is a backend one.
Enter JSON Schema, and “a call to reverse roles”: the frontend owns the description of the content, and the CMS configuration is generated from it.
If a system can describe itself — components, props, tokens, content shapes — then a CMS and a language model can use that description. The schema layer is what makes the AI angle more than a demo.
In detail
What is actually inside it
Every claim maps to something built: token layers, schema-derived CMS configuration, generated types, the generator/validator split.
Before the current wave of AI tooling — the argument about structure over prompts has only got easier to make since.
“A call to reverse roles” is addressed to everyone building frontends and CMSes, not to users of one particular framework.
| Detail | Value |
|---|---|
| Part 1 | kickstartds.com/blog/unlocking-the-frontend-pt1 |
| Part 2 | …-pt2 (5 March 2024) |
| Themes | silos, ecosystems, schema universality, reversed CMS roles, AI |
Technical notes
The decisions behind it
What is the core claim of part 2?
Why write it as prose?
What part 1 actually diagnoses
The architectural argument, and the counter-argument it answers
Part 1 is dated 6 March 2022 (12 min read) and is a genealogy rather than a complaint list. It walks four stages.
1. Bespoke everything. Models, relations, the logic on top of them, the actions triggered on interaction, and finally a frontend built for exactly those circumstances — all interlocked, so “changes of every kind typically being costly as a consequence, leading to everyone trying to over-spec even more… a vicious cycle of ultimately missed expectations.”
2. MVC and shared practice. Symfony for PHP, Rails for Ruby, Express for Node.js, Spring for Java — plus agile processes. Changes became predictable, and that feedback loop converged everyone on shared best practices, shipped as plugins, extensions and addons.
3. CMS as the web's MVC. WordPress, TYPO3 and Drupal added an already established content domain. But every customer still needed fine-tuning, “the frontend still got painstakingly re-implemented with every major overhaul”, and every editor type — news, career, marketing, blog, internal communication — was pushed into the same monolith.
4. Headless and Jamstack. Decoupling frontend from backend (“Jamstack” set against the classic “LAMP” stack) makes the API a shared contract that both sides can test in isolation. Generators (Gatsby, Next.js, 11ty) then let several sources feed one interface: WordPress for long-form content, Storyblok for landing pages, Sanity for structured content, third-party APIs as needed.
Then the turn: “But… where's my frontend ecosystem?” Everything else got re-use, specialization and standardization; the frontend is still assembled per project — a design file on one side, and “data structures that are the result of decisions that were made in your absence” on the other. The same component is also somehow expected to work on the blog, only to “look and behave slightly different”. Camus' Sisyphus is the epigraph for that job.
The design-system objection gets its own chapter — Why just creating a Design System is not the answer, either. A design system is too often treated as “just another added thing on top, that's expected to be delivered, en passant”, when the real requirement is “adjusting the way frontends are architected” and, “in some places inverting the way we work today”. Note what part 1 does not name: there is no JSON Schema here yet, only a call to standardize “the way components can be compared, the way they expect and consume data, and effective ways of mapping between all of those.”
What part 2 proposes — and where it came from
JSON Schema as the neutral layer, and the roles that have to reverse
Part 2 landed two years later, on 5 March 2024 (20 min). Its universal claim is deliberately narrow: every component has an API — “Component Props” in React, Vue and Svelte, “Property Binding” in Angular, “Variables” in Figma, the structure of Frontmatter in an 11ty project. Today that shape is owned either by a backend/API (“leaking a backend view of the world into the implementation”) or by a design prototype (“a too visually reductionist direction”). Either way, you are downstream of it.
The proposal is to stop being downstream: put JSON Schema in as the neutral description layer, and generate the CMS configuration from it instead of mapping the schema to the CMS. Part 2 calls this “a call to reverse roles”. Decoupling the Design System from any one implementation also separates structure and function from implementation, so one design system can back several component libraries, or several CMS integrations.
The lineage is stated too: 20 years of agency work integrating frontend into PHP systems (TYPO3, WordPress) through templating engines like Fluid; Pattern Lab's habit of documenting every component variant as a JSON data.json; the 2021 move from agency to product; and the rewrite that ditched Pattern Lab for Storybook, Handlebars for React (templating only) and ported those data.json files into JSON Schema-backed “component APIs”. The tooling open-sourced alongside the post splits that layer into two output families: TypeScript types, GraphQL fragments and dereferenced schemas for development, and headless-CMS configuration for integration.
Predicted vs. shipped
The essays checked against the repositories, after 5 March 2024
Did the Web Components switch happen?
.tsx templates (ButtonComponent.tsx, ContactComponent.tsx, …) with no custom-elements package. The prediction is unfulfilled, not disproven.What did the converter tooling actually grow into?
kickstartDS/schema now ships seven conversions from one JSON Schema base: Storyblok, Static CMS, Stackbit, Hygraph, Uniform, CPort and TypeScript types. They share one reducer pattern — eight type-specific process functions (processObject, processRef, processEnum, …) plugged into a central walker — so a new target is mostly a mapping, not a rewrite.How is the reversed role enforced at runtime?
x-cms-group-inline, @kickstartds/cambria emits a forward lens per component as invertible operations (hoist, rename, remove). The renderer reverses the lens and applies it to the incoming CMS payload to recover the nested shape its TypeScript types expect. Cambria is a real data-migration engine: 10 invertible lens ops, translation of RFC 6902 JSON Patch operations through lenses, and Dijkstra-based path finding between schema versions.What about the AI section?
outlines and at .json (by outlines' authors) for guided generation that follows a JSON Schema, and frames schema docs as “semantic context for the AI model / LLM”. That remains an argument, not shipped code — the concrete artifacts are the CMS annotation vocabulary (x-cms-group-name, x-cms-group-inline, x-cms-order, x-cms-label) and twelve ADRs recording decisions such as re-allocating Storyblok's tab/section primitives and keeping tab keys deterministic (tab-<groupName>) so two converter runs produce identical diffs.What does the tooling still not do?
x-cms-hidden and x-cms-preview, naming of nested object arrays in the Storyblok converter, and enum merging for properties below the root level (open since Nov 2023).Links
Where to find this one
