# Slint: a declarative GUI toolkit for Rust, C++, JavaScript and Python

> Slint compiles .slint markup to native code and binds it to business logic in four host languages. It suits embedded and desktop work where Qt's footprint or a web view's overhead is the wrong fit, and the licence choice is the first thing to settle.

**slint-ui/slint** — Slint is an open-source declarative GUI toolkit to build native user interfaces for Rust, C++, JavaScript, or Python apps.

- Repository: https://github.com/slint-ui/slint
- Website: https://slint.dev
- Stars: 24,012 · Forks: 1,011
- Language: Rust
- License: NOASSERTION
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/slint-ui-slint

## The gap Slint fills between Qt and a web view

Desktop and embedded UI work usually forces a choice between two unsatisfying options. A heavyweight native toolkit gives you real widgets and real performance but drags in a large dependency tree and a C++ build system. A web view gives you fast iteration and CSS but costs you a browser engine's memory and a JavaScript bridge on every property change. Slint takes a third position: a small declarative language compiled ahead of time into the host language, with a runtime that the README describes as laying components, elements, items and properties out in a single memory region to reduce allocations.

The intended audience is narrow and specific. The README lists embedded systems first, then desktops and mobile platforms, and the repository ships example directories for MCU board support and Embassy-based microcontrollers alongside a desktop gallery. If you are building a settings panel on a Raspberry Pi, a kiosk UI, or an instrument panel that has to run without a browser, this is the target. If you are building a content-heavy web application, it is not.

The README also states the design goals behind the name: scalable, lightweight, intuitive, native. Those are goals, not measurements, and the README offers no numbers to back them. Treat the lightweight claim as a design intention you should verify against your own binary size and memory budget.

## How .slint markup becomes native code

The mechanism is a compiler, not a runtime parser. According to the README, .slint files are compiled ahead of time, and expressions inside them are treated as pure functions the compiler can optimize. The README gives one concrete example of that optimization: the compiler may inline properties and remove those that are constant or never change. The stated compiler phases are lexing, parsing, optimization and code generation.

Code generation is per-language. The README says the C++ generator produces a C++ header file, the Rust generator produces Rust code, and an interpreter is included for dynamic languages. That interpreter is what the JavaScript and Python bindings lean on, and the README marks both of those bindings as Beta while the C++ and Rust APIs are presented without that qualifier. The distinction matters if you are choosing a host language for a long-lived product.

At runtime the engine owns the properties declared in the markup. Rendering backends are chosen at compile time, and the README names three: femtovg, which uses OpenGL ES 2.0, skia, which uses the Skia library, and a software renderer. The workspace members confirm this split: internal/renderers/femtovg, internal/renderers/skia, internal/renderers/software and internal/renderers/anyrender are separate crates, and the backends are separate again in internal/backends/winit, internal/backends/qt, internal/backends/linuxkms and internal/backends/android-activity. Picking a renderer is a build-time decision, so it is worth making before you write much UI code.

## Installing Slint and rendering a first window in Rust

The README points to per-language directories under api/ for setup, and to a docs/building.md file for building the project itself. For application work you do not build Slint from source; you add the crate and let Cargo fetch it. The Rust binding lives at api/rs/slint and the README links a getting-started template for it.

Then write the UI in a .slint file. The README's own Hello World example is this one, and it is worth typing rather than paraphrasing because it shows how properties bind to parent geometry.

```slint
export component HelloWorld inherits Window {
    width: 400px;
    height: 400px;

    Text {
       y: parent.width / 2;
       x: parent.x + 200px;
       text: "Hello, world";
       color: blue;
    }
}
```

What you should see when it runs is a 400 by 400 window containing a single blue line of text. The Text element's y coordinate is bound to the parent's width divided by two, which is a binding rather than a fixed value: resize the window and the text moves. That is the core idea of the language in one line.

To wire it into a Rust program, the api/rs/slint README and the docs site cover the macro and build-script paths. The repository also ships a viewer tool under tools/viewer, and the README mentions a Live Preview with editor integrations, which is the fastest way to iterate on a .slint file without recompiling the host program. Editor integration is in the editors/ directory, including a Zed extension in the workspace members.

## Where the ahead-of-time compiler costs you

Compiling the UI ahead of time is the source of Slint's runtime efficiency and also its main friction. Anything you want to change about the interface requires a rebuild of the host program, because the markup is not interpreted at runtime in the compiled path. The README does mention an interpreter for dynamic languages, and there is a separate api/wasm-interpreter crate, so runtime interpretation exists as a mode. But the primary story the README tells is compilation, and that is the mode most users will be in.

The language bindings are not at equal maturity. The README labels JavaScript/NodeJS and Python as Beta, while C++ and Rust get no such label. If your team's strength is Python, you are adopting a beta surface, and the README does not state what the beta label means for API stability or for the timeline to a stable release. That is a real gap in the documentation, not a detail.

Licensing is the other cost, and it is not incidental. The repository metadata reports the licence as NOASSERTION, which tells you nothing useful. The header of the root Cargo.toml is explicit, listing three options: GPL-3.0-only, LicenseRef-Slint-Royalty-free-2.0 and LicenseRef-Slint-Software-3.0. A three-way choice including a royalty-free tier and a separate software licence tier means the licence question is a commercial decision, not a formality. The repository also carries a REUSE.toml and a LICENSES directory, and the README shows a REUSE compliance badge. Read LICENSE.md and the LICENSES directory before you build a product on this. Nothing here is legal advice, and the terms of the royalty-free and software licences are not reproduced in the repository files.

## Slint against Qt, egui and Tauri

The most direct comparison is Qt. Qt is a mature C++ framework with a widget set that has been built up over decades, a designer tool, and its own declarative language in QML. Slint is younger and its stated goal is a smaller resource footprint, which is why the embedded examples exist. The difference in approach is where the UI description is compiled: Slint compiles .slint into the host language ahead of time and can inline and drop constant properties, whereas QML is evaluated by a JavaScript-driven engine at runtime. If you already have a Qt codebase and a commercial Qt licence, moving to Slint means rewriting the UI layer and taking on a different licence model. If you are starting from nothing on a device with tight memory, that rewrite is the point.

egui is the closer comparison for Rust developers. egui is immediate mode: you rebuild the interface every frame from Rust code, and there is no separate markup file or code generator. Slint is retained mode with a declarative markup language and a compiler. Immediate mode is simpler to reason about for tool-like interfaces and avoids a build step for the UI, while a declarative compiled language is easier to hand to a designer and, per the README, lets designers work in parallel with developers. The README also mentions a Figma to Slint plugin, which is a workflow egui does not offer.

Tauri takes a different route entirely: the interface is web technology rendered in a system web view, and Rust sits behind it as the backend. That gives you the entire web ecosystem for UI work, at the cost of a web engine in your binary and a serialization boundary between the front end and the Rust side. Slint has no web view in that sense, though it does target the web through WebAssembly, and the README lists several WebAssembly demos including a printer demo and a slide puzzle. If your UI is already React, Tauri is the shorter path. If you want one UI definition to run on a microcontroller and a desktop without a browser, that is Slint's argument.

## Release cadence and what upgrading costs

The release history in the repository shows v1.17.0 on 2026-06-24, v1.17.1 on 2026-07-07 and v1.18.0 on 2026-09-16, with the last push to master on 2026-09-20. That is a steady minor-release rhythm with patch releases in between, and the README states that Slint follows a stable 1.x API and evolves without breaking your code. The 1.x stability promise is the relevant fact for upgrade planning: the project's stated intent is that a version bump within 1.x does not require you to rewrite the UI.

What the repository does not give you is a migration guide. There is a CHANGELOG.md at the repository root, and that is where you should look for the specific changes between 1.17 and 1.18, but its contents are not reproduced in the README. There is no documented deprecation policy beyond the 1.x stability statement, and the README does not document rollback procedures if a release causes a regression. If you pin to a specific version and a patch release breaks a rendering path, the repository's issue tracker and the changelog are your only sources; plan for that by pinning exact versions rather than using a caret range in production.

The workspace layout is worth knowing for build cost. The root Cargo.toml explains that the workspace contains only the library and tool crates developers work on, while examples, demos, integration tests and the material UI library each live in their own workspace so that rust-analyzer and cargo do not have to load roughly seventy crates that pull in the slint! proc-macro. All workspaces share the repository target directory and identical profile settings, so common artifacts build once. That is a deliberate answer to a real problem, and it tells you the full build is heavy enough that the maintainers split it.

## Conclusion

Adopt Slint when you want one .slint file to drive a native UI on a desktop machine or a microcontroller and you are willing to pick a licence tier before shipping. Skip it if your team is committed to a web-based UI stack, or if you need a widget set as broad as Qt's. Before writing code, read LICENSE.md and the LICENSES directory: the crate metadata says NOASSERTION, while Cargo.toml lists GPL-3.0-only, LicenseRef-Slint-Royalty-free-2.0 and LicenseRef-Slint-Software-3.0 as a choice, and only you can decide which of those three you can live with.

## FAQ

### Is Slint open source?

Yes. The repository is public and the README describes Slint as an open-source declarative GUI toolkit. Note that the repository metadata reports the licence as NOASSERTION, while the root Cargo.toml header lists three options: GPL-3.0-only, LicenseRef-Slint-Royalty-free-2.0 and LicenseRef-Slint-Software-3.0.

### Is Slint free to use?

That depends on which of the three licence options you take. The root Cargo.toml header names GPL-3.0-only, LicenseRef-Slint-Royalty-free-2.0 and LicenseRef-Slint-Software-3.0, and the repository carries a LICENSES directory and a LICENSE.md. The terms of the royalty-free and software licences are not reproduced in the repository files.

### How does Slint compare to Qt?

Both are native GUI toolkits with a declarative UI language, but Slint compiles .slint markup ahead of time into Rust, C++ or another host language and can inline or drop constant properties, while Qt's QML is evaluated at runtime. Slint's README states a goal of minimal memory and processing power, which is why it ships embedded examples for boards like STM32 and RP2040.

### How does Slint compare to egui?

egui is immediate mode, so the interface is rebuilt from Rust code every frame with no separate markup file. Slint is retained mode with a declarative .slint language compiled ahead of time, which the README says lets designers work in parallel with developers and supports a Figma to Slint plugin.

## Sources

- [Issues](https://github.com/slint-ui/slint/issues)
- [Project website](https://slint.dev)
- [README](https://github.com/slint-ui/slint/blob/master/README.md)
- [Releases](https://github.com/slint-ui/slint/releases)
- [slint-ui/slint on GitHub](https://github.com/slint-ui/slint)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/slint-ui-slint
