Skip to main content
The Tauri shell is Yasumu’s native desktop layer, providing OS integration, window management, and the bridge between the Next.js frontend and the Tanxium runtime.

What is Tauri?

Tauri is a framework for building desktop applications using web technologies for the UI and Rust for the backend. Unlike Electron, which bundles Chromium and Node.js, Tauri:
  • Uses the OS’s native webview (WebView2 on Windows, WebKit on macOS/Linux)
  • Results in much smaller binaries (typically 10-20x smaller than Electron)
  • Provides better performance with lower memory usage
  • Offers a stricter security model with capability-based permissions

Tauri configuration

Yasumu’s Tauri app is defined in apps/yasumu/src-tauri/Cargo.toml:
[package]
name = "yasumu"
version = "0.1.0"
edition = "2024"

[dependencies]
tauri = { version = "2", features = ["devtools"] }
deno_runtime = { version = "0.229.0", features = ["transpile", "snapshot"] }
deno_core = "0.363.0"
# ... other dependencies

Key dependencies

  • tauri: Core framework
  • deno_runtime / deno_core: Embedded JavaScript runtime
  • tokio: Async runtime for Rust
  • serde / serde_json: Serialization for IPC
  • rustls: TLS implementation for HTTPS requests

Application lifecycle

The Tauri app lifecycle is managed in lib.rs:
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_window_state::Builder::new().build())
        .plugin(tauri_plugin_updater::Builder::new().build())
        .plugin(tauri_plugin_store::Builder::new().build())
        // ... more plugins
        .setup(|app| {
            // Initialize Tanxium runtime
            tanxium::set_app_handle(app.handle().clone());
            tanxium::initialize_prompter();
            
            // Load and start the main JavaScript module
            let main_module = /* ... load from resources ... */;
            tanxium::create_and_start_worker(&main_module, app_handle)?;
            
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![
            on_frontend_ready,
            get_rpc_port,
            respond_to_permission_prompt,
            // ... more commands
        ])
        .run(tauri::generate_context!())
}

Initialization flow

Tauri commands

Tauri commands are Rust functions that can be called from the frontend via IPC. Yasumu defines several commands:

on_frontend_ready

Called when the Next.js frontend has loaded:
#[tauri::command]
fn on_frontend_ready(app: tauri::AppHandle) -> Result<(), ()> {
    let state = app.state::<Mutex<YasumuInternalState>>();
    let mut yasumu_state = state.lock().unwrap();
    
    if !yasumu_state.ready {
        yasumu_state.ready = true;
        tanxium::invoke_renderer_event_callback(
            &json!({"type": "yasumu_internal_ready_event"}).to_string()
        );
    }
    Ok(())
}

get_rpc_port

Returns the port where Tanxium’s RPC server is listening:
#[tauri::command]
fn get_rpc_port(app: tauri::AppHandle) -> Option<u16> {
    let state = app.state::<Mutex<YasumuInternalState>>();
    state.lock().unwrap().rpc_port
}

respond_to_permission_prompt

Forwards permission decisions to Tanxium:
#[tauri::command]
fn respond_to_permission_prompt(thread_id: String, response: String) {
    tanxium::respond_to_permission_prompt(
        &thread_id,
        tanxium::PermissionsResponse::from_str(&response)
    );
}

Window management

Yasumu creates a single main window with platform-specific styling:
let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
    .title("Yasumu")
    .inner_size(1280.0, 720.0);

// macOS: Use native title bar overlay
#[cfg(target_os = "macos")]
let win_builder = win_builder
    .title_bar_style(TitleBarStyle::Overlay)
    .hidden_title(true);

// Windows/Linux: Custom window decorations
#[cfg(not(target_os = "macos"))]
let win_builder = win_builder.decorations(false);

let window = win_builder.build()?;
This provides:
  • macOS: Native title bar with transparent overlay
  • Windows/Linux: Custom-drawn title bar for consistent styling

Plugin system

Tauri plugins extend the application with native capabilities:
PluginPurpose
window-statePersists window position and size
updaterAuto-update functionality
dialogNative file picker dialogs
storePersistent key-value storage
httpHTTP client (for Tanxium)
fsFilesystem access
osOS information
Each plugin is initialized during app setup:
tauri::Builder::default()
    .plugin(tauri_plugin_window_state::Builder::new().build())
    .plugin(tauri_plugin_updater::Builder::new().build())
    .plugin(tauri_plugin_dialog::init())
    // ...

Security model

Tauri’s security is built on capabilities and allowlists:
  1. No eval by default: The frontend can’t execute arbitrary code
  2. Explicit IPC: Only registered commands are callable
  3. Scoped filesystem: Access is limited to allowed directories
  4. Content Security Policy: Strict CSP prevents XSS attacks

IPC security

All communication between frontend and backend goes through type-safe Tauri commands:
// Frontend (TypeScript)
import { invoke } from '@tauri-apps/api/core';

const port = await invoke<number>('get_rpc_port');
// Backend (Rust)
#[tauri::command]
fn get_rpc_port(app: tauri::AppHandle) -> Option<u16> {
    // implementation
}
There’s no way for the frontend to call arbitrary Rust code—only explicitly registered commands.

Development vs production

Yasumu behaves differently in development and production:

Development mode

#[cfg(debug_assertions)]
{
    window.open_devtools();  // Auto-open Chrome DevTools
}
  • DevTools open automatically
  • Hot module replacement enabled
  • More verbose logging

Production mode

  • Optimized bundles
  • Code signing (macOS/Windows)
  • Auto-update enabled
  • Crash reporting

Building and bundling

The build process involves several steps:
  1. Build Tanxium: Compile TypeScript to a single JavaScript bundle
    pnpm --filter=tanxium run build
    
  2. Build Next.js: Create static export
    pnpm --filter=@yasumu/app run build
    
  3. Bundle Tauri: Compile Rust and package everything
    pnpm --filter=@yasumu/app tauri build
    
The result is a single executable for each platform:
  • Windows: yasumu.exe (installer)
  • macOS: Yasumu.app (DMG or PKG)
  • Linux: yasumu (AppImage, deb, rpm)

Resource management

Tanxium’s JavaScript bundle is embedded as a resource:
let resource_dir = app_handle.path().resource_dir()?;
let main_path = resource_dir
    .join("resources")
    .join("yasumu-scripts")
    .join("main.ts");

let main_module = ModuleSpecifier::from_file_path(&main_path)?;
tanxium::create_and_start_worker(&main_module, app_handle)?;
At build time, the compiled Tanxium bundle is copied to the resources directory and included in the final binary.

State management

Tauri manages global state using app.state():
pub struct YasumuInternalState {
    pub ready: bool,
    pub rpc_port: Option<u16>,
    pub echo_server_port: Option<u16>,
    pub virtual_modules: VirtualModulesStore,
}

// In setup:
app.manage(Mutex::new(YasumuInternalState {
    ready: false,
    rpc_port: None,
    echo_server_port: None,
    virtual_modules: Arc::new(Mutex::new(HashMap::new())),
}));
This state is accessible from any Tauri command via dependency injection.

Next steps

Build docs developers (and LLMs) love