Architecture
How the layers fit together, and what regenerates what.
Four formats that cannot drift apart, because none of them contains any design. This page explains how that works, which matters as soon as you want to change something the guides do not cover.
The problem this solves
A theme sold in four formats is normally four codebases. Fix a bug in the Hugo version and the Jekyll version still has it. Change a colour and you change it four times, badly, and the screenshots stop matching two of them.
Adjuvant has one codebase. The formats are adapters: they re-express the same markup in each engine's template language and read the same compiled CSS and the same content files. An adapter that contained a colour would be a bug.
The four layers
tokens.json one file: every colour, size, weight, radius, shadow
|
v
css/tokens.css CSS custom properties, light and dark
css/theme.css every rule in the theme, all reading those properties
js/*.js behaviour, no styling
markup/ canonical HTML for the chrome and every section
content/*.json what the pages say
|
v
html/ hugo/ jekyll/ jbake/ the adapters
|
v
your site
Each layer may read the one above it and never the one below. The rule that keeps this honest: an adapter contains no CSS, no design decisions and no behaviour. If a change belongs in one format only, it belongs in the content, not in the adapter.
What regenerates what
Two scripts, both in source/.
| Script | Reads | Writes |
|---|---|---|
build-core.py | tokens/tokens.json, css/, js/, assets/ | css/tokens.css, and the compiled stylesheet and assets |
build-site.py | content/*.json, markup/, the output above | the HTML site |
The other formats have a vendor.py that copies the compiled output verbatim into the engine's expected layout and materialises the content in the engine's own data format. Vendoring copies; it never edits. If you find yourself hand editing a vendored file, the change belongs upstream in source/.
Why the content is JSON and not front matter
Front matter binds content to one engine's file layout. A Hugo page's front matter is not a Jekyll page's front matter, and neither is a JBake header. Move the content into plain JSON and all four engines can read the same file, which is the only reason the formats stay identical.
The cost is that a blog post is less pleasant to write in JSON than in markdown. So articles are the exception: each format takes markdown for articles in its own idiomatic way, and only the structured content stays in JSON. That trade is explained in the four formats.
Skins
A skin is a JSON file that overrides some tokens and nothing else. The theme ships tokens/skin-clinical-blue.json, which changes four brand values and produces a complete blue site. Build it alongside the default and point a page at the other stylesheet.
This is the same mechanism as a rebrand, just packaged. There is no separate "blue theme" to maintain, which is the point.
Where the design lives, precisely
| Concern | File | Not in |
|---|---|---|
| Colour, type, spacing, radius, shadow | tokens/tokens.json | any stylesheet, any template |
| Every visual rule | css/theme.css | the adapters, the markup |
| Structure of a section | markup/ | the adapters |
| What a section says | content/*.json | the markup |
| Interface labels, ARIA strings | content/ui.json | the renderer |
| Titles, Open Graph, robots, schema.org | content/seo.json | the templates |
The last two are worth knowing about. There is no user-visible English string hard-coded in the renderer, which is what makes translating the theme a matter of editing two files rather than grepping through templates.
What this buys you
- One edit reaches every format. Change a product name once; the catalogue row, the detail page, the schema.org block and the sitemap all follow, in all four formats.
- A rebrand is one line. Because nothing hard-codes a colour.
- The demo cannot lie. The demo site is built by the same two scripts from the same content that ships to you.
What it costs you
- A rebuild step for anything structural. Editing the built HTML directly is supported and always will be, but those edits do not survive a rebuild.
- JSON is stricter than a template. A trailing comma stops the build. The error names the file and the line.
- Deep restructuring means reading
markup/. Adding a genuinely new kind of section is a markup change plus a stylesheet rule, not a content change. The section catalogue covers the seventeen that already exist, which between them handle most pages without any new code.