What is Tauri

A detailed introduction to the Tauri framework covering what it is, the problems it solves, and its core advantages of security, small size, and architectural flexibility.

Tauri is a framework for turning web code into native desktop and mobile applications. You write your user interface with HTML, CSS, and JavaScript just like you would for a website, and Tauri wraps it inside a system-provided webview while giving you a Rust-powered backend that can access the file system, system tray, notifications, and any other operating system capability you need. The final result is a single, small binary — often just a few megabytes — that runs on Windows, macOS, Linux, Android, and iOS from one codebase.

This page unpacks what Tauri actually is, why it exists, and what makes it different from heavier alternatives. You will leave with a clear picture of the three core design pillars — security, minimal size, and a flexible architecture that adapts to your tools, not the other way around.

Definition and Purpose

Tauri is an open-source framework that lets you build cross-platform applications with a web frontend and a Rust backend. It does not bundle its own browser engine. Instead, it uses the webview that already exists on every modern operating system: WebKit on macOS and iOS, WebView2 on Windows, and WebKitGTK on Linux. On Android, it leverages the Android System WebView. This single decision is what makes Tauri apps so much smaller than alternatives that ship an entire Chromium runtime. For full details on the core concepts, see the Definition and Purpose guide.

The project started in 2020 and reached a stable 1.0 release in June 2022. Version 2.0, released in October 2024, added full mobile support and a refined security model. Tauri is governed by the Tauri Foundation, part of the Dutch non-profit Commons Conservancy, and is dual-licensed under MIT and Apache 2.0.

The problem Tauri solves is concrete. Before Tauri, if you wanted to build a desktop application with web technologies, the dominant option was Electron. Electron works, but every app bundles a complete Chromium browser engine, which means even a hello-world app weighs over 100 MB and runs a separate browser process for every instance. Tauri removes that overhead by trusting the operating system to provide the webview. The result is a desktop app that looks and behaves like a native window but has the development speed of web tooling, without the disk footprint or memory cost of an embedded browser.

Real applications in production include GitButler, a Git client that uses a React frontend and a Rust backend for all Git operations; Authme, a two-factor authenticator; and Clash Verge, a proxy management client. These are not tiny experiments — they are actively maintained tools that ship to thousands of users.

At a high level, a Tauri app consists of two pieces that communicate with each other:

+------------------------------------------+
|            Your Application              |
|                                          |
| +-----------------+ +------------------+ |
| | Frontend (UI)   | | Rust Backend     | |
| | HTML/CSS/JS     | | Native APIs      | |
| | React/Vue/etc.  | | File System, etc.| |
| +-------+---------+ +--------+---------+ |
|         |                    |           |
|         +---- invoke()  ----+           |
|                    |                     |
| +------------------v-------------------+ |
| | OS WebView (system-provided)        | |
| +--------------------------------------+ |
+------------------------------------------+

The frontend runs inside the webview sandbox. The Rust backend runs as the actual native process. The two communicate through an inter-process call (IPC) mechanism that Tauri exposes as a simple invoke() function from JavaScript. You never set up a local HTTP server, open ports, or worry about cross-origin issues — Tauri uses a custom protocol to serve the frontend assets directly from the binary.

Mobile support in Tauri v2:

Tauri v2 supports Android and iOS in addition to desktop platforms. The architecture is the same — a web frontend inside the mobile system webview and a Rust backend that can call platform APIs via plugins written in Kotlin or Swift. This means one codebase can reach phones, tablets, and desktops.

Why Tauri (Core Advantages)

Tauri was designed around three constraints that together produce a fundamentally different kind of application framework. Every design decision — from choosing Rust to reusing the system webview — traces back to these goals: hard security boundaries, the smallest possible binary, and an architecture that does not lock you into a specific frontend or language for platform logic. For a deep dive into these architectural pillars, explore Why Tauri Core Advantages.

These three advantages are not independent. The small size comes from leaning on the operating system for the webview. The security comes from Rust’s memory model and an explicit permission system that denies everything by default. The flexibility comes from keeping the frontend and backend as separate, loosely coupled layers that communicate through a well-defined IPC boundary.

The following sections explore each of these in depth.

Secure Foundation

A Tauri app starts with every door locked. By default, the frontend running inside the webview cannot access the file system, spawn shell commands, open network requests beyond what the webview itself allows, or touch any system API. To grant access, you must explicitly declare permissions in a capability file. There is no backdoor, no ambient authority — if a permission is not listed, the attempt fails at runtime. For complete security details, see the dedicated Secure Foundation overview and Tauri v2 Permissions & Security.

This model is fundamentally different from Electron, where a Node.js process has access to the entire operating system by default, and any dependency in the renderer process can become a vector for a supply-chain attack. Tauri’s isolation pattern keeps untrusted content in a sandboxed WebView that has no direct access to the Rust backend. All communication from the frontend to the backend goes through the typed invoke() channel, which only exposes the Rust commands you explicitly register.

Rust itself provides another layer of defense. Memory safety bugs — use-after-free, buffer overflows, null pointer dereferences — account for the majority of critical vulnerabilities in systems software. Rust eliminates these classes of bugs at compile time through its ownership system, borrow checker, and strict type safety. A developer writing a Tauri backend does not need to be a Rust expert to inherit these guarantees; the language enforces them automatically.

Tauri also undergoes external security audits for major and minor releases. These audits cover not only the Tauri codebase but also critical upstream dependencies. While no framework can guarantee absolute safety, the combination of a deny-by-default permission model, a memory-safe language, and third-party audits creates a baseline that is unusually high for an application framework.

Missing permissions cause silent failures:

If you call invoke() for a command that requires a system capability — like reading a file — but forget to add the corresponding permission in your capability configuration, the call will fail. The error message in the JavaScript console will mention a permission denial. Developers new to Tauri often spend time debugging their Rust code before realizing the issue is a missing permission entry, not a logic error.

Do not enable all permissions by default:

Tauri’s permission system is granular for a reason. Enabling broad permissions like fs:allow-all or shell:allow-all during development may seem convenient, but shipping with those permissions opens attack surface that Tauri intentionally avoids. List only the specific subpaths and commands your application genuinely needs.

Smaller App Size

A minimal Tauri application — the default scaffold with no extra assets — compiles to a binary that can be under 600 KB. The full installer for a real-world app is typically between 2 and 10 MB, depending on the frontend framework and bundled assets. Electron apps, by comparison, commonly exceed 100 MB because they embed an entire Chromium browser engine that duplicates functionality already present on the user’s machine. Read more in the Smaller App Size breakdown.

The size advantage comes from the architecture. Every modern operating system already ships with a webview capable of rendering modern HTML, CSS, and JavaScript. Tauri does not replace or rebundle that webview — it uses it. The binary contains only your app’s unique code: the Rust backend, the compiled frontend assets, and any static resources like images or fonts.

This matters in ways that go beyond disk space. A smaller installer downloads faster, which reduces friction for users deciding whether to try your app. It installs faster, uses less memory at runtime, and leaves a lighter footprint on the system. For developers distributing apps through app stores or over bandwidth-constrained networks, the difference between a 4 MB binary and a 120 MB binary is the difference between a user clicking "install" and walking away.

Your app is correctly leveraging the system webview:

If you build a Tauri app and the final executable (or installer) is only a few megabytes, the framework is working as designed. The small size confirms that the system webview is being used instead of a bundled browser engine. You can check the src-tauri/target/release/bundle/ directory after running tauri build to see the exact output sizes.

Flexible Architecture

Tauri does not prescribe a frontend framework. You can use React, Vue, Svelte, Solid, vanilla JavaScript, or anything else that compiles to HTML, CSS, and JavaScript. The frontend is a standard web project — a Vite or Webpack setup, for instance — that Tauri integrates as an asset source. You develop the UI exactly as you would for a browser, with hot-reload on file changes, and Tauri serves it inside a native window. Learn more about these architectural components in Flexible Architecture.

On the backend, Rust is the primary language, but the architecture allows you to reach into Swift and Kotlin when a plugin needs to use a platform-specific API that Rust cannot access directly. Tauri’s plugin system is how features like biometrics, push notifications, and deep linking are handled. Official plugins exist for common needs — file system access, HTTP clients, system tray management, auto-updates — and community plugins fill in the gaps.

The link between the frontend and backend is a typed IPC channel. You define a Rust function, annotate it with #[tauri::command], and register it in the app builder. From the JavaScript side, you import invoke and call the function by name, passing arguments as a plain object. The serialization between JavaScript and Rust is automatic. For step-by-step code patterns, see Connecting Backend to Frontend.

Here is a minimal example that sends a name to Rust and gets a greeting back:

#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust.", name)
}
pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
import { invoke } from '@tauri-apps/api/core';
async function greetUser(name: string) {
  const message = await invoke<string>('greet', { name });
  console.log(message);
  // Output: "Hello, Alice! You've been greeted from Rust."
}

The invoke() call is asynchronous. Under the hood, the arguments are serialized to JSON, sent across the IPC boundary to the Rust process, deserialized, and the return value travels the same path back. For the vast majority of use cases — button clicks, menu actions, periodic data syncs — this overhead is imperceptible.

CamelCase in JavaScript, snake_case in Rust:

A common early mistake is using snake_case keys in the JavaScript arguments object. Even though the Rust parameter is name, the JavaScript call must use { name: value }, not { name: value } with an underscore. Tauri v2 expects camelCase keys in the frontend invoke payload. If you use snake_case, the argument will be null on the Rust side, and the error may not be obvious.

Unregistered commands produce runtime errors:

Every #[tauri::command] function must appear in the generate_handler![] macro inside the builder. If you write a new command but forget to add it to the handler list, invoking it from the frontend will throw an error saying the command is not found. This is one of the first issues you will hit when extending a Tauri app — always double-check the registration.

Two core libraries sit beneath Tauri: TAO handles window creation and management across platforms, and WRY provides a uniform interface to the system webview. These libraries are maintained by the Tauri project and can be used directly if your application needs deeper window or rendering control than what Tauri’s high-level APIs expose. Most developers never need to touch them, but their existence means the platform integration is not a black box — the entire stack is auditable and extensible.

This layered design is what gives Tauri its flexibility. The frontend framework, the backend logic language, the system API surface, and the windowing layer are all independently swappable components that communicate through well-defined interfaces. You can start with a simple React app calling a few Rust functions and, over time, grow into multi-window setups with native menus, system tray integrations, and platform-specific plugins — all without leaving the same project structure.

Definition and Purpose

Understanding what Tauri is, its core purpose, and the philosophy behind building cross-platform desktop and mobile applications with web technologies, Rust, and system webviews.

Why Tauri (Core Advantages)

An overview of the three main advantages that set Tauri apart - a secure Rust-powered foundation, dramatically smaller app bundles through OS webview reuse, and a flexible architecture that works with any frontend and multiple backend languages

Secure Foundation

How Tauri's architecture uses Rust safety guarantees, deny-by-default permissions, and external audits to provide a strong security baseline for desktop and mobile applications

Smaller App Size

Understand why Tauri applications are dramatically smaller than traditional desktop app frameworks, how Tauri's architecture eliminates bloat, and the techniques for shrinking your app's binary even further.

Flexible Architecture

How Tauris composable layers let you freely choose frontend frameworks native code languages and plugins while controlling exactly what the frontend can access