TAO vs WRY in Tauri: Understanding the Core Architecture
TAO handles native window creation and OS-level event loops while WRY provides the cross-platform WebView implementation, with Tauri combining both to create desktop applications where TAO owns the window and WRY renders the web content inside it.
The Tauri ecosystem (tauri-apps/tauri) is built on a modular architecture that separates window management from web rendering. Understanding the difference between TAO and WRY in the Tauri stack is essential for developers who want to leverage low-level platform APIs or customize the runtime behavior. These two foundational crates handle distinct responsibilities: TAO manages the operating system's native windowing layer, while WRY abstracts the WebView engine.
What Is TAO in Tauri?
TAO serves as the cross-platform application window creation library. According to the ARCHITECTURE.md documentation, it provides the event loop and manages native windows, menus, system trays, cursor states, and focus across platforms.
TAO's primary responsibilities include:
- Wrapping OS-specific windowing APIs including Win32, Cocoa, X11/Wayland, iOS, and Android
- Managing the main event loop that processes user input and system events
- Handling DPI scaling, monitor detection, and window geometry
- Controlling window decorations, focus states, and visibility
In crates/tauri/src/lib.rs at line 190, TAO is re-exported, making its types available through the main Tauri crate. The Window abstraction in crates/tauri/src/window/mod.rs builds directly on TAO's window handle, providing safe Rust bindings to the underlying native window object that TAO creates and owns.
What Is WRY in Tauri?
WRY acts as the abstract layer responsible for determining which WebView engine is used. As documented in ARCHITECTURE.md, it supplies the cross-platform WebView implementation using WebKit on macOS/Linux and Edge WebView2 on Windows.
WRY's core responsibilities include:
- WebView instantiation and lifecycle management
- JavaScript evaluation and IPC (Inter-Process Communication) between WebView and Rust
- Navigation handling and rendering callbacks
- Abstracting platform-specific WebView APIs into a unified interface
WRY is also re-exported in crates/tauri/src/lib.rs and serves as the default runtime for Tauri applications. The WebviewWindow implementation in crates/tauri/src/webview/webview_window.rs forwards WebView-specific operations—such as evaluate_script—to the underlying WRY layer.
How TAO and WRY Work Together in Tauri
In practice, TAO creates and owns the native window object, while WRY creates the WebView that lives inside that window. The tauri-runtime-wry crate acts as the glue layer that coordinates between these two systems, implemented primarily in crates/tauri-runtime-wry/src/lib.rs.
When you create a window using tauri::Builder, the runtime performs the following sequence:
- TAO creates the native window with the specified geometry, decorations, and platform-specific attributes
- WRY initializes the WebView engine and attaches it to the TAO window's content area
- The resulting
Windowobject in Tauri wraps both the TAO window handle and the WRY WebView controller
This separation allows Tauri to keep window-related code (menus, system-tray, DPI handling) independent of the rendering engine. You can theoretically swap the WebView implementation without touching window management, as demonstrated by the ability to disable the wry feature and supply a custom runtime.
Creating Windows with TAO and WRY
The following example demonstrates how Tauri internally uses TAO for window properties while WRY handles the content:
use tauri::{Builder, WindowBuilder, WindowUrl};
fn main() {
Builder::default()
.setup(|app| {
// The builder internally uses TAO to create the native window
let win = WindowBuilder::new(
app,
"main",
WindowUrl::App("index.html".into())
)
.title("My Tauri App")
.inner_size(800.0, 600.0)
.resizable(true)
.build()?;
// The WebView is automatically created by WRY and attached to `win`
Ok(())
})
.run(tauri::generate_context!())
.expect("failed to run app");
}
Executing JavaScript Through WRY
When you need to interact with the WebView layer directly, WRY handles the implementation while TAO manages the window context:
use tauri::{Manager, Window};
fn eval_script(window: &Window) {
// `window` is a wrapper around a TAO window that contains a WRY WebView
// `evaluate_script` forwards the call to the underlying WRY WebView
window.eval("document.title = 'Hello from Rust';")
.expect("script evaluation failed");
}
Summary
- TAO manages the native operating system window, event loop, and platform-specific windowing APIs, providing the container for your application
- WRY abstracts the WebView implementation across platforms, handling HTML rendering, JavaScript execution, and IPC communication
- The
tauri-runtime-wrycrate binds these layers together, using TAO to create the window and WRY to populate it with web content - This architecture allows independent evolution of window management and rendering technologies, enabling you to swap WebView implementations without rewriting window code
Frequently Asked Questions
Can I use TAO without WRY in Tauri?
Yes, TAO can be used independently for native window management without a WebView. The Tauri architecture allows you to disable the default wry feature and implement a custom runtime that uses TAO for windows while substituting a different rendering approach. This is supported through the abstraction layer in crates/tauri-runtime-wry/src/lib.rs and the re-exports in crates/tauri/src/lib.rs.
Why does Tauri separate window management from WebView rendering?
This separation follows the single responsibility principle and enables platform flexibility. By isolating window creation (TAO) from web rendering (WRY), Tauri can support different WebView engines or alternative rendering backends without rewriting window management code. It also allows developers to use TAO for native UI components—such as system trays and menus—while WRY handles the web content area.
How do I access TAO or WRY directly in my Tauri application?
Both crates are re-exported in the main Tauri crate at crates/tauri/src/lib.rs around line 190. You can access them through tauri::tao and tauri::wry when you need low-level control. However, most applications should use the high-level tauri::Window and tauri::WebviewWindow APIs, which wrap these underlying crates with safe abstractions found in crates/tauri/src/window/mod.rs and crates/tauri/src/webview/webview_window.rs.
Which platforms do TAO and WRY support?
TAO supports Windows (Win32), macOS (Cocoa), Linux (X11/Wayland), iOS, and Android, providing a unified windowing API across desktop and mobile. WRY targets the native WebView engines on these platforms: WebKit on macOS and Linux, Edge WebView2 on Windows, and WebKit on iOS/Android. This combination allows Tauri applications to run natively across all major operating systems while using the most efficient rendering engine available on each.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →