{"id":48013585,"url":"https://github.com/nongio/layers","last_synced_at":"2026-04-04T13:42:06.296Z","repository":{"id":204101521,"uuid":"618725277","full_name":"nongio/layers","owner":"nongio","description":"Layers is a rendering engine for animated user interfaces","archived":false,"fork":false,"pushed_at":"2026-04-04T08:57:39.000Z","size":7690,"stargazers_count":6,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-04T10:22:20.625Z","etag":null,"topics":["graphical-user-interface","scene-graph","skia","ui"],"latest_commit_sha":null,"homepage":"https://nongio.github.io/layers/docs/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nongio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2023-03-25T06:52:10.000Z","updated_at":"2026-04-04T08:35:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"87d41f1a-50b0-4f1f-83c3-44cc14f89e5f","html_url":"https://github.com/nongio/layers","commit_stats":null,"previous_names":["nongio/layers"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/nongio/layers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nongio%2Flayers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nongio%2Flayers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nongio%2Flayers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nongio%2Flayers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nongio","download_url":"https://codeload.github.com/nongio/layers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nongio%2Flayers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31402276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphical-user-interface","scene-graph","skia","ui"],"created_at":"2026-04-04T13:42:06.200Z","updated_at":"2026-04-04T13:42:06.279Z","avatar_url":"https://github.com/nongio.png","language":"Rust","readme":"\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/nongio/layers/blob/main/assets/laye-rs.jpg?raw=true\" alt=\"Layers Engine Logo\" width=\"384\" height=\"192\"\u003e\n\u003c/p\u003e\n\n## laye-rs engine\n![CI Status](https://github.com/nongio/layers/actions/workflows/ci.yml/badge.svg)\n\n\n\n\nlaye-rs is a rendering engine for animated user interfaces, mainly designed in support of the Otto compositor [project](https://github.com/nongio/otto).\n\nIt uses a scene graph to render the nodes in retained mode, optmising the most common UI interpolations (opacity, 2d transformations, blending).\nNodes of the scene graph are graphical layers like text or simple shapes like rectangles but can also be external textures.\n\n- Nodes have animatable properties that accepts changes and schedule them in the engine to be executed. \n- Layers use a Command pattern to receive changes with a consistent api between immediate changes and animated changes.\n- The rendering commands are optimised using displaylist.\n- Node properties can be animated, hooks to different stages of the animation progress are exposed by the API.\n\n## Read the docs\nThe api is getting documented, be aware that is also still in evolution.\n[documentation](https://nongio.github.io/layers/docs/)\n\n- Engine update pipeline \u0026 damage tracking: see `docs/` for a deep dive into frame stages and redraw rules.\n- Layers Inspector: a browser-based debugger that shows the live scene graph with search and highlights (`docs/layers_inspector.md`).\n  - **Web UI**: `http://localhost:8000/client/index.html`\n  - **HTTP API**: The debugger server exposes a REST endpoint to fetch the scene graph:\n    - `GET /scene` — returns the full scene tree as JSON\n    - `GET /scene/{node_id}` — returns only the subtree rooted at the specified node\n    - Port defaults to `8000`, configurable via `LAYERS_DEBUGGER_PORT` env var\n\n\n## Rendering\nAt the moment the components are rendered using Skia on different backends. This enables some drawing optimisation: the draw calls can be cached using a DisplayList. A Skia PictureRecorder is generate on a separate thread and then replayed on the main thread when needed.\n\n### Scene\nThe scene tree is stored in a memory arena using IndexTree, which allow fast read/write and thread safe parallel iterations.\n\n### Colors\nColors are stored in OK lab color space to enable smooth and uniform looking transitions between them.\nmore about Oklab in Björn Ottosson [blog](https://bottosson.github.io/posts/oklab/)\n\n### Layout\nThe layout is done using Taffy, every layer supports Flex, Block and Grid layout.\n\n# Build the library\nAt the moment the project requires to setup skia-safe configuration variables before building. See `Cargo.toml`. Once configured the library can be built using cargo.\nThe C header will be generated in the `target` folder.\nThe project requires nightly rust to use the negative_impl feature.\n```\ncargo build\n```\n\n### Run the damage test suite\nThe integration tests in `tests/damage.rs` cover the damage tracking pipeline end-to-end.\n```\ncargo test --test damage\n```\n\n## Build the rust example\nThe rust example is setup as a different workspace.\n```\ncargo build -p hello-rust\n```\nLikewise to run the rust example:\n```\ncargo run -p hello-rust\n```\n\n## Build the C example\nThe C example is setup with meson. It requires linux to be built and run because of the dependency with Wayland.\nTo build, it first needs to configure meson:\n```\nmeson build/\n```\nand then run ninja:\n```\nninja -c build\n```\nthe executable will be in the `build/` folder.\n\n## Usage\n\n## Usage: Setup a basic scene with a root layer\n```rust\nuse layers::prelude::*;\nlet engine = Engine::create(800.0, 600.0);\nlet layer = engine.new_layer();\nlet engine = Engine::create(1024.0, 768.0);\nlet root_layer = engine.new_layer();\nroot_layer.set_position(Point { x: 0.0, y: 0.0 });\nroot_layer.set_background_color(\n    PaintColor::Solid {\n        color: Color::new_rgba255(180, 180, 180, 255),\n    }\n);\nroot_layer.set_border_corner_radius(10.0, None);\nroot_layer.set_layout_style(taffy::Style {\n    position: taffy::Position::Absolute,\n    display: taffy::Display::Flex,\n    flex_direction: taffy::FlexDirection::Column,\n    justify_content: Some(taffy::JustifyContent::Center),\n    align_items: Some(taffy::AlignItems::Center),\n    ..Default::default()\n});\nengine.add_layer(root_layer.clone());\n```\n\n## Usage: Tick the engine to update layout and animations\n```rust\nuse layers::prelude::*;\nlet engine = Engine::create(800.0, 600.0);\n// setup the scene...\nengine.update(0.016);\n```\n\n## Usage: View builder\n```rust\nuse layers::prelude::*;\n\n// view rendering function\npub fn render_main_view(state: \u0026bool, view: \u0026View\u003cbool\u003e) -\u003e LayerTree {\n    let mut position = 0.0;\n    if *state {\n        position = 100.0;\n    }\n    let view = view.clone();\n\n    LayerTreeBuilder::default()\n        .key(\"main_view\")\n        .position(\n            Point {\n                x: position,\n                y: position,\n            }\n        )\n        .size(\n            Size {\n                width: taffy::Dimension::Length(50.0),\n                height: taffy::Dimension::Length(50.0),\n            }\n        )\n        .build()\n        .unwrap()\n}\n\nlet engine = Engine::create(1000.0, 1000.0);\n// create a new layer and add it to the scene\nlet layer = engine.new_layer();\nengine.add_layer(layer.clone());\n\n// define a new view with a boolean state\nlet initial = false;\nlet mut view = View::new(\"test_view\", initial, render_one_child_view);\n// assign the layer to the view, the rendered tree will be added to the layer\nview.mount_layer(layer);\n// layout the scene and update animations\nengine.update(0.016);\n// render the scene to terminal\ndebug_scene(engine.scene(), engine.scene_root().unwrap());\n```\n\n## More examples\nPlease check the example folder:\nhttps://github.com/nongio/layers/tree/main/examples\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnongio%2Flayers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnongio%2Flayers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnongio%2Flayers/lists"}