new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Tauri · Develop · all subjects

architecture

83 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Tauri apps are small and use the OS's native webview

Tauri apps are very small because they use the OS's webview and do not ship a runtime since the final binary is compiled from Rust. This makes reversing Tauri apps not a trivial task.

Tauri uses WRY and TAO for system calls

Tauri is not a lightweight kernel wrapper. Instead, it directly uses WRY and TAO to do the heavy lifting in making system calls to the OS. Tauri is not a VM or virtualized environment, but an application toolkit that allows making Webview OS applications.

tauri crate reads tauri.conf.json at compile time

The tauri crate is the major crate that holds everything together. It reads the tauri.conf.json file at compile time to bring in features and undertake the actual configuration of the app and even the Cargo.toml file in the project's folder. It handles script injection at runtime, hosts the API for systems interaction, and manages the updating process.

tauri-runtime is the glue layer between Tauri and webview libraries

tauri-runtime is the glue layer between Tauri itself and lower-level webview libraries.

tauri-macros creates context, handler, and command macros

tauri-macros creates macros for the context, handler, and commands by leveraging the tauri-codegen crate.

tauri-utils provides common utilities and configuration parsing

tauri-utils provides common code reused in many places and offers useful utilities like parsing configuration files, detecting platform triples, injecting the CSP, and managing assets.

Tauri is a polyglot desktop app toolkit using Rust and Webview

Tauri is a polyglot and generic toolkit for building desktop applications using a combination of Rust tools and HTML rendered in a Webview. Apps can ship with optional JS API and Rust API so that webviews can control the system via message passing. Developers can extend the default API with custom functionality and bridge the Webview and Rust-based backend.

tauri-codegen embeds and processes assets at compile time

tauri-codegen embeds, hashes, and compresses assets including icons for the app and the system tray. It parses tauri.conf.json at compile time and generates the Config struct.

tauri-runtime-wry handles system-level interactions for WRY

tauri-runtime-wry opens up direct systems-level interactions specifically for WRY, such as printing, monitor detection, and other windowing-related tasks.

tauri-bundler builds apps for macOS, Windows, and Linux

The tauri-bundler is a library that builds a Tauri app for the platform it detects or is told. Currently supports macOS, Windows and Linux, with mobile platform support planned for the near future. It may be used outside of Tauri projects.

TAO is a cross-platform window creation library

TAO is a cross-platform application window creation library in Rust that supports all major platforms like Windows, macOS, Linux, iOS and Android. It is a fork of winit that has been extended with features like menu bar and system tray.

WRY is a cross-platform WebView rendering library

WRY is a cross-platform WebView rendering library in Rust that supports all major desktop platforms like Windows, macOS, and Linux. Tauri uses WRY as the abstract layer responsible for determining which webview is used and how interactions are made.

Tauri plugins enable Rust functionality with JS interface

Tauri plugins are generally authored by third parties and do three things: enable Rust code to do something, provide interface glue to make it easy to integrate into an app, and provide a JavaScript API for interfacing with the Rust code. Examples include tauri-plugin-fs, tauri-plugin-sql, and tauri-plugin-stronghold.

Tauri is licensed under MIT or Apache-2.0

Tauri itself is licensed under MIT or Apache-2.0. If you repackage it and modify any source code, it is your responsibility to verify that you are complying with all upstream licenses. Tauri is provided AS-IS with no explicit claim for suitability for any purpose.

Tauri multi-process architecture overview

Tauri employs a multi-process architecture similar to Electron or modern web browsers. This design isolates components on different processes, allowing crashes in one component to not affect the whole system. It makes better use of modern multi-core CPUs and creates safer applications.

Core process responsibilities

The Core process is the application's entry point and the only component with full access to the operating system. Its primary responsibility is to create and orchestrate application windows, system-tray menus, and notifications using cross-platform abstractions. The Core process also routes all Inter-Process Communication (IPC) through itself, allowing you to intercept, filter, and manipulate IPC messages in one central place.

Core process state management

The Core process should be responsible for managing global state, such as settings or database connections. This allows you to easily synchronize state between windows and protect your business-sensitive data from prying eyes in the Frontend.

Rust for Tauri implementation

Tauri is implemented in Rust because of Rust's concept of Ownership, which guarantees memory safety while retaining excellent performance.

WebView process role

The Core process does not render the actual user interface. It spins up WebView processes that leverage WebView libraries provided by the operating system. A WebView is a browser-like environment that executes your HTML, CSS, and JavaScript.

WebView libraries are dynamically linked

Unlike other similar solutions, the WebView libraries are not included in your final executable but dynamically linked at runtime. On Windows, Tauri uses Microsoft Edge WebView2; on macOS, it uses WKWebView; and on Linux, it uses webkitgtk. This makes your application significantly smaller, but you need to keep platform differences in mind, similar to traditional web development.

Plugin naming convention and NPM package names

Tauri plugins are prefixed with `tauri-plugin-` by default. The generated Cargo crate name is `tauri-plugin-{plugin-name}` and the JavaScript NPM package name is `tauri-plugin-{plugin-name}-api`. The recommended NPM naming convention uses scopes: `@scope-name/plugin-{plugin-name}`.

Plugin project structure with CLI init

When initializing a plugin with `npx @tauri-apps/cli plugin new [name]`, the generated project at `tauri-plugin-[name]/` contains: src/ directory with commands.rs (commands for webview), desktop.rs (desktop implementation), error.rs (default error type), lib.rs (re-exports and setup), mobile.rs (mobile implementation), and models.rs (shared structs); permissions/ directory for permission files; android and ios directories for mobile libraries; guest-js directory for JavaScript API bindings source; dist-js directory for transpiled assets; Cargo.toml for Cargo metadata; and package.json for NPM metadata.

Plugin composition and capabilities

A Tauri plugin is composed of a Cargo crate and an optional NPM package providing API bindings for commands and events. Plugins can optionally include Android library projects and Swift packages for iOS. Plugins can hook into the Tauri lifecycle, expose Rust code for webview APIs, handle commands with Rust/Kotlin/Swift, and access state management.

Platform support declaration in Cargo.toml

Plugins declare platform support in `[package.metadata.platforms.support]` section of Cargo.toml. Each platform key (windows, linux, macos, android, ios) accepts a required `level` field with values "full" (works as intended), "partial" (works with limitations), or "none" (unsupported), and an optional `notes` field for describing caveats rendered as Markdown on the plugin page.

Plugin configuration in tauri.conf.json

Plugin configuration is specified in `tauri.conf.json` under the `plugins` object with the plugin name as the key. For example: `{ "plugins": { "plugin-name": { "timeout": 30 } } }`. The plugin configuration is set on the Builder and parsed at runtime.

Deserializing plugin config in Rust

Define a struct deriving `Deserialize` to represent plugin configuration. Use `Builder::<R, Config>::new("<plugin-name>")` to create a plugin with that config type. To make config optional, use `Builder::<R, Option<Config>>` instead. Access the config in lifecycle hooks via `api.config()`.

Plugin lifecycle events

Plugins can hook into five lifecycle events: setup (plugin initialization), on_navigation (webview navigation attempt), on_webview_ready (new window created), on_event (event loop events), and on_drop (plugin destruction). Mobile plugins have additional lifecycle events documented separately.

Setup lifecycle hook for state and background tasks

The setup hook runs when the plugin is being initialized. Use it to register mobile plugins, manage state with `app.manage()`, and run background tasks. The hook receives `app` and `api` parameters and should return `Ok(())`.

On_navigation lifecycle hook for URL validation

The on_navigation hook is called when the webview attempts navigation. It receives the window and URL as parameters. Return `false` to cancel the navigation, or `true` to allow it.

On_webview_ready lifecycle hook for window initialization

The on_webview_ready hook is called when a new window has been created. Use it to execute initialization scripts for every window. It receives the window parameter.

On_event lifecycle hook for core events

The on_event hook handles event loop events such as window events, menu events, and application exit requests. It receives `app` and `event` parameters where event is of type `RunEvent`. Use `RunEvent::ExitRequested` with `api.prevent_exit()` to prevent app exit, and `RunEvent::Exit` for cleanup logic.

On_drop lifecycle hook for plugin destruction

The on_drop hook is called when the plugin is being deconstructed. It receives the `app` parameter and follows Rust's Drop trait semantics. Use it for cleanup when the plugin is destroyed.

Exposing Rust APIs through plugin structs

Plugin APIs defined in `desktop.rs` and `mobile.rs` are exported as a struct with the same name as the plugin in PascalCase. The struct instance is created and managed as state when the plugin is setup. Users retrieve it via a `Manager` instance (AppHandle, App, or Window) through an extension trait defined in the plugin.

Plugin state management same as Tauri applications

Plugins manage state in the same way as Tauri applications using the State Management guide. Use `app.manage()` to register state and retrieve it via the Manager interface.

Plugin differs from core by design

By design, the Tauri core does not contain features not needed by everyone. Instead, Tauri offers a mechanism called plugins to add external functionalities into Tauri applications.

iOS plugin configuration

iOS plugin configuration is accessed via parseConfig(Config.self) in the load method, which must be wrapped in a do-catch block. Define a configuration struct conforming to Decodable with optional properties (Type?) for optional fields.

Mobile plugin template structure

The default Tauri plugin template splits implementation into two separate modules: desktop.rs and mobile.rs. The desktop implementation uses Rust code directly, while the mobile implementation sends a message to native mobile code. Shared logic across both implementations should be defined in lib.rs.

Android plugin class requirements

A Tauri plugin for Android is defined as a Kotlin class that extends app.tauri.plugin.Plugin and is annotated with app.tauri.annotation.TauriPlugin. Each method annotated with app.tauri.annotation.Command can be called by Rust or JavaScript. Java can be used instead of Kotlin by converting the Kotlin file in Android Studio.

iOS plugin class requirements

A Tauri plugin for iOS is defined as a Swift class that extends the Plugin class from the Tauri package. Each function with the @objc attribute and the (_ invoke: Invoke) parameter can be called by Rust or JavaScript. The plugin is defined as a Swift package using the Swift package manager.

Plugin load lifecycle event

The load lifecycle event fires when the plugin is loaded into the web view. It is used to execute plugin initialization code. On Android, override the load(webView: WebView) method. On iOS, override the load(webview: WKWebView) method.

Android onNewIntent lifecycle event

The onNewIntent lifecycle event is Android-only and fires when the activity is re-launched. It is used to handle application re-launch such as when a notification is clicked or a deep link is accessed. Override the onNewIntent(intent: Intent) method to handle this event.

Android plugin configuration

Android plugin configuration is accessed via getConfig(Config::class.java) in the load method. Define a configuration class annotated with @InvokeArg with nullable properties (Type?) for optional fields and default values for fields with defaults.

Android long-running operations pitfall

On Android native commands are scheduled on the main thread. Performing long-running operations will cause the UI to freeze and potentially trigger an "Application Not Responding" (ANR) error. Use CoroutineScope(Dispatchers.IO).launch for blocking IO operations.

When to use async vs sync Mutex

It is often fine and preferred to use std::sync::Mutex in asynchronous code. The primary use case for async mutex (like Tokio's Mutex) is providing shared mutable access to IO resources such as database connections. Use async mutex only if you need to hold the MutexGuard across await points.

Wrap mutable state with Mutex for thread safety

State shared between multiple threads requires interior mutability. Wrap state with std::sync::Mutex to prevent data races. Lock the mutex to get mutable access, and it automatically unlocks when the MutexGuard is dropped.

Mutex-wrapped state example

Example of wrapping state with Mutex and modifying it: ```rust use std::sync::Mutex; use tauri::{Builder, Manager}; #[derive(Default)] struct AppState { counter: u32, } fn main() { Builder::default() .setup(|app| { app.manage(Mutex::new(AppState::default())); Ok(()) }) .run(tauri::generate_context!()) .unwrap(); } // Access and modify: let state = app.state::<Mutex<AppState>>(); let mut state = state.lock().unwrap(); state.counter += 1; ```

Basic state management example

Example showing how to set up state in a Tauri application: ```rust use tauri::{Builder, Manager}; struct AppData { welcome_message: &'static str, } fn main() { Builder::default() .setup(|app| { app.manage(AppData { welcome_message: "Welcome to Tauri!", }); Ok(()) }) .run(tauri::generate_context!()) .unwrap(); } ```

No need to wrap state with Arc

Do not use Arc when storing state with Tauri's State because Tauri handles the Arc wrapping internally. If State's lifetime prevents moving into a thread, move an AppHandle instead (AppHandle is cheap to clone) and retrieve state using app_handle.state::<Type>().

Use type alias to prevent state type mismatches

Create a type alias for your wrapped state to prevent type mismatch errors: ```rust use std::sync::Mutex; #[derive(Default)] struct AppStateInner { counter: u32, } type AppState = Mutex<AppStateInner>; ``` Use the type alias as-is in commands, not wrapped in another Mutex.

Sidecar binary naming convention with target triple suffix

External binaries (sidecars) must be named with a target triple suffix for each supported architecture. For a sidecar configured as 'binaries/my-sidecar', you need separate executables like 'my-sidecar-x86_64-unknown-linux-gnu' on Linux or 'my-sidecar-aarch64-apple-darwin' on macOS with Apple Silicon. The target triple can be determined by running 'rustc --print host-tuple' (Rust 1.84.0+), or for older versions use 'rustc -Vv | grep host | cut -f2 -d" "' on Unix or 'rustc -Vv | Select-String "host:" | ForEach-Object {$_.Line.split(" ")[1]}' on Windows PowerShell.

Frontend architecture patterns supported by Tauri

Tauri supports static site generation (SSG), single-page applications (SPA), and classic multi-page apps (MPA). Tauri does not natively support server-based alternatives such as server-side rendering (SSR).

Tauri acts as a static web host

Tauri functions conceptually as a static web host. You must provide Tauri with a folder containing HTML, CSS, JavaScript, and possibly WASM that can be served to the webview Tauri provides.

Client-server relationship requirement

Tauri applications should use a proper client-server relationship between the app and APIs, avoiding hybrid solutions that mix SSR with client-side rendering.

Supported frontend frameworks for Tauri projects

Tauri works with virtually any frontend framework. The create-tauri-app utility includes officially maintained templates for: vanilla (HTML, CSS, JavaScript), Vue.js, Svelte, React, SolidJS, Angular, Preact, Yew, Leptos, and Sycamore. Additional community templates and frameworks can be found in the Awesome Tauri repository.

Use SSG with Tauri Leptos projects

Use static site generation (SSG) for Leptos projects with Tauri. Tauri does not officially support server-based solutions.

Qwik SSG requirement for Tauri

Tauri does not support server-based solutions. When using Qwik, you must use Static Site Generation (SSG).

Frontend framework compatibility with Tauri

Virtually any frontend framework that compiles to HTML, JavaScript, and CSS is compatible with Tauri. The Frontend Configuration guide contains common configurations for popular frontend frameworks.

TAO and WRY libraries

TAO is maintained by Tauri and is responsible for Tauri window creation. WRY is maintained by Tauri and is responsible for web view rendering. These libraries can be consumed directly if deeper system integration is required outside of what Tauri exposes.

Rust-only Tauri projects

If working with Rust code only, remove everything else and use the src-tauri/ folder as the top-level project or as a member of a Rust workspace.

Standard Tauri project structure

A Tauri project typically consists of two parts: a JavaScript project at the top level and a Rust project in the `src-tauri/` directory. The JavaScript project contains `package.json`, `index.html`, and `src/main.js`. The Rust project is a standard Cargo project with additional Tauri-specific files and directories.

Give your agent this brain