Comprehensive improvements across all guide documents

definitive-guide.md:
- Add missing AsyncReadExt import in streaming example
- Fix v1/v2 WindowUrl table entry (v1 used WindowUrl not WebviewUrl)
- Rename 3-Step Pattern to 4-Step Pattern for plugins

agent-prompts.md:
- Add new Section 15: Prompt for debugging build/compile errors

error-resolution-guide.md:
- Improve A3 lib naming convention explanation
- Clarify G3 multiple definition root cause
- Add actionable WebView2 install commands to H1
- Add O9-O11 mobile build errors (Android SDK, macOS, CocoaPods)

cheatsheet.md:
- Add deep linking subsection with plugin example
- Add gen/schemas/ to file hierarchy
- Fix tokio::spawn -> tauri::async_runtime::spawn in WS example
- Bump tokio-tungstenite 0.21 -> 0.24

ws_server_client_inject_guide.md:
- Add WebSocket.OPEN guard to sendToAllWindows()

tauri2-links.md:
- Expand from 6 to 16 official documentation links
This commit is contained in:
Z User 2026-05-30 20:45:20 +00:00
parent e01e542d65
commit 5972c96ff9
6 changed files with 262 additions and 14 deletions

View File

@ -27,6 +27,8 @@ my-app/
├── src-tauri/ # Backend environment ├── src-tauri/ # Backend environment
│ ├── capabilities/ # NEW: Security capability JSON/TOML files │ ├── capabilities/ # NEW: Security capability JSON/TOML files
│ │ └── default.json # Maps app windows to permissions │ │ └── default.json # Maps app windows to permissions
│ ├── gen/
│ │ └── schemas/ # Generated JSON schemas (referenced by $schema in capabilities)
│ ├── src/ │ ├── src/
│ │ ├── main.rs # Minimal platform entry-point │ │ ├── main.rs # Minimal platform entry-point
│ │ └── lib.rs # Core Application setup & commands │ │ └── lib.rs # Core Application setup & commands
@ -130,7 +132,7 @@ If you want your Tauri application to **act as a WebSocket Server** (e.g., expos
[dependencies] [dependencies]
tauri = { version = "2.0", features = [] } tauri = { version = "2.0", features = [] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
tokio-tungstenite = "0.21" # Industry standard high-performance WS crate tokio-tungstenite = "0.24" # Industry standard high-performance WS crate
futures-util = "0.3" futures-util = "0.3"
``` ```
@ -147,7 +149,7 @@ async fn start_ws_server(port: &str) {
.expect("Failed to bind port"); .expect("Failed to bind port");
while let Ok((stream, _)) = listener.accept().await { while let Ok((stream, _)) = listener.accept().await {
tokio::spawn(async move { tauri::async_runtime::spawn(async move {
if let Ok(mut ws_stream) = accept_async(stream).await { if let Ok(mut ws_stream) = accept_async(stream).await {
println!("New connection established to Tauri WS Server!"); println!("New connection established to Tauri WS Server!");
while let Some(Ok(msg)) = ws_stream.next().await { while let Some(Ok(msg)) = ws_stream.next().await {
@ -165,8 +167,8 @@ async fn start_ws_server(port: &str) {
pub fn run() { pub fn run() {
tauri::Builder::default() tauri::Builder::default()
.setup(|app| { .setup(|app| {
// Spin up native server safely in an isolated async tokio environment // Spin up native server safely using Tauri's async runtime (NOT tokio::spawn directly)
tokio::spawn(start_ws_server("8080")); tauri::async_runtime::spawn(start_ws_server("8080"));
Ok(()) Ok(())
}) })
.run(tauri::generate_context!()) .run(tauri::generate_context!())
@ -263,10 +265,13 @@ fn create_extra_window(app: &tauri::AppHandle) {
} }
``` ```
### Single Instance Lock & Deep Linking ### Single Instance Lock
Ensures only one instance runs, piping external application schemas (e.g. `my-app://open?token=xyz`) into the active runtime. Ensures only one instance runs, focusing the existing window when a second launch is attempted.
```rust ```rust
// src-tauri/Cargo.toml: tauri-plugin-single-instance = "2"
// src-tauri/capabilities/default.json: add "single-instance:default" to permissions
// src-tauri/src/lib.rs // src-tauri/src/lib.rs
#[cfg_attr(mobile, tauri::mobile_entry_point)] #[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() { pub fn run() {
@ -282,3 +287,67 @@ pub fn run() {
.expect("failed execution"); .expect("failed execution");
} }
``` ```
### Deep Linking with `tauri-plugin-deep-link`
Registers a custom URL scheme (e.g., `my-app://open?token=xyz`) so the OS routes external links into your running app.
#### 1. Setup
```toml
# src-tauri/Cargo.toml
[dependencies]
tauri-plugin-deep-link = "2"
```
```json
// src-tauri/capabilities/default.json — add permission
{
"permissions": ["deep-link:default"]
}
```
```json
// src-tauri/tauri.conf.json — register the scheme
{
"app": {
"deepLink": {
"desktop": {
"schemes": ["my-app"]
},
"mobile": {
"scheme": "myapp"
}
}
}
}
```
#### 2. Rust Handler
```rust
// src-tauri/src/lib.rs
use tauri_plugin_deep_link::DeepLinkExt;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_deep_link::init())
.setup(|app| {
// macOS / Linux / Windows desktop handler
#[cfg(desktop)]
app.deep_link().on_open_url(|url| {
println!("Deep link opened: {}", url);
// Parse URL and route to the appropriate handler
});
Ok(())
})
.run(tauri::generate_context!())
.expect("failed execution");
}
```
#### 3. Frontend Listener (optional)
```typescript
import { listen } from '@tauri-apps/api/event';
// The deep-link plugin emits 'deep-link://new-url' events
await listen('deep-link://new-url', (event) => {
console.log('Received deep link:', event.payload);
});
```

View File

@ -13,5 +13,35 @@
* Tauri 2.0 Official Configuration Files Layout Schema (`tauri.conf.json`): * Tauri 2.0 Official Configuration Files Layout Schema (`tauri.conf.json`):
https://v2.tauri.app/develop/configuration-files/ https://v2.tauri.app/develop/configuration-files/
* Tauri 2.0 Rust API Documentation Engine (Official `tauri` Crate Source Docs): * Tauri 2.0 Rust Crate API Documentation (Official `tauri` Crate Source Docs):
https://docs.rs https://docs.rs/tauri/latest/tauri/
* Tauri 2.0 Plugin Index (All Official Plugins):
https://v2.tauri.app/plugin/
* Tauri 2.0 JavaScript API Reference:
https://v2.tauri.app/references/javascript/
* Tauri 2.0 Calling Rust from Frontend (`invoke` Commands):
https://v2.tauri.app/develop/calling-rust/
* Tauri 2.0 Calling Frontend from Rust (Events & Channels):
https://v2.tauri.app/develop/calling-frontend/
* Tauri 2.0 Architecture Overview:
https://v2.tauri.app/develop/architecture/
* Tauri 2.0 Security Overview:
https://v2.tauri.app/security/
* Tauri 2.0 Window Customization:
https://v2.tauri.app/develop/window-customization/
* Tauri 2.0 System Tray Guide:
https://v2.tauri.app/develop/tray/
* Tauri 2.0 Frontend Frameworks (Vite Integration):
https://v2.tauri.app/start/frontend/
* Tauri 2.0 Build Configuration:
https://v2.tauri.app/develop/building/

View File

@ -235,7 +235,11 @@ mainSocket.onerror = (err) => {
// Sending data to other connected windows // Sending data to other connected windows
function sendToAllWindows(payload) { function sendToAllWindows(payload) {
if (mainSocket.readyState === WebSocket.OPEN) {
mainSocket.send(JSON.stringify(payload)); mainSocket.send(JSON.stringify(payload));
} else {
console.warn('WebSocket not open — cannot send. readyState:', mainSocket.readyState);
}
} }
// Example: button click sends data // Example: button click sends data

View File

@ -21,6 +21,7 @@
12. [Prompt: Full App Build (End-to-End)](#12-prompt-full-app-build-end-to-end) 12. [Prompt: Full App Build (End-to-End)](#12-prompt-full-app-build-end-to-end)
13. [Verification Checklist for Agents](#13-verification-checklist-for-agents) 13. [Verification Checklist for Agents](#13-verification-checklist-for-agents)
14. [Quick Reference: v1 vs v2 API Map](#14-quick-reference-v1-vs-v2-api-map) 14. [Quick Reference: v1 vs v2 API Map](#14-quick-reference-v1-vs-v2-api-map)
15. [Prompt: Debug a Tauri 2.0 Build/Compile Error](#15-prompt-debug-a-tauri-20-buildcompile-error)
--- ---
@ -507,3 +508,68 @@ Do NOT skip any file. Generate complete, production-ready code.
| `tauri.updater` | `plugins.updater` | | `tauri.updater` | `plugins.updater` |
| `tauri.systemTray` | `app.trayIcon` | | `tauri.systemTray` | `app.trayIcon` |
| `tauri.cli` | `plugins.cli` | | `tauri.cli` | `plugins.cli` |
---
## 15. Prompt: Debug a Tauri 2.0 Build/Compile Error
```
Diagnose the following Tauri 2.0 build or compile error.
[PASTE FULL ERROR OUTPUT HERE]
Follow this structured diagnosis process:
1. READ THE ERROR MESSAGE CAREFULLY
- Identify the exact error code (e.g., E0432, E0599, E0757, E0277, E0255)
- Note which file and line number the error originates from
- Capture any "note" or "help" lines the compiler provides
2. CROSS-REFERENCE AGAINST ERROR CATEGORIES
Consult the `error-resolution-guide.md` categories and match the error:
- Category A (Rust Compilation Errors): Version mismatches, missing [lib], windres, strip failures
- Category B (v1→v2 Migration): tauri::api removals, Window→WebviewWindow, JS import paths
- Category C (Async & Thread Safety): Borrowed refs in async, Mutex not Send, Rc/RefCell in async
- Category D (Config Errors): V1 config keys, allowlist, tauri→app section, devUrl/frontendDist
- Category E (Capabilities & Permissions): Plugin not allowed, event permissions, path scope
- Category F (Plugin Integration): Plugin not registered in Builder, wrong plugin API usage
- Category G (IPC / Command Errors): Command not found, multiple invoke_handler, pub in lib.rs
- Category H (Webview & Window): WebView2 errors, blank screens, GDK main thread
- Category I (Event System): Events not received, emit vs emit_to confusion
- Category J (CSP Errors): IPC connection refused, inline styles blocked
- Category K (Frontend Integration): Vite port mismatch, Next.js static export, SvelteKit adapter
- Category L (WebSocket): Broken pipe, unstable connections
- Category M (Path & Asset): 403 on asset:// protocol
- Category O (Mobile Build): iOS/Android specific failures
3. CHECK FOR COMMON PATTERNS
- [ ] v1 imports still present (tauri::api::*, @tauri-apps/api/tauri, @tauri-apps/api/window)
- [ ] Missing `pub` on commands in separate modules (or extra `pub` on commands in lib.rs)
- [ ] tauri/tauri-build version mismatch (one is "1" and the other is "2")
- [ ] Async command uses borrowed references (&str, &Path) without Result wrapping
- [ ] std::sync::Mutex held across .await (should be tokio::sync::Mutex)
- [ ] Plugin in Cargo.toml but not registered with .plugin() in Builder
- [ ] Missing capability permission for the plugin/command being used
- [ ] Multiple .invoke_handler() calls (only last one takes effect)
- [ ] tokio::spawn used instead of tauri::async_runtime::spawn inside setup()
- [ ] Window creation in async context without run_on_main_thread()
4. OUTPUT STRUCTURED DIAGNOSIS
Format your response exactly as:
## Error Diagnosis
**Error Category:** [Category letter + name from error-resolution-guide.md]
**Error Code:** [Rust error code if applicable, e.g., E0432]
**Root Cause:** [1-3 sentence explanation of WHY this error occurs]
**Fix Steps:**
1. [Specific file to edit]
- [Exact change to make, with before/after code if applicable]
2. [Additional files if needed]
- [Changes]
**Verification:** [How to confirm the fix works — what should the output look like after]
**Cross-Reference:** [Relevant section in error-resolution-guide.md]
If the error doesn't match any known category, say so explicitly and provide your best analysis based on the error message, Rust compiler output, and Tauri 2.0 API knowledge.
```

View File

@ -693,6 +693,7 @@ For streaming large amounts of data to the frontend:
```rust ```rust
use tauri::ipc::Channel; use tauri::ipc::Channel;
use tokio::io::AsyncReadExt;
#[tauri::command] #[tauri::command]
async fn stream_file(path: std::path::PathBuf, on_chunk: Channel<Vec<u8>>) { async fn stream_file(path: std::path::PathBuf, on_chunk: Channel<Vec<u8>>) {
@ -1048,7 +1049,7 @@ await newWindow.once('tauri://error', (e) => {
| `tauri::WindowBuilder` | `tauri::WebviewWindowBuilder` | | `tauri::WindowBuilder` | `tauri::WebviewWindowBuilder` |
| `tauri::WindowUrl` | `tauri::WebviewUrl` | | `tauri::WindowUrl` | `tauri::WebviewUrl` |
| `app.get_window("main")` | `app.get_webview_window("main")` | | `app.get_window("main")` | `app.get_webview_window("main")` |
| `WebviewUrl::App(path)` | `WebviewUrl::App(path.into())` | | `tauri::WindowUrl::App(path)` | `tauri::WebviewUrl::App(path.into())` |
| `WebviewUrl::External(url)` | `WebviewUrl::External(url)` | | `WebviewUrl::External(url)` | `WebviewUrl::External(url)` |
--- ---
@ -1092,9 +1093,9 @@ await newWindow.once('tauri://error', (e) => {
| Window State | `tauri-plugin-window-state` | `@tauri-apps/plugin-window-state` | Win, Lin, Mac, Android, iOS | | Window State | `tauri-plugin-window-state` | `@tauri-apps/plugin-window-state` | Win, Lin, Mac, Android, iOS |
| Window Customization | `tauri-plugin-window-customization` | `@tauri-apps/plugin-window-customization` | Win, Lin, Mac | | Window Customization | `tauri-plugin-window-customization` | `@tauri-apps/plugin-window-customization` | Win, Lin, Mac |
### Adding a Plugin (3-Step Pattern) ### Adding a Plugin (4-Step Pattern)
Every plugin follows the same 3-step setup: Every plugin follows the same 4-step setup:
**Step 1: Add Rust dependency** **Step 1: Add Rust dependency**
```toml ```toml

View File

@ -88,6 +88,8 @@ crate-type = ["staticlib", "cdylib", "rlib"]
``` ```
Create `src-tauri/src/lib.rs` with your core logic in `pub fn run()`, and a minimal `main.rs` that calls `my_app_lib::run()`. Create `src-tauri/src/lib.rs` with your core logic in `pub fn run()`, and a minimal `main.rs` that calls `my_app_lib::run()`.
> **Naming convention:** The `[lib]` `name` field must match the crate name used in `main.rs`'s function call (`crate_name::run()`). Rust replaces hyphens with underscores in crate identifiers, so a `name = "my-app-lib"` in Cargo.toml becomes `my_app_lib` in code — your `main.rs` must call `my_app_lib::run()`, not `my-app-lib::run()`. Keep this naming consistent across `[lib]`, `main.rs`, and any `mod` re-exports.
--- ---
### A4. `windres` Not Found (Windows) ### A4. `windres` Not Found (Windows)
@ -949,7 +951,7 @@ tauri::Builder::default()
error[E0255]: the name '__cmd__my_command' is defined multiple times error[E0255]: the name '__cmd__my_command' is defined multiple times
``` ```
**Cause:** Commands in `lib.rs` cannot be `pub` due to glue code generation. **Cause:** The `#[tauri::command]` macro generates a companion item named `__cmd__<function_name>` in the same scope. When a command in `lib.rs` is marked `pub`, the generated `__cmd__` glue item is also `pub` — and since `lib.rs` itself re-exports everything at the crate root, the command's `__cmd__` symbol collides with a second copy that `generate_handler![]` produces internally. This can also happen when the same command function appears in multiple modules (e.g., defined in one module and `pub use`'d into another).
**Solution:** Remove `pub` from commands in `lib.rs`, or move them to a separate module where they MUST be `pub`: **Solution:** Remove `pub` from commands in `lib.rs`, or move them to a separate module where they MUST be `pub`:
```rust ```rust
@ -1033,7 +1035,10 @@ Or `0x800700AA` ("The requested resource is in use").
**Cause:** Multiple possible causes: (1) WebView2 runtime not installed/corrupted, (2) Invalid `additional_browser_args`, (3) Another process holding a WebView2 lock, (4) Data folder creation failure. **Cause:** Multiple possible causes: (1) WebView2 runtime not installed/corrupted, (2) Invalid `additional_browser_args`, (3) Another process holding a WebView2 lock, (4) Data folder creation failure.
**Solution:** **Solution:**
1. Install/repair WebView2 runtime 1. Install/repair WebView2 runtime:
- **winget (recommended):** `winget install Microsoft.WebView2Runtime`
- **Direct download:** https://developer.microsoft.com/en-us/microsoft-edge/webview2/
- **Evergreen Bootstrapper:** Download and run the bootstrapper from the link above to install/update to the latest version
2. Remove custom `additional_browser_args` from config 2. Remove custom `additional_browser_args` from config
3. Kill old Tauri dev instances: `taskkill /f /im <your-app>.exe` 3. Kill old Tauri dev instances: `taskkill /f /im <your-app>.exe`
4. For multi-webview support, ensure `features = ["unstable"]` in Cargo.toml 4. For multi-webview support, ensure `features = ["unstable"]` in Cargo.toml
@ -1574,6 +1579,79 @@ No code signing certificates found. You must add one and set the certificate dev
--- ---
### O9. Android SDK Not Found
**Error:**
```
Android SDK not found at ANDROID_HOME. Please set the ANDROID_HOME environment variable.
```
Or Gradle fails with `SDK location not found`.
**Cause:** The `ANDROID_HOME` (or `ANDROID_SDK_ROOT`) environment variable is not set, or points to a nonexistent directory. Tauri's Android build requires the Android SDK to be available.
**Solution:**
1. Install Android Studio, which bundles the SDK
2. Set the environment variable:
```bash
# macOS/Linux — add to ~/.zshrc or ~/.bashrc
export ANDROID_HOME="$HOME/Android/Sdk"
export PATH="$ANDROID_HOME/platform-tools:$PATH"
# Windows — set via System Properties → Environment Variables
ANDROID_HOME=C:\Users\<you>\AppData\Local\Android\Sdk
```
3. Verify: `echo $ANDROID_HOME` and `adb version`
4. Re-run `npx tauri android init`
---
### O10. iOS Development Requires macOS
**Error:**
```
iOS is not supported on this platform
```
Or `xcodebuild: command not found` when running on Linux or Windows.
**Cause:** iOS builds require Xcode and the Apple toolchain, which are only available on macOS. Cross-compilation to iOS from Linux or Windows is not supported by Tauri.
**Solution:**
1. Use a Mac (physical or CI runner like GitHub Actions `macos-latest`)
2. Install Xcode from the Mac App Store
3. Accept the Xcode license: `sudo xcodebuild -license accept`
4. Install CocoaPods: `sudo gem install cocoapods` (or `brew install cocoapods`)
5. For CI, use GitHub Actions with `macos-latest` runner
---
### O11. `pod install` Failed (iOS)
**Error:**
```
Pod installation failed. CocoaPods could not find compatible versions for pod "TauriDriver"
```
Or `pod: command not found`.
**Cause:** CocoaPods is not installed, outdated, or the Podfile.lock is stale and conflicts with updated dependencies.
**Solution:**
1. Ensure CocoaPods is installed:
```bash
sudo gem install cocoapods
# Or via Homebrew:
brew install cocoapods
```
2. Clean and reinstall pods:
```bash
cd src-tauri/gen/apple
rm -rf Podfile.lock Pods
pod install --repo-update
```
3. If version conflicts persist, update CocoaPods to the latest version: `sudo gem install cocoapods --pre`
4. Ensure your Xcode Command Line Tools are up to date: `xcode-select --install`
---
## Category P: Platform-Specific Build Errors ## Category P: Platform-Specific Build Errors
### P1. Linux — Missing System Dependencies ### P1. Linux — Missing System Dependencies