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.

Tauri is a framework for building cross-platform desktop and mobile applications from a single codebase. It lets you write the user interface with any web technology that compiles to HTML, CSS, and JavaScript, while the core application logic runs in Rust (and, on mobile platforms, optionally in Swift or Kotlin). The result is a small, fast, native binary that feels like a real app — because it is one — but gets its UI from the operating system’s own webview instead of shipping a bundled browser engine.

The word "Tauri" itself is a Latin-derived term linked to strength (from taurus, the bull). In practice, that strength comes from Rust: the same language that powers parts of Firefox, Linux kernel modules, and critical infrastructure gives Tauri apps memory safety, thread safety, and performance guarantees without a garbage collector.

The Polyglot Toolkit

Tauri is not a single monolithic library. It is a polyglot toolkit — meaning it orchestrates pieces written in different languages — designed to let web developers and systems programmers work on the same application.

The frontend lives inside a system webview. On macOS and iOS, that is WKWebView. On Windows, it is WebView2 (the Chromium-based Edge engine). On Linux, it is WebKitGTK. On Android, it is the Android System WebView. (To ensure your system has all required libraries, see the System Dependencies Overview guide). Because the webview is already present on every user’s machine, a Tauri app does not need to bundle a copy. The frontend folder can contain a React, Vue, Svelte, Solid, or plain HTML/CSS/JS project — anything that produces static files.

The backend is a Rust binary. It acts as the operating system’s entry point, manages windows and menus, and exposes functions that the frontend can call. On mobile, you can also write native code in Swift or Kotlin for deep platform integration, though the core Rust layer remains available.

Webview ≠ Browser Engine Bundle:

The system webview is not the same as a full browser. It renders HTML/CSS/JS but cannot install extensions or open arbitrary tabs. Think of it as the rendering engine your OS provides for displaying web content inside a native window — lightweight and sandboxed.

Here is the relationship between the pieces in a typical desktop Tauri app:

Frontend (HTML/CSS/JS)
   |
   |  calls invoke("command_name", args)
   v
Rust Backend (tauri::command functions)
   |
   |  manages windows, filesystem, system tray, etc.
   v
Operating System

The frontend and backend communicate through an inter-process message passing layer. The frontend calls a Rust function using a JavaScript invoke, which serializes the arguments and sends them to the Rust side. The Rust function runs, returns a value, and the JavaScript receives it asynchronously. This pattern keeps the webview isolated from direct system access: the frontend can only call the exact Rust commands you have explicitly registered.

Why Tauri Exists

Before Tauri, the dominant way to build a desktop app with web technologies was Electron. Electron works, but it bundles an entire Chromium browser with every app, which makes even a "Hello, World" program dozens of megabytes in size and consumes substantial memory. Many developers accepted that trade-off for the sake of cross-platform reach and the convenience of web development skills.

Tauri was created to provide a genuine alternative. Its purpose can be summed up in three goals:

  1. Keep the frontend open to any web stack. No forced framework, no opinionated UI library (see Supported Frontend Templates).
  2. Use the system webview so apps stay tiny. A minimal Tauri app can be under 600KB (see Smaller App Size).
  3. Run core logic in Rust for safety, speed, and control. Developers get access to multi-threading, direct file I/O, and a type system that prevents whole categories of bugs at compile time (see Installing Rust via Rustup).

These goals translate into an architecture that feels familiar to web developers but behaves like a native application — with window menus, system trays, file dialogs, and automatic updates, all driven by a Rust binary that starts instantly.

If you think of it like this, you’ve got it:

The simplest mental model: a Tauri app is a web frontend that runs inside a thin native container. The container is written in Rust and talks to the OS. The frontend can request things from the container (open a file, show a notification) through a secure bridge. The container never exposes raw system access to the webview — only the exact commands you have defined.

Write Once, Run Anywhere (with a Twist)

Tauri embraces the "write once, run anywhere" philosophy, but with an important nuance. The frontend code is shared across all platforms — the same HTML, CSS, and JavaScript produce identical UIs on Windows, macOS, Linux, Android, and iOS. The Rust backend also compiles to every target. However, if you need platform‑specific behaviour (for example, different keyboard shortcuts on macOS versus Windows, or native Swift code for a HealthKit integration on iOS), Tauri provides explicit hooks without forcing you to abandon the shared core.

This is distinct from frameworks that compile a single codebase to platform‑native widgets. Tauri’s UI is always rendered in a webview. That means you get pixel‑perfect consistency across operating systems, with the trade‑off that the UI does not automatically look like a "native" app unless you style it that way. Many teams prefer this trade because it eliminates the cost of writing separate UIs for each OS while still allowing access to all the native APIs through Rust or mobile language bindings.

A Concrete Look: Minimal Tauri App Anatomy

To make the definition tangible, here is the smallest possible Tauri desktop app. It has a plain HTML file as the frontend and a Rust file that registers one command. For a step-by-step walkthrough of creating and invoking commands, see Connecting Backend to Frontend.

Frontend: src/index.html

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <h1>Hello from the webview</h1>
    <button id="greet-btn">Greet</button>
    <p id="output"></p>
    <script>
      const { invoke } = window.__TAURI__;
      document.getElementById('greet-btn').addEventListener('click', () => {
        invoke('greet', { name: 'World' }).then((msg) => {
          document.getElementById('output').textContent = msg;
        });
      });
    </script>
  </body>
</html>

Backend: src-tauri/src/main.rs

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! From Rust.", name)
}
fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

When this app launches, the operating system creates a native window with a webview inside it. The webview loads index.html. The user clicks the button, and the JavaScript invoke function calls the greet command in Rust. The Rust function returns a string, and the webview displays it — all without a local HTTP server, because Tauri uses a custom protocol to serve assets directly.

Notice that greet is not automatically available. It must be registered in main() via generate_handler!. That is a deliberate security boundary: no function in Rust is callable from the frontend unless you explicitly opt in.

Mismatched argument names between JavaScript and Rust:

In Rust, function parameters are snake_case. The JavaScript invoke call must use camelCase keys in the arguments object. Writing { name: "World" } is correct; { snake_name: "World" } will cause an error. This is the single most common mistake when wiring frontend to backend.

What Tauri Is Not

Clarifying what Tauri isn’t prevents a lot of early confusion.

  • Not a lightweight kernel wrapper. Tauri does not run its own kernel or virtualization layer. It uses the system’s existing webview through the WRY library and creates windows through the TAO library. Both are maintained by the Tauri project but are straightforward abstraction layers over OS‑provided functionality.
  • Not a web server. The frontend assets are not served over HTTP. Tauri uses a custom tauri:// protocol that maps directly to files on disk, loaded by the webview. There is no localhost server to configure or secure.
  • Not an Electron clone with a different engine. Electron bundles Chromium and Node.js. Tauri uses the OS webview and Rust. That means no built‑in Node.js APIs; instead, you use Rust for anything that needs system access.
  • Not a mobile‑web‑view wrapper that gives up desktop features. Tauri’s desktop support includes system tray icons, native notifications, window menus, and an updater. The same application can target mobile with the same frontend and shared Rust logic, plus platform‑specific native code when needed.

Assuming Node.js APIs are available:

A common mistake from developers moving from Electron: trying to require('fs') or use Node.js modules in the frontend. They do not exist in a Tauri webview. Filesystem access, for example, must go through a Rust command that you write or through an official plugin like tauri-plugin-fs. The frontend is pure browser‑API territory, with invoke as the only bridge to native capabilities.

Where This Definition Leads

Understanding what Tauri is at this definitional level is the foundation for everything else. The fact that the frontend is just static web files means you choose your UI framework independently. The fact that the backend is Rust means you get to write performance‑critical code in a language that prevents memory bugs. The fact that the bridge is explicit and opt‑in means you have full control over the attack surface of your application.