Back to Blog

Tauri Tutorial: Build Your First Desktop App with Rust & JavaScript (2026)

Sandy LaneSandy Lane

Video: Tauri Tutorial: Build Your First Desktop App with Rust & JavaScript (2026) by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

A native cross-platform desktop window driven by HTML and Rust. The 2026 way to ship desktop apps without bundling Chromium.

Tauri lets you build desktop applications using web technologies for the UI (HTML, CSS, JavaScript) and Rust for the backend — without shipping a 200MB Electron bundle. Tauri uses the operating system's native webview (WebKit on macOS, WebView2 on Windows, WebKitGTK on Linux), which means a final binary is typically 5–15MB instead of 100+.

This is Lesson 1 of the Tauri series. By the end you will have a working desktop app with React on the front-end and Rust on the back-end.

Prerequisites

Before you start, you need:

  • Rust — install from rustup.rs.
  • Node.js — version 18 or newer.
  • A C compiler — Xcode CLT on macOS, MSVC build tools on Windows, GCC on Linux.
  • Platform-specific WebView — already installed on macOS, Edge WebView2 on Windows 11+, WebKitGTK on Linux.

Check your install:

rustc --version
node --version

Scaffold the project

The create-tauri-app CLI scaffolds a fresh project with sensible defaults:

npm create tauri-app@latest

Follow the prompts. For this lesson:

  • Project namemy-first-tauri-app
  • Language — TypeScript
  • Framework — React
  • Bundler — Vite (default)
  • UI flavor — Tailwind (optional)

The CLI creates a directory with two halves:

my-first-tauri-app/
├── src/                  # frontend (React + TypeScript)
├── src-tauri/            # Rust backend
│   ├── Cargo.toml
│   └── src/
│       ├── main.rs
│       └── lib.rs
└── package.json

The frontend is a standard Vite + React project. The backend is a standard Cargo project that uses the tauri crate as its main dependency. Both halves are wired together by Tauri's build system.

The Rust side

src-tauri/src/lib.rs looks something like:

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    .plugin(tauri_plugin_opener::init())
    .invoke_handler(tauri::generate_handler![/* commands here */])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

tauri::Builder::default() is the entry point. It configures the app with plugins and command handlers, then runs it.

src-tauri/src/main.rs is a thin wrapper:

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

fn main() {
  my_first_tauri_app_lib::run()
}

The cfg_attr line hides the console window on Windows release builds. main calls into the lib so Tauri can also build for mobile (which uses a different entry point macro).

The frontend

src/App.tsx is a normal React component:

import { useState } from "react";

function App() {
  const [count, setCount] = useState(0);

  return (
    <main>
      <h1>Tauri + React</h1>
      <button onClick={() => setCount(count + 1)}>
        Count is {count}
      </button>
    </main>
  );
}

export default App;

There's nothing Tauri-specific yet — the React side is just web. Tauri shows up when you start invoking Rust functions from the frontend, which we'll do in Lesson 2.

Run the app

npm run tauri dev

Three things happen:

  1. Cargo compiles the Rust side (slow first time, ~30 seconds; cached after).
  2. Vite starts the frontend dev server.
  3. Tauri opens a native window and points its webview at the Vite server.

The window appears with the React app inside. Edit src/App.tsx and Vite hot-reloads — the change appears in the window without a restart. Edit Rust and Cargo recompiles, then Tauri restarts the app automatically.

Build a release binary

npm run tauri build

Cargo builds in release mode, Vite produces production assets, Tauri bundles everything into a native installer for the host OS:

  • macOS: .dmg and .app
  • Windows: .msi and .exe
  • Linux: .deb, .AppImage, and .rpm

The output lives in src-tauri/target/release/bundle/. Ship the bundle to users.

The release build is 5–15MB depending on platform — much smaller than Electron's typical 100MB.

What Tauri solves

Two recurring desktop-app problems Tauri addresses:

Bundle size. Electron ships an entire Chromium runtime per app. Tauri uses the system webview, so the runtime is shared.

Native access. Web apps can't read files, talk to system processes, or use most native APIs. Tauri bridges that — Rust functions exposed to the frontend can do anything Rust can do.

The trade-off is that you lose Chromium consistency: WebKit on macOS and WebView2 on Windows differ subtly in CSS support, JS APIs, and rendering. Most apps don't notice; complex web apps occasionally do.

What's next

Lesson 2 introduces commands — Rust functions exposed to the frontend that you can call with invoke(). That's where Tauri stops being "React in a window" and starts being a hybrid app.

Common mistakes

Skipping the Rust toolchain install. Tauri builds need Cargo. If cargo --version doesn't work, install Rust first.

Running npm run dev instead of npm run tauri dev. The first runs only the frontend in a browser; the second wraps it in the Tauri window.

Trying to import Node.js modules in the frontend. The Tauri frontend is a web context — no fs, no path, no child_process. Use Tauri commands (Lesson 2) to call into Rust for those.

Forgetting the tauri-plugin-opener. Tauri 2 uses a plugin model for many features. The default scaffold includes opener for opening URLs and files; other plugins for filesystem, dialog, http, etc., are added with cargo add and npm install.

Recap

npm create tauri-app@latest scaffolds a Tauri 2 project with React + TypeScript + Vite. The project has two halves: src/ (frontend) and src-tauri/ (Rust backend). npm run tauri dev runs both with hot-reload. npm run tauri build produces a native installer. Tauri 2 uses a plugin model — pull in tauri-plugin-* crates for native features.

Next lesson: commands — the bridge between Rust and JavaScript.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.