Rust GUI frameworks
2024 ✔ 1.0 · Stable milestone Framework 2026: Mobile and plugin system, mainstream
28

Tauri 2.0

Desktop, then mobile, with a plugin system.

Tauri 2.0 (2 October 2024) added mobile (iOS and Android) and replaced the global allowlist with a permissions and capabilities model. The Rust entry point changes shape: the app is a library with a run function, and a mobile_entry_point attribute lets the same code start as an Android activity or an iOS app. Desktop just calls run from main.

tauri-app/src/lib.rs ✔ compiled · raw-window-handle 0.6, serde 1 · rustc 1.95.0
use book_error::{Context, Result};
use tauri::Manager;

// A command: Rust code the web frontend can call by name.
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {name}! (from Rust)")
}

fn try_run() -> Result<()> {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .setup(|app| {
            // The webview window is a native window too: it exposes the same
            // raw handles any renderer would want. Setup hooks return a boxed
            // error, and our `Error` converts into one, so `?` just works.
            use raw_window_handle::HasWindowHandle;
            let window = app.get_webview_window("main").context("no window labelled `main`")?;
            let _handle = window.window_handle()?;
            Ok(())
        })
        .run(tauri::generate_context!())?;
    Ok(())
}

// Mobile entry points cannot return a Result, so this is the one place an
// error is finally reported and turned into a non-zero exit.
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    if let Err(err) = try_run() {
        eprintln!("{}", err.report());
        std::process::exit(1);
    }
}

Permissions are declared per window in a capability file. Each capability names which windows it applies to and which plugin permissions they hold. The build script validates it at compile time, so an unknown permission is a build error. This is the exact file used in the project that compiled the Rust above.

tauri-app/capabilities/default.json ✔ compiled · raw-window-handle 0.6, serde 1 · rustc 1.95.0
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "What the main window may do",
  "windows": ["main"],
  "permissions": ["core:default", "core:window:allow-set-title"]
}

Tauri has 680 dependent crates and the largest download count of any framework in the book. 2.0 is a declared-stable release, so it carries the green badge, but the line is moving again: a 3.0 alpha is already on crates.io as of September 2026. Going from 1.0 to 2.0 took about two and a half years.

Tauri 2.0 announcement; crates.io: tauri 2.0.0, 2024-10-02. Source →