Open a Second Window in Tauri 2 | Multi-Window React + Rust Tutorial

0views
C
CelesteAI
Description
Open a second OS window from your Tauri 2 app in about fifty lines of code. The WebviewWindow API lets a React button spawn a real native window with its own URL, its own size, and its own lifecycle — no Electron, no pop-up hacks, just native windows. Source code: https://github.com/GoCelesteAI/tauri_multiwin We build MultiWin, a deliberately minimal demo: a main window with a button that opens a second window labeled "settings", and each window can close the other. The whole thing is one App.tsx and zero new Rust commands — the multi-window API is pure JavaScript. What You'll Learn: - WebviewWindow from @tauri-apps/api/webviewWindow — the JS-side API for creating windows at runtime. - Window labels — every window has a unique string label; getByLabel("settings") returns the existing one if it's already open, so you can focus instead of duplicate. - Hash-routing two views from one React app — index.html#settings lets the same bundle render either the main UI or the settings UI based on window.location.hash. - getCurrentWebviewWindow().close() — close-self pattern for the secondary window. - Capability gates — core:webview:allow-create-webview-window is the permission your capabilities/default.json needs before the API call works at runtime. - Window options that matter — width, height, title, resizable, center — set once at creation, harder to change later. Timestamps: 0:00 - Two windows. One app. Here is the build. 0:15 - Capability config — the permission gate 0:45 - App.tsx — main window and the open-settings button 2:15 - App.tsx — settings window and close-self 3:00 - Run it — click open, click close 3:45 - End screen Key Takeaways: 1. WebviewWindow is the runtime window API. import { WebviewWindow } from "@tauri-apps/api/webviewWindow"; call new WebviewWindow(label, options); the second window is born. The label is your handle for everything that follows (focus, close, listen). Pick stable label strings — "settings", "about", "preview" — and keep them in a single constants file once you have more than two. 2. Use getByLabel before creating. Calling new WebviewWindow("settings", ...) while a window with that label already exists throws. The safe pattern is const existing = await WebviewWindow.getByLabel("settings"); if (existing) { existing.setFocus(); return; }. Spawn only if absent. This is the single most common multi-window bug in production Tauri apps — fix it before you ship. 3. One React app, multiple windows, hash routing. The simplest way to ship multi-window without a custom Vite config is to load index.html#settings for the second window and branch on window.location.hash at the top of App. Same bundle, two entry points. For larger settings UIs, switch to a separate Vite entry; for the 90% case, hash routing is enough. 4. getCurrentWebviewWindow().close() is close-self. From any window, getCurrentWebviewWindow() returns the WebviewWindow handle for that window — call .close() and the current window closes. From the main window, you can also close any other window by label: (await WebviewWindow.getByLabel("settings"))?.close(). 5. Capabilities gate window creation. capabilities/default.json must include core:webview:allow-create-webview-window (and core:window:allow-close if you close from JS). If you see "Permission core:webview:create-webview-window not granted" at runtime, that's the missing entry. Add it once; don't grant the wildcard core:webview:default in production. This channel is run by Claude AI. Tutorials AI-produced; reviewed and published by Codegiz. Source code at codegiz.com. Part of Tauri Patterns for Production — full playlist linked in the description. #Tauri #Tauri2 #Rust #DesktopApp #React #TypeScript #MultiWindow #ClaudeAI --- Generated by Claude AI · part of the Tauri Patterns for Production series
Back to tutorials

Duration

Added to Codegiz

May 11, 2026

📖 Read the articleOpen in YouTube