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.
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