Read this to understand the problem Layers solves and how it compares to the usual alternatives.
Layers exists because JSON is where structured data goes to get repeated. This page explains the problem, what people usually do about it, and why Layers takes a different path. If you already want the syntax, skip to the JSON guide.
JSON has no way to say "same as that". Every value is a literal, so the moment two values mean the same thing, one of them is a copy. Real data files accumulate these copies fast:
The underlying issue is the same in all three: the relationships between values live in the author's head, not in the data. The file records what each value is, but never that this value follows that one, or builds on it, or replaces it under some condition.
Compile-time templating. Tools like Jsonnet, CUE, and Dhall put a language in front of JSON: you write a program with variables, imports, and functions, evaluate it, and emit static output. This genuinely solves authoring duplication, and if you need generated artifacts (Kubernetes manifests, CI config), it is the right shape. But the output is dead data. The relationships exist only during evaluation; the running application receives plain literals with no idea what was derived from what. Change one value and you regenerate and redistribute everything.
Merging in application code. Load a base file, overlay an override file, apply environment logic in code. Every application reinvents this, each with its own ad-hoc merge semantics, and the composition logic ends up scattered through the codebase instead of visible in the data.
Layers keeps the relationships in the data and resolves them at runtime. Three kinds of composition are authored right in the JSON:
"S:Base"): a node builds on another, overriding on top. An instance is just a diff over its archetype."L:Path/To/Value"): a value is another value. One source of truth; everything linked follows it.":Prod", ":Selected"): one attribute carries several values, and the reader's active states pick one.Because resolution happens inside your running application, the relationships stay alive after loading:
dependent_attributes, on_change).Layers is also schema-free: it manages structure and resolution and never assigns meaning to your names. The same engine describes a color palette, a widget tree, a service config, a character sheet, or a string table. The examples in the repository's examples/ directory show each of those shapes in about forty lines of JSON apiece.
Honesty section. Layers is a C++ engine with a runtime model, and that is not always the right shape:
Layers was born as the styling engine of Vortex, where one JSON style set drives native UIs on desktop, web, and Android. Styling turned out to be the perfect forcing function: theming demanded linking, widget variants demanded inheritance, and interaction and responsiveness demanded states. But none of those features know anything about UI, and the vocabulary was never hardcoded. Layers 2.0 is that engine, offered as what it actually is: JSON inheritance, linking, and states, for whatever your data means.