Tauri: the webview shell
Ship a web UI with a Rust backend and the system webview.
Tauri does not draw your UI. It pairs a Rust backend with the operating system's webview: WKWebView on macOS, WebView2 on Windows, WebKitGTK on Linux. No browser is bundled, so apps are small. The Rust side exposes commands the web frontend can call by name. This is the full backend for a tiny app.
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);
}
} Note that run itself returns nothing, because mobile entry points cannot return a Result. It calls a fallible try_run, prints the error chain once and exits non-zero. The lockfile shows how the layers divide: tauri-runtime-wry brings in wry (the webview wrapper) and tao (windows). There is no winit, because tao is Tauri's fork of it. The frontend can be anything that runs in a browser: plain JavaScript, Svelte (this book is built with it), or a Rust framework such as Leptos or Yew compiled to WebAssembly.
import { invoke } from '@tauri-apps/api/core';
// Calls the Rust `greet` command by name and awaits the result.
const message = await invoke('greet', { name: 'Ada' });
console.log(message); // "Hello, Ada! (from Rust)" The Rust snippet was compiled as a real Tauri 2 project, including its build script, config and capability file. The JavaScript shows the matching call and is not compiled. Measured by total downloads (about 33 million) Tauri is the most downloaded framework here, ahead of egui's 25 million, with 680 dependent crates. Its 1.0 and 2.0 releases each have a page of their own.