Tauri
Build desktop apps with a web frontend and Rust backend - lightweight shells, typed IPC, and OS integration.
Search across all documentation pages
Build desktop apps with a web frontend and Rust backend - lightweight shells, typed IPC, and OS integration.
#[tauri::command]
fn read_text(path: String) -> Result<String, String> {
std::fs::read_to_string(path).map_err(|e| e.to_string())
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![read_text])
.run(tauri::generate_context!())
.expect("error running tauri");
}When to reach for this:
use serde::Serialize;
use tauri::State;
use std::sync::Mutex;
#[derive(Default)]
struct AppState {
counter: Mutex<i32>,
}
#[derive(Serialize)]
struct CounterResponse {
value: i32,
}
#[tauri::command]
fn increment(state: State<AppState>) -> CounterResponse {
let mut c = state.counter.lock().unwrap();
*c += 1;
CounterResponse { value: *c }
}
fn main() {
tauri::Builder::default()
.manage(AppState::default())
.invoke_handler(tauri::generate_handler![increment])
.run(tauri::generate_context!())
.expect("tauri run failed");
}What this demonstrates:
dist/ folder.| Aspect | Tauri | Electron |
|---|---|---|
| Runtime size | System WebView | Bundled Chromium |
| Backend | Rust | Node.js |
| IPC | Commands/events | Node integration |
async commands for IO-heavy work.unwrap in commands - panics kill app. Fix: return Result to frontend.| Alternative | Use When | Don't Use When |
|---|---|---|
| Electron | Need Chromium-specific APIs | Binary size critical |
| egui | Pure Rust UI, no HTML | Rich marketing site UI required |
| iced | Native Rust widgets | Team only knows React |
| Flutter desktop | Design system in Dart | Rust backend mandate |
Tauri 2 uses capabilities-based permissions - migrate configs when upgrading templates.
Any static build - React, Svelte, Vue, or plain TS. Rust does not dictate UI framework.
import { invoke } from '@tauri-apps/api/core' then invoke('increment').
Spawn Tokio tasks in setup hook; emit events to frontend with app.emit.
Built-in updater plugin with signed artifacts - see packaging page.
Tauri mobile targets exist - separate from desktop chapter but shares command model.
Unit test Rust commands; Playwright on WebView for E2E where feasible.
Never embed API keys in frontend bundle - fetch from Rust command reading env or OS keychain.
See State & Architecture.
Native Integration for dialogs and notifications.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 19, 2026