Tauri 2.0 Project Setup for Production: Capabilities, Plugins, the Real Structure | Ep1
0views
C
CelesteAI
Description
Episode 1 of *Tauri Patterns for Production* — the series for developers who've built a Tauri demo and want to ship a real desktop app.
Tauri 2.0 changed the foundation. The 1.x allowlist is replaced by **capabilities** — JSON files that grant exact permissions per window. Plugins are now first-class — most platform features (opener, fs, dialog, http, sql, notification, updater) ship as opt-in plugins instead of being built-in. This episode tours the project structure every production Tauri 2 app starts from.
What You'll Learn:
- The two-half project layout: `src/` for the React frontend, `src-tauri/` for the Rust backend, with a strict separation that keeps the toolchain boundaries clean.
- The Tauri 2.0 capability model: each capability is a JSON file under `src-tauri/capabilities/` listing exact permissions (`core:default`, `opener:allow-open-url`, etc.) for which windows. Replaces the 1.x global allowlist.
- The plugin-first architecture: `tauri = "2"` is the minimal core; everything else (`tauri-plugin-opener = "2"`, `tauri-plugin-fs`, etc.) is opt-in. Pull only what you need.
- The Rust entry point: `#[tauri::command]` marks any Rust function as JavaScript-callable; `invoke_handler` registers it; `tauri::Builder::default()` chains plugins, the handler, and runs the app.
- The frontend bridge: `invoke("command_name", { args })` from `@tauri-apps/api/core` returns whatever the Rust side returned, fully typed if you set up TypeScript right.
- Production bundling: `pnpm tauri build` produces `.app` + `.dmg` on macOS, `.msi` on Windows, `.deb` + `.AppImage` on Linux — release-ready outputs, covered in detail in episode 8.
Timestamps:
0:00 - Intro — Episode 1 starts here
0:23 - Preview — capabilities, plugins, the new model
1:10 - Setup walkthrough — scaffold, install, verify Tauri 2+
2:00 - Project structure: src/ and src-tauri/
2:15 - Frontend dependencies (package.json)
2:30 - Rust backend (Cargo.toml — tauri = "2", plugins)
2:45 - Window config + bundling (tauri.conf.json)
3:05 - Capabilities — the new Tauri 2 permission model
3:20 - Rust entry point + invoke handler (lib.rs)
3:50 - Frontend invoke() pattern (App.tsx)
4:25 - Production build output
4:38 - Live demo — the running Stock Watcher app
5:00 - Recap
5:50 - End screen
Key Takeaways:
1. **Two halves, never mix.** `src/` is the React frontend (TypeScript, Vite); `src-tauri/` is the Rust backend (Cargo). Tauri keeps them strictly separated. The bridge between them is `invoke()` on the JS side and `#[tauri::command]` on the Rust side. Trying to import Rust crates from frontend code (or vice versa) is a category error.
2. **Capabilities replaced the 1.x allowlist.** In Tauri 1.x you'd set a global allowlist in `tauri.conf.json` listing every API surface. In Tauri 2.0, each capability is a separate JSON file under `src-tauri/capabilities/` granting specific permissions to specific windows. The default file `default.json` ships with `core:default` (basic core permissions) plus whatever plugins you've added. This is more verbose but vastly more secure — every permission is explicit.
3. **Plugins are first-class.** The Tauri 2 core (`tauri = "2"` in Cargo.toml) is minimal. File system access, HTTP, dialogs, OS info, notifications, updater, SQL — all of these are opt-in plugins (`tauri-plugin-fs`, `tauri-plugin-http`, etc.). You install only the ones you need, and each one has its own JS API and capability permissions. This dramatically reduces the bundled binary size for apps that don't need everything.
4. **`#[tauri::command]` + `invoke_handler` is the IPC surface.** Annotate any async or sync Rust function with `#[tauri::command]`, register it via `tauri::generate_handler![fn1, fn2]` passed to `invoke_handler` on the builder. From the frontend, call `await invoke("fn_name", { args })` from `@tauri-apps/api/core` (typed via the generic parameter). We'll go deep on IPC patterns in episode 2.
5. **`pnpm tauri build` is the production output.** Generates platform-specific bundles per the `bundle.targets` config: `.app` and `.dmg` on macOS, `.msi` on Windows, `.deb` and `.AppImage` on Linux. The output is a signed-and-notarized release artifact (once you've configured signing — covered in episode 7). The release binary is ~5-15 MB depending on plugins included, vs ~150 MB for an equivalent Electron app.
This channel is run by Claude AI. Tutorials AI-produced; reviewed and published by Codegiz. Source code at codegiz.com.
#Tauri #Tauri2 #Rust #DesktopApp #React #TypeScript #ClaudeAI