Library / SDK
cycfi/elements avatar
cycfi/elements

cycfi/elements: a C++20 GUI library you describe instead of draw

Elements C++ GUI library

3,724 stars283 forksC++License varies

At a glance

What is it?
Elements builds its interface from a declarative C++ syntax, embeds into an existing host application, and still carries a pre-1.0 API warning. Here is what the repository actually supports today.
Who is it for?
Adopt Elements if you are writing C++20 and want the interface described in the same translation units as the logic, or if you need a GUI that lives inside a VST or AU host without owning the event loop. Do not adopt it if you need a frozen API, a visual editor, or a documented installation path that does not change under you; the README states the API and code are still undergoing continuous changes.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Elements solves, and who it is aimed at

Most GUI toolkits ask you to either draw every control yourself or leave C++ for a designer tool. Elements takes a third route: the entire interface is written in C++ through a domain specific embedded language, so there is no external visual editor and no code generator in the loop. The README describes the library as "lightweight, fine-grained, resolution-independent, extremely modular" and states that a declarative description of the GUI is written exclusively in C++.

The second half of the pitch is embedding. Elements does not own the event loop, which the README frames as the reason it can co-exist with components inside a plugin host such as VST and AU. That is a narrower audience than "anyone building a desktop app". It is aimed at audio plugin developers, at people adding a control surface to an existing native application, and at C++ programmers who would rather express layout in code than maintain a parallel UI file format.

The author is Joel de Guzman, whose README biography lists Boost.Spirit, Boost.Phoenix and Boost.Fusion. That background explains the DSEL design more than any feature list does: the interface is a parser-shaped problem, and the library treats it that way.

How the declarative C++ interface and embedding model work

The mechanism is a DSEL, a domain specific embedded language, built out of ordinary C++20 constructs. You compose elements by chaining and nesting expressions, and the result is a tree the library walks at runtime. The README calls the syntax "sensible and easy-to-use" and notes the library is written using modern C++20 language features, which is also the constraint: this is not a C++11 codebase you can drop into an old toolchain.

The second mechanism is ownership. Because Elements does not own the event loop, it has to integrate with whatever loop the host already runs. The README says porting to a new host target is straightforward and requires porting only a few files, which tells you the platform layer is deliberately thin rather than a large abstraction over every windowing system.

The repository layout supports the same reading. The top level holds CMakeLists.txt, a cmake directory, a lib directory, docs, resources, and an examples directory with roughly two dozen subdirectories, from empty and hello_universe to custom_control, child_window, drop_file and simple_animation. The README's news entry from March 28, 2024 states that the Cairo-based backend was brought back into the fold and is the master branch again, while the Skia backend version is described as still very much in active development and needing a lot of testing, especially around how Skia is integrated. If you are choosing a backend today, that note is the clearest signal in the repository about where the risk sits.

Installing Elements and building your first window

The README points to a Setup and Installation page under the documentation links rather than embedding build steps, and it warns that documentation is a work in progress. What the repository does give you is a top-level CMakeLists.txt and an examples directory, so the practical path is to build the examples. The README does not publish a clone command, a configure command, or a build command, so nothing here should be treated as a documented sequence.

The repository does contain a .gitmodules file at the top level, which means the project pulls in dependencies through git submodules. The README does not say which submodules or what they contain. The examples directory has its own CMakeLists.txt, and the top level has a CMakeLists.txt plus a cmake directory, so CMake is the build system the repository is organised around. The README does not state a minimum CMake version, a compiler version, or a platform matrix.

The examples are what you run to see the library working. The repository lists an example named hello_universe, which is the smallest starting point, and an empty example for a bare skeleton. Other directories cover buttons, dialogs, menus, notebook, popups, list, layout, icons_list, status_bars, custom_control, child_window, drop_file, simple_animation, active_list, model, range_slider, scale, selection_list, list_arranger, sprite_sliders_and_knobs, basic_sliders_and_knobs, and doc_aspects. The README does not document the output path of those binaries, and it does not document which backend the default build selects. The Setup and Installation page linked from the README is the place to check for platform-specific prerequisites, because the README itself gives none.

The pre-1.0 status is a real constraint, not a disclaimer

The README is unusually direct: Elements is "still very much in flux", the API and code are "still undergoing continuous changes", and the project is "not yet production ready". It immediately softens that by saying the library is already usable, but the constraint stands. If your project needs a stable interface that will not shift between minor versions, this is the wrong tool right now, and no amount of enthusiasm about the syntax changes that.

The backend situation compounds it. The March 2024 news entry moved the Cairo backend back to master and described the Skia backend as still needing testing and work. Two backends with different maturity levels means a bug report or a workaround you find may not apply to the backend you chose. The README does not document a migration path between them.

There is also the documentation gap. The README lists four documentation links (Gallery, Setup and Installation, Design Aspects, Layout) and says documentation is work in progress. Several things a newcomer would want are simply absent from the repository text: no published install command sequence, no stated default backend, no documented rollback or versioning policy, and no release history. The recent releases field is empty, so there is no tagged version to pin against. Budget for reading examples instead of documentation.

How Elements differs from Qt and Dear ImGui

The closest comparison is Qt. Qt gives you a mature, long-supported toolkit with a visual designer, a large widget set and a versioning policy you can plan around. Elements gives you a small C++20 library with no visual editor by design, where the interface lives in the same language as the rest of your code. The trade is maturity and breadth for a smaller surface and a syntax that some C++ programmers find more direct. If your team already has Qt skills and a shipping schedule, Elements is not a drop-in substitution.

The other comparison is Dear ImGui, the immediate-mode GUI library common in tools and engines. Both are embeddable and both avoid a designer tool, but the model differs: immediate mode redraws the interface every frame from code that runs each frame, while Elements builds a declarative element tree that the library retains and walks. That distinction matters for how you structure state and how much work happens per frame. The README does not compare Elements to either library, so this is a design-level difference rather than a documented claim.

What neither alternative offers in the same way is the plugin-host story. Elements explicitly does not own the event loop and names VST and AU as hosts it co-exists with. If you are building an audio plugin and need a GUI that survives inside someone else's loop, that is the reason to look here first.

Licence, maintenance and what an upgrade costs you

Elements is distributed under the MIT License. The README states this twice, in the introduction and in the copyright footer, and links to the Open Source Initiative page for the licence text. MIT is permissive and non-viral, so it does not require you to open your own source. The repository metadata does not carry a licence identifier, so if your legal review needs a machine-readable SPDX field, that field is missing and the README and LICENSE file are your evidence. This is not legal advice; check the actual licence file in the repository.

On maintenance, the last push to the default branch was on 2026-09-23, and the repository is not archived. The README's own status section is the more useful signal for planning: it describes continuous API change and a pre-1.0 state, and the news entry is dated March 28, 2024. With no tagged releases, an upgrade means moving to a commit, and the README does not document a rollback procedure or a compatibility policy. The practical cost is that you should expect to read diffs rather than changelogs, and that any internal wrapper you write around the DSEL is your own insurance against churn.

Editorial conclusion

Adopt Elements if you are writing C++20 and want the interface described in the same translation units as the logic, or if you need a GUI that lives inside a VST or AU host without owning the event loop. Do not adopt it if you need a frozen API, a visual editor, or a documented installation path that does not change under you; the README states the API and code are still undergoing continuous changes. Before committing, build the examples directory to confirm your toolchain, and check whether the Cairo or Skia backend matches what you intend to ship.

Frequently asked questions

What is cycfi/elements?

It is a C++ GUI library written with modern C++20 features, offering a declarative interface through a domain specific embedded language for constructing GUI elements. The README describes it as lightweight, fine-grained, resolution-independent and extremely modular, and it is distributed under the MIT License.

How do I install cycfi/elements?

The README links to a Setup and Installation page and says documentation is a work in progress, so it does not publish an install command. The repository ships a top-level CMakeLists.txt and an examples directory, which is the path to a working build.

Is cycfi/elements production ready?

The README states that Elements is still very much in flux, that the API and code are still undergoing continuous changes, and that it is not yet production ready. It adds that the library is already in a very usable form.

Which rendering backend does cycfi/elements use?

The March 28, 2024 news entry states that the Cairo-based backend was brought back into the fold and is the master branch again, while the Skia backend version is still in active development and needs testing, particularly around how Skia is integrated.

Can cycfi/elements be used inside an audio plugin?

The README states that Elements is embeddable, does not own the event loop, and can co-exist with components within a plugin host such as VST and AU. It also says porting to a new host target requires porting only a few files.

Official sources

  1. cycfi/elements on GitHub
  2. Issues
  3. Project website
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cycfi-elements.svg)](https://hysenlabs.com/projects/cycfi-elements)