Tauri lets you build desktop apps using web technologies (HTML, CSS, JS) with a Rust backend. Unlike Electron, it uses the OS webview — so your app binary is 600KB instead of 150MB.
Why Tauri?
- Tiny bundles — 600KB vs Electron's 150MB
- Low memory — uses OS webview, not bundled Chromium
- Rust backend — secure, fast, native system access
- Any frontend — React, Vue, Svelte, plain HTML
- Cross-platform — Windows, macOS, Linux from one codebase
Quick Start
# Prerequisites: Rust + Node.js
cargo install create-tauri-app
cargo create-tauri-app my-app
cd my-app
# Dev mode
cargo tauri dev
# Build distributable
cargo tauri build
IPC API (Frontend ↔ Rust)
Rust Commands (Backend)
// src-tauri/src/lib.rs
use tauri::command;
#[command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[command]
async fn read_file(path: String) -> Result<String, String> {
std::fs::read_to_string(&path)
.map_err(|e| e.to_string())
}
#[command]
async fn save_data(key: String, value: String) -> Result<(), String> {
// Access database, file system, OS APIs...
Ok(())
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, read_file, save_data])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
JavaScript (Frontend)
import { invoke } from '@tauri-apps/api/core';
// Call Rust from JavaScript
const greeting = await invoke('greet', { name: 'World' });
console.log(greeting); // "Hello, World! You've been greeted from Rust!"
// Read file from filesystem (via Rust)
const content = await invoke('read_file', { path: '/tmp/data.txt' });
// Save data
await invoke('save_data', { key: 'theme', value: 'dark' });
Tauri Plugins (Built-in APIs)
import { open, save } from '@tauri-apps/plugin-dialog';
import { readTextFile, writeTextFile } from '@tauri-apps/plugin-fs';
import { sendNotification } from '@tauri-apps/plugin-notification';
// File dialog
const file = await open({ filters: [{ name: 'Text', extensions: ['txt', 'md'] }] });
const content = await readTextFile(file);
// Save dialog
const savePath = await save({ defaultPath: 'output.txt' });
await writeTextFile(savePath, 'Hello from Tauri!');
// System notification
sendNotification({ title: 'Tauri App', body: 'Task completed!' });
Event System
// Rust: emit event to frontend
#[command]
async fn start_process(app: tauri::AppHandle) -> Result<(), String> {
for i in 0..100 {
app.emit("progress", i).unwrap();
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
}
Ok(())
}
import { listen } from '@tauri-apps/api/event';
// Frontend: listen for events from Rust
const unlisten = await listen('progress', (event) => {
console.log(`Progress: ${event.payload}%`);
});
Size Comparison
| Tauri | Electron | Flutter | |
|---|---|---|---|
| Hello World | 600 KB | 150 MB | 20 MB |
| RAM usage | 30 MB | 150 MB | 80 MB |
| Startup | 0.2s | 1.5s | 0.5s |
| Renderer | OS WebView | Chromium | Skia |
Resources
Building desktop or web apps? I create custom tools and data solutions. Check my Apify actors or email spinov001@gmail.com.
Top comments (0)