Library / SDK
marc2332/freya avatar
marc2332/freya

Freya: a declarative native GUI library for Rust

Cross-platform native GUI library for 🦀 Rust

3,190 stars140 forksRustMIT

At a glance

What is it?
Freya builds native desktop, web and Android interfaces from Rust functions and components. The 0.5 line is still at release candidate, so most readers should start on 0.4 or on the rc and expect churn.
Who is it for?
Use Freya if you already write Rust and want a declarative, component-based interface that renders natively with Skia instead of shipping a webview. Avoid it if you need a stable 0.5 API today, or if you want the widest widget ecosystem: egui and Iced have longer release histories and more third-party material.
Can I use it commercially?
Yes. MIT 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 received new commits within the last day.
What is it written in?
Mainly Rust, 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

What Freya is for, and who should pick it

Freya is a cross-platform, native, declarative GUI library for Rust. The problem it addresses is the usual one for Rust desktop work: a systems language with no bundled widget toolkit, and a choice between binding to C libraries or drawing your own. Freya takes the second route. It renders through Skia, the same 2D graphics library behind Flutter and Chrome, and it exposes a component model rather than an immediate-mode loop.

The audience is Rust developers building tools, editors, dashboards or internal apps who want native rendering and are willing to write UI in Rust rather than HTML. The repository layout confirms the scope: a workspace with freya-core, freya-winit, freya-components, freya-router, freya-i18n, freya-devtools, freya-markdown, freya-terminal, freya-code-editor, freya-camera, freya-webview, freya-android and freya-web. That is a platform project, not a thin wrapper.

The trade-off is that you inherit a young API. The most recent release is v0.5.0-rc.7, dated 2026-09-21, and the three releases before it are all release candidates. If your project ships this quarter and cannot absorb breaking changes, the stable line is freya = "0.4".

Components, state and the re-render model

The README describes the model plainly: components can hold internal state or subscribe to shared state, and they produce UI as output. Any type implementing the Component trait can be a component; the root app component can be a plain function.

State is read and written through handles. The counter example uses use_state with an initial closure, then count.read() to render and *count.write() += 1 inside a button handler. That is a signal-style API: the component re-renders when the state it depends on changes, and you do not call a redraw function yourself. The same pattern appears in the animation example, where use_animation returns a handle with start() and reverse() methods and the current value is read with animation.read().

Two design choices stand out. First, layout and styling are builder methods on elements: rect().width(Size::fill()).height(Size::percent(50.)).center().spacing(8.0). Second, text editing is not an input widget but a set of primitives. The rich text example wires use_editable, use_focus, and a ParagraphHolder, then forwards mouse and keyboard events into editable.process_event with EditableEvent variants such as Down, Move, Release, KeyDown and KeyUp. That is more code than an <input> tag. It is also the reason the crate can offer paragraph-level selection and cursor control at all.

Installing Freya and running a first example

Freya is published on crates.io. The README gives three dependency lines: the stable release, the next release, and the main branch. Pick one and add it to Cargo.toml.

toml
freya = "0.4"

If you want the code the documentation currently describes, including the animation and editable APIs, use the release candidate instead.

toml
freya = "0.5.0-rc.7"

To try the bundled examples rather than your own app, clone the repository. The README warns that the repo uses git submodules and that cloning without --recurse-submodules will make the examples fail to compile.

bash
git clone --recurse-submodules https://github.com/marc2332/freya.git
cd freya
cargo run --example counter

If you already cloned without submodules, the README gives the fix: run git submodule update --init --recursive. Before any of this, the README points to a Development Setup page in the docs.rs documentation, and says to make sure that setup is ready. Expect a window with a counter and two buttons, Increase and Decrease, matching the code in the README. The README also notes that Windows users on the windows-gnu target may hit compile errors and links issue 794; that target is worth avoiding until you have read the thread.

Where Freya is the wrong tool

The release cadence is the first limitation. A library whose newest tag is a release candidate means the API you read about today may move. The README itself presents 0.4 and 0.5.0-rc.7 as separate choices, which tells you the two are not interchangeable. Code written against the animation or editable examples will not necessarily compile against 0.4.

The second limitation is ecosystem depth. Freya ships a solid set of built-in components, from Button, Switch and Slider to VirtualScrollView, Calendar and ColorPicker, but the README does not claim third-party widget libraries, and the repository gives no sign of a plugin registry beyond the crates in the workspace. If your app needs a mature data grid, a charting suite or a native menu bar, you will be building it.

The third is platform coverage. The topics list android, desktop and web, and the workspace contains freya-android and freya-web, but the README's own instructions are desktop-oriented: clone, then cargo run --example counter. The web demo in the justfile is a separate pipeline that builds for wasm32-unknown-emscripten, copies the .js and .wasm into website/public/demo, and is not presented as a general deployment path. If web is your primary target, treat it as unproven for your use case.

Freya against egui and Iced

The closest alternatives in Rust are egui and Iced, and the difference is architectural rather than cosmetic. egui is immediate mode: you rebuild the UI every frame from current state, which makes small tools quick to write and keeps state management simple, but it gives you less structure for large screens and no component abstraction of the kind Freya uses.

Iced is the nearer comparison. It is also declarative, but it is built around an Elm-style architecture: a message enum, an update function, and a view function, with the framework owning the state transitions. Freya instead keeps state inside components through handles like use_state and use_animation, closer to the hooks model in React. If your team already thinks in reducers and messages, Iced will feel familiar; if it thinks in components with local state, Freya will.

Freya's other differentiator is the rendering layer. Skia gives it real text layout, shadows, and paragraph-level editing, which is why the rich text example can implement selection and cursor movement in user code. That is a heavier dependency than a pure-Rust renderer, and it is the reason the crate can target desktop, web and Android from one codebase.

Licence, maintenance and the cost of upgrading

Freya is MIT licensed. That is a permissive licence, so you can use it in closed-source products provided you keep the copyright notice and licence text with the distribution. The repository also has a separate LICENSE.md file, and the workspace includes crates from other authors, so check each dependency you pull in rather than assuming the top-level licence covers everything. This is not legal advice; if your organisation has a licence review process, run the dependency tree through it.

On maintenance, the last push to the default branch was on 2026-09-23, and the repository is not archived. Releases are frequent: three candidates landed within two weeks in September 2026. That pace is the upgrade cost. A project pinned to 0.4 that wants a 0.5 feature will have to migrate, and the README offers no migration guide. The justfile shows the project's own discipline, with formatting, clippy with -D warnings, cargo audit, and nextest runs across the workspace, and the toolchain is pinned in rust-toolchain.toml and rust-toolchain-nightly.toml. Note that the nightly toolchain is used for formatting and documentation, so a contributor workflow may need both.

Frequently asked questions

The questions below come from search data and from what a new user of this crate would reasonably ask. Only questions that the repository can answer are included.

Editorial conclusion

Use Freya if you already write Rust and want a declarative, component-based interface that renders natively with Skia instead of shipping a webview. Avoid it if you need a stable 0.5 API today, or if you want the widest widget ecosystem: egui and Iced have longer release histories and more third-party material. Before committing, run the counter example, check whether you can live on freya = "0.4" or must track 0.5.0-rc.7, and confirm the Development Setup page covers your platform. Also decide early whether your app needs the freya-* workspace crates listed in Cargo.toml or only the main freya crate.

Frequently asked questions

How do I install Freya in a Rust project?

Add freya to your Cargo.toml dependencies. The README gives freya = "0.4" for the latest stable release, freya = "0.5.0-rc.7" for the next release, and a git dependency on the main branch as a third option.

How do I use Freya to build an app?

You write a root app function that returns an element, and use components with state handles such as use_state. The README's counter example reads state with count.read(), mutates it with *count.write(), and attaches on_press handlers to Button components.

How do I run the Freya counter example?

Clone the repository with git clone --recurse-submodules, change into the freya directory, and run cargo run --example counter. The README warns that cloning without --recurse-submodules will make the examples fail to compile.

Why do the Freya examples fail to compile after cloning?

The repository uses git submodules, and the README states that cloning without --recurse-submodules breaks the examples. If you already cloned, run git submodule update --init --recursive to fetch them.

Which Freya version should I depend on?

The README lists freya = "0.4" as the latest stable release and freya = "0.5.0-rc.7" as the next release. The most recent published tags are all release candidates, so 0.5 APIs may still change.

Official sources

  1. License: MIT
  2. marc2332/freya on GitHub
  3. Project website
  4. README
  5. Releases
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/marc2332-freya.svg)](https://hysenlabs.com/projects/marc2332-freya)