Relm4 for Rust GTK4 desktop applications
Build truly native applications with ease!
At a glance
- What is it?
- Relm4 is a Rust GUI library built on gtk4-rs and inspired by Elm. It gives developers message-driven components, declarative views, optional libadwaita support, and version-specific GNOME integration.
- Who is it for?
- Adopt Relm4 when building a native GTK4 desktop application in Rust and you want Elm-style component organization. Do not choose it for an interface that does not use GTK4 or when your deployment process cannot supply the required GTK environment.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- Relm4/Relm41,995 ★ · +6
| Repository | 2026-10-17 | 2026-11-07 |
|---|---|---|
| Relm4/Relm4 | 2k | 2k |
6 Stars in the last 21 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Relm4's Rust model for GTK4 interfaces
Relm4 addresses the problem of organizing native desktop GUI code in Rust when the underlying toolkit is GTK4. It is intended for developers who want a native GTK interface without moving application logic to another language, particularly those who find direct widget construction and callback management difficult to coordinate in larger programs.
Its central design comes from Elm. Application state is represented by a component model, user actions become typed messages, and a declarative view describes how the model maps to widgets. This arrangement gives interactions a visible route through the program. A button does not silently change unrelated application state. It sends a message, the component handles that message, and an observed view property reflects the updated model.
Relm4 does not hide GTK4 or replace its widget system. The README identifies `gtk4-rs` as the foundation and describes Relm4 as an idiomatic layer based on it. GTK orientations, margins, labels, windows, and property assignments remain visible in application code. Relm4 mainly changes how those pieces are declared and coordinated. The practical audience is therefore Rust developers building GTK4 applications who value component structure over a toolkit-independent interface API.
Components, messages, and Relm4 view generation
The README counter example exposes the architecture clearly. `App` contains one state field, `counter`, and the `Msg` enum contains two inputs, `Increment` and `Decrement`. The component is declared with `#[relm4::component]` and an implementation of `SimpleComponent`. Its associated types specify an initial value of `u8`, the message enum as input, and `()` as output.
The view is written with the `view!` macro. It declares a `gtk::Window`, a vertical `gtk::Box`, two `gtk::Button` widgets, and a `gtk::Label`. Each button connects its click signal to a `Msg` value. The label uses `#[watch]`, which ties its text to `model.counter`. During initialization, `view_output!()` converts the declared widget structure into the widgets returned as part of `ComponentParts`.
This is a more restrictive design than direct callback mutation because state changes pass through `update`. In the counter, `wrapping_add` and `wrapping_sub` handle the `u8` state. That choice allows values above the type's maximum to wrap instead of failing at compile time. It is suitable for a demonstration, but production code may need explicit bounds or a different integer type.
The separation also improves reviewability. View construction, initialization, and state transitions can be examined independently. The cost is reliance on Relm4 macros and a component lifecycle that application developers must learn before using the full example as a template.
Installing Relm4 alongside its GTK4 dependency
The README does not give operating-system-specific commands for installing GTK4. Instead, it directs readers to the linked gtk4-rs guide titled “How to install GTK4 and Rust.” Those system libraries must be present before a Relm4 application can be built. This is an important distinction from a pure Rust crate whose dependencies can all be fetched through Cargo.
For Cargo dependencies, the README gives the following package declarations:
# Core library
relm4 = "0.10"
# Optional: reusable components
relm4-components = "0.10"
# Optional: icons
relm4-icons = "0.10"The repository's workspace metadata describes version 0.11.0, Rust edition 2024, and a minimum Rust version of 1.93. It also declares workspace dependencies for `relm4`, `relm4-css`, `relm4-macros`, `relm4-icons`, `gtk4`, `libadwaita`, and `libpanel`. A project should check whether it is following the README's package line or building against the repository workspace before choosing exact versions.
The repository has no GitHub releases, so there is no release listing there to use as a version-selection guide. Its package metadata, `Cargo.lock`, and current documentation are the relevant project-specific references.
Creating a first Relm4 counter application
A first implementation can follow the state and message types documented in the README:
use gtk::prelude::*;
use relm4::prelude::*;
struct App {
counter: u8,
}
#[derive(Debug)]
enum Msg {
Increment,
Decrement,
}The component then implements `SimpleComponent` through the `#[relm4::component]` attribute. Its `view!` body creates the window and controls. Its `init` function constructs the initial model, calls `view_output!()`, and returns both through `ComponentParts`. Its `update` function matches each `Msg` and changes `counter`.
The program entry point is also short:
fn main() {
let app = RelmApp::new("relm4.example.simple");
app.run::<App>(0);
}Running a completed version should produce a small GTK window with Increment and Decrement buttons plus a label. The label begins with the initial value supplied to `run` and changes when either button sends its message. This is a real interactive path through the model, update logic, macros, and GTK4 widgets rather than a static rendering demonstration.
For a production application, developers should replace the counter state with domain-specific values and expand the message enum. The repository's `examples/` directory shows possible next steps, including components, actions, data binding, factories, menus, drag and drop, drawing, message streams, multiple windows, and navigation split views.
Selecting Relm4 macros and GNOME feature flags
The `macros` feature is enabled by default and re-exports `relm4-macros`. This supports the declarative syntax used by the counter example. Disabling it would remove the default macro path, so projects using `#[relm4::component]`, `view!`, or the related macros need to account for that dependency explicitly.
Relm4 also offers `libadwaita` and `libpanel` features for improved integration with their respective GNOME libraries. Separate features named `gnome_50` through `gnome_42` enable matching version feature flags across dependencies. The README marks `gnome_42` as enabled by default. It introduces this section by calling them four feature flags but then lists more than four entries. That inconsistency makes the feature table, rather than the introductory sentence, the more useful reference.
The appropriate feature depends on the SDK and libraries targeted by the application. Enabling `gnome_50` says that dependency version features should match the GNOME 50 SDK, while `gnome_42` serves a different target. The README does not provide a detailed compatibility matrix for every flag, so an application with strict packaging requirements should verify the selected feature against its dependency lockfile and target environment.
The optional ecosystem crates add separate adoption choices. `relm4-components` supplies reusable components, `relm4-icons` supplies icons, `relm4-macros` supplies macros, and `relm4-template` provides a starter application template in the Flatpak package format.
Limits of Relm4's GTK4 foundation
Relm4 is the wrong choice when the application cannot depend on GTK4. Because it is based on gtk4-rs and explicitly lists GTK4 as a dependency, it does not provide a toolkit-independent rendering layer. Web embedding, proprietary native toolkits, and non-GTK embedded interfaces would require a different foundation.
It can also add unnecessary structure to a very small gtk4-rs program. Direct gtk4-rs code can be more appropriate when the interface has a small state model and straightforward event handling. Relm4 becomes more defensible as the number of modeled states, messages, child components, and observed properties grows. Its advantage is organizational rather than a claim that it removes every GTK complexity.
Relm4 does not solve deployment by itself. The README links to the GTK4 installation guide and lists a Flatpak template, but it does not document a complete Windows, macOS, or Linux packaging procedure for an arbitrary application. Native look, runtime libraries, and platform behavior still depend on the selected GTK environment. The optional GNOME features may improve fit with GNOME releases, but they do not make every distribution deployment identical.
Direct gtk4-rs and multi-component Relm4 designs
The closest documented comparison is direct use of gtk4-rs. The README says that gtk4-rs already provides what is needed for modern, cross-platform GTK applications. Relm4 builds on that foundation with Elm-inspired components and macros. A direct gtk4-rs design exposes GTK APIs immediately and leaves component structure to the application. Relm4 instead defines a model, message type, update function, generated view, and lifecycle through `SimpleComponent` or another component abstraction.
This difference matters when application state has meaningful transitions. Relm4's `Msg` enum documents accepted inputs, while `update` creates one location for state changes. Direct gtk4-rs remains a practical choice for thin wrappers, short-lived tools, or applications that already have an established widget organization.
For larger applications, Relm4 also offers patterns beyond the simple component. The `examples/` directory includes data binding, component composition, factories, asynchronous factories, message brokers, and navigation views. Those patterns are evidence of intended architecture, not documentation of runtime performance. The README does not publish comparative benchmarks, so adoption should not be justified by an unsupported speed claim.
Maintenance status, licenses, and upgrade boundaries
The repository is not archived. Its last push was on 2026-10-13. That date records recent repository activity, but it does not establish release cadence because the repository has no GitHub releases. Version planning must therefore use package versions, dependency metadata, and change documentation rather than a GitHub release timeline.
The workspace package metadata states `Apache-2.0 OR MIT`, and the repository contains `LICENSE-APACHE` and `LICENSE-MIT`. Applications need to review the actual license files and the licenses of GTK and other dependencies as part of distribution review. This paragraph identifies the project's stated licensing terms and does not replace legal advice.
Upgrades may touch more than one version choice. The workspace uses resolver 3, edition 2024, Rust 1.93, and specific GTK4, libadwaita, and libpanel versions. An application also chooses a GNOME version feature and may add `relm4-components` or `relm4-icons`. A coordinated crate upgrade, SDK retargeting, or packaging change is therefore a project-level task rather than a blind edit to one dependency line.
Editorial conclusion
Adopt Relm4 when building a native GTK4 desktop application in Rust and you want Elm-style component organization. Do not choose it for an interface that does not use GTK4 or when your deployment process cannot supply the required GTK environment. Verify the system dependencies, feature flags, Rust version, and application packaging path first. The workspace metadata specifies Rust 1.93 and package version 0.11.0, while the README dependency example still uses 0.10.
Frequently asked questions
What is Relm4 used for?
Relm4 is used to build native GTK4 desktop applications in Rust. It provides an Elm-inspired component model and declarative views on top of gtk4-rs.
Does Relm4 require GTK4?
Yes. The README states that Relm4 depends on GTK4 and links to the gtk4-rs GTK4 installation guide.
Which Rust version does Relm4 require?
The workspace metadata specifies Rust 1.93 as the minimum version and uses edition 2024. The README also displays a minimum Rust version badge.
Does Relm4 support libadwaita?
Yes. The `libadwaita` feature provides improved support for libadwaita, while separate GNOME version features select dependency versions for a target SDK.
Official sources
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.
[](https://hysenlabs.com/projects/relm4-relm4)Star history chart for your README
[](https://hysenlabs.com/projects/relm4-relm4)Was this useful?