Layers Logo Image Layers

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.

Quick examples

Since Layers is schema-free, these examples demonstrate how it might be used across a variety of domains.

Configurations

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

Access roles and permissions

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

User interfaces

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"

What is Layers?

First, here's a brief rundown of important Layers terms and their meanings.

  • A layer is a declared thing described with attributes and other layers (like objects in a hierarchy or nodes in a tree).
  • An attribute is a declared expression (like key-value pairs).
  • A declaration is a path that identifies one or more items (like keys or identifiers).
  • An expression is either a value or an attribute reference.
  • A value is a literal unit of data, such as a string, number, boolean, or color.
  • A reference is a path that identifies one specific item.

Describing relationships

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`

Other language features

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

C++ runtime

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.

Want to learn more?

To learn more about Layers, check out our documentation guides:

Building

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>.

License

Layers is open-source under the MIT license.

Appearance
Theme
—