Layers is a declarative language for describing things and the relationships between them. A C++ engine resolves the data and associated relationships at runtime. It is schema-free: Layers manages the structure and resolution; you (or a framework built on it, like Vortex) give the values their meaning. Layers data is stored in .lyr files.
✨ This project is developed with AI-assistance. Please refer to our AI policy.
Since Layers is schema-free, these examples demonstrate how it might be used across a variety of domains.
See how states let one tree answer for all environments.
Service:
Name: "My API"
Version: "0.1"
Host: "api.example.com"
@Dev: "api.example.dev"
@Local: "localhost:8080"
Registration: false
@Prod: true // `true` if environment is `Prod`
Account Limit: 1000
@Dev: 30
@Local: 5
See how an inheritance chain means each role is the same as the previous, plus some changes.
Viewer:
Can.(Read,Comment): true
Can.(Write,Delete,Invite): false
Editor << Viewer: // `Editor` is a `Viewer`
Can.Write: true
Admin << Editor: // `Admin` is an `Editor`
Can.(Delete,Invite): true
See how a linked reference creates a single source of truth, how composition works through nesting, and how derivations can override.
Theme:
Foreground: #e3e3e3
Primary: #36393f
Secondary: #2f3136
Tertiary: #25272b
Button:
Fill: Theme/Tertiary // `Button/Fill` links to `Theme/Tertiary`
Corner Radius: 5
Icon: // `Icon` is first child of `Button`
Source: ""
Size.(Width,Height): 30
Label: // `Label` is second child of `Button`
Text: "Button"
Color: Theme/Foreground // `Button/Label/Color` is also linked
Confirm Button << Button: // Override values to make a specific button
Icon/Source: "check.svg"
Label/Text: "Confirm"
First, here's a brief rundown of important Layers terms and their meanings.
Layers lets you describe relationships that resolve and stay active at runtime.
Layer inheritance (<< + reference) produces a clone of a referenced base layer.
Editor << Viewer: // `Editor` is a `Viewer`
// ...
Attribute linking (reference as attribute expression) means the value (or link) of another attribute represents the declared attribute. Links are evaluated at runtime so that the chain stays intact to enable relinking later.
Button:
Fill: Theme/Tertiary // `Button/Fill` links to `Theme/Tertiary`
Attribute states conditionally override the main attribute expression.
Registration: false
@Prod: true // `true` if environment is `Prod`
Layers includes other language features for versatility.
Name expansions (parenthesized, comma-separated name segments) break a name into multiple declaration targets.
Can.(Read,Comment): true // Declares both `Can.Read` and `Can.Comment`
A group (name + .) identifies related items.
Padding.(Left,Top,Right,Bottom): 4 // `Padding` is a group
A group-set is useful for declaring multiple group items without repeating the group name.
Font. // Declares both `Font.Family` and `Font.Size`
Family: "Roboto"
Size: 12
A state-set is useful for isolating state values.
@Dev:
Host: "api.example.dev"
Account Limit: 30
Using the user interface example from the top:
LEngine engine;
engine.load_files("path/to/ui/example");
engine.resolve_links();
LLayer* theme = engine.find_layer("Theme");
LAttribute* foreground = theme->find_attribute("Foreground");
LAttribute* secondary = theme->find_attribute("Secondary");
LLayer* btn = engine.find_layer("Confirm Button");
LLayer* btn_base = btn->base(); // `Button`
LAttribute* fill = btn->find_attribute("Fill"); // Inherited
LString fill_val = fill->as<LString>(); // "#ff25272b" (from link)
LConnectionID connection = fill->on_change([]() // Notify when changed
{ std::cout << "Fill changed!" << std::endl; });
fill->create_link(secondary); // Outputs "Fill changed!"
LString new_val = fill->as<LString>(); // "#ff2f3136" (from link)
fill->disconnect_change(connection); // Disconnect notifications
LLayer* label = btn->find_layer("Label");
LAttribute* text = label->find_attribute("Text"); // Overridden
LString text_val = text->as<LString>(); // "Confirm"
LAttribute* color = label->find_attribute("Color"); // Inherited
LString color_val = color->as<LString>(); // "#ffe3e3e3" (from link)
foreground->set_value("#3cf9ff"); // Update link source
color_val = color->as<LString>(); // "#3cf9ff" (from link)
See the class reference documentation for more details.
To learn more about Layers, check out our documentation guides:
Requires CMake 3.22+ and a C++17 compiler.
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
This produces a shared library in lib/. Debug builds append a d suffix (e.g., Layersd). Include headers like #include <Layers/lengine.h>.
Layers is open-source under the MIT license.