From 51ae409ecbf131c14939150ba10884859a00b58b Mon Sep 17 00:00:00 2001 From: uroma Date: Fri, 23 Jan 2026 18:39:20 +0000 Subject: [PATCH] Add Tauri framework development skill Created comprehensive Tauri skill for building desktop and mobile applications with Rust backend and web frontend. Skill Content: - Complete Tauri 2.0 framework coverage - Cross-platform development (Windows, macOS, Linux, iOS, Android) - IPC communication patterns (commands, events, bridges) - Security best practices (capabilities, permissions, CSP) - Native API integration (system tray, notifications, file system) - Build and distribution guidance (code signing, auto-updater) Files Created: - skill.md - Main skill with 6 slash commands - templates/ - tauri.conf.json - Config template with all options - capabilities/default.json - Basic permissions - capabilities/fs-full.json - File system access - capabilities/network.json - Network permissions - src-tauri/commands/mod.rs - Rust command templates - src-tauri/events.rs - Event emission examples - examples/ - command-invoking.txt - Frontend command patterns - event-listening.txt - Event handling patterns - plugin-usage.txt - 10+ plugin examples (fs, http, dialog, etc.) - mobile-setup.txt - iOS/Android development guide Slash Commands: - /tauri-init - Initialize new Tauri project - /tauri-add-plugin - Add Tauri plugin - /tauri-build - Build for specific platform - /tauri-capability - Create permission capability - /tauri-ipc - Design IPC interface - /tauri-native - Add native feature Integration: - Uses rust-patterns for backend code quality - Integrates with react-dev, vue, svelte for frontend - Leverages architecture skill for system design - Uses test-driven-development for testing Credits: - Proper attribution to Tauri Team and The Commons Conservancy - Links to official documentation and community resources - Credits core dependencies: WRY, TAO, Tauri CLI Planned via /brainstorm with comprehensive Ralph-validated design. Co-Authored-By: Claude --- skills/tauri/examples/command-invoking.txt | 95 +++++ skills/tauri/examples/event-listening.txt | 103 +++++ skills/tauri/examples/mobile-setup.txt | 283 ++++++++++++++ skills/tauri/examples/plugin-usage.txt | 258 +++++++++++++ skills/tauri/skill.md | 353 ++++++++++++++++++ .../tauri/templates/capabilities/default.json | 26 ++ .../tauri/templates/capabilities/fs-full.json | 24 ++ .../tauri/templates/capabilities/network.json | 21 ++ .../tauri/templates/src-tauri/commands/mod.rs | 63 ++++ skills/tauri/templates/src-tauri/events.rs | 70 ++++ skills/tauri/templates/tauri.conf.json | 63 ++++ 11 files changed, 1359 insertions(+) create mode 100644 skills/tauri/examples/command-invoking.txt create mode 100644 skills/tauri/examples/event-listening.txt create mode 100644 skills/tauri/examples/mobile-setup.txt create mode 100644 skills/tauri/examples/plugin-usage.txt create mode 100644 skills/tauri/skill.md create mode 100644 skills/tauri/templates/capabilities/default.json create mode 100644 skills/tauri/templates/capabilities/fs-full.json create mode 100644 skills/tauri/templates/capabilities/network.json create mode 100644 skills/tauri/templates/src-tauri/commands/mod.rs create mode 100644 skills/tauri/templates/src-tauri/events.rs create mode 100644 skills/tauri/templates/tauri.conf.json diff --git a/skills/tauri/examples/command-invoking.txt b/skills/tauri/examples/command-invoking.txt new file mode 100644 index 0000000..19b4127 --- /dev/null +++ b/skills/tauri/examples/command-invoking.txt @@ -0,0 +1,95 @@ +# Frontend Command Invocation Examples + +## Basic Command Call +```typescript +import { invoke } from '@tauri-apps/api/core'; + +// Simple command +const greeting = await invoke('greet', { name: 'World' }); +console.log(greeting); // "Hello, World! From Rust backend!" +``` + +## Command with Structured Payload +```typescript +interface ExamplePayload { + data: string; + count: number; +} + +const result = await invoke('process_data', { + payload: { + data: 'test', + count: 42 + } +}); +``` + +## Async Command +```typescript +const asyncResult = await invoke('async_operation', { + input: 'test input' +}); +console.log(asyncResult); // Returns after 1 second +``` + +## Error Handling +```typescript +try { + await invoke('command_with_error', { + should_fail: false + }); +} catch (error) { + console.error('Command failed:', error); +} +``` + +## With Progress Tracking +```typescript +import { listen } from '@tauri-apps/api/event'; + +// Listen for progress events +const unlisten = await listen('progress', (event) => { + const { current, total, message } = event.payload as { + current: number; + total: number; + message: string; + }; + console.log(`Progress: ${current}/${total} - ${message}`); +}); + +// Then call a long-running command +await invoke('long_running_task'); + +// Cleanup when done +unlisten(); +``` + +## Type-Safe Commands +```typescript +// Define command types +interface GreetArgs { + name: string; +} + +// Use with generics +const result = await invoke('greet', { name: 'Claude' } as GreetArgs); +``` + +## Batch Commands +```typescript +const results = await Promise.all([ + invoke('greet', { name: 'Alice' }), + invoke('greet', { name: 'Bob' }), + invoke('greet', { name: 'Charlie' }) +]); +``` + +## With Window Reference +```typescript +import { getCurrentWindow } from '@tauri-apps/api/window'; + +const window = getCurrentWindow(); +await invoke('window_command', { + windowLabel: window.label +}); +``` diff --git a/skills/tauri/examples/event-listening.txt b/skills/tauri/examples/event-listening.txt new file mode 100644 index 0000000..66492cd --- /dev/null +++ b/skills/tauri/examples/event-listening.txt @@ -0,0 +1,103 @@ +# Event Listening Examples + +## Basic Event Listener +```typescript +import { listen } from '@tauri-apps/api/event'; + +const unlisten = await listen('my-event', (event) => { + console.log('Received event:', event.payload); +}); +``` + +## Typed Event Payload +```typescript +interface ProgressPayload { + current: number; + total: number; + message: string; +} + +const unlisten = await listen('progress', (event) => { + const { current, total, message } = event.payload; + console.log(`Progress: ${current}/${total} - ${message}`); +}); +``` + +## Multiple Event Listeners +```typescript +const listeners = [ + await listen('progress', (e) => console.log('Progress:', e.payload)), + await listen('error', (e) => console.error('Error:', e.payload)), + await listen('complete', (e) => console.log('Complete:', e.payload)) +]; + +// Cleanup all +listeners.forEach(unlisten => unlisten()); +``` + +## Event with Window Filter +```typescript +import { listen } from '@tauri-apps/api/event'; +import { getCurrentWindow } from '@tauri-apps/api/window'; + +const window = getCurrentWindow(); + +await listen('window-event', (event) => { + console.log('Window event:', event.payload); +}, { + window: window.label +}); +``` + +## One-Time Event +```typescript +import { once } from '@tauri-apps/api/event'; + +once('initial-data', (event) => { + console.log('Initial data:', event.payload); +}); +``` + +## Emitting from Frontend +```typescript +import { emit } from '@tauri-apps/api/event'; + +emit('frontend-event', { data: 'from frontend' }); +``` + +## Real-Time Updates Pattern +```typescript +class TauriEventHandler { + private listeners: Array<() => void> = []; + + async setup() { + this.listeners.push( + await listen('data-update', this.handleDataUpdate.bind(this)), + await listen('progress', this.handleProgress.bind(this)), + await listen('error', this.handleError.bind(this)) + ); + } + + private handleDataUpdate(event: Event) { + // Handle data updates + } + + private handleProgress(event: Event) { + // Update progress bar + } + + private handleError(event: Event) { + // Show error notification + } + + cleanup() { + this.listeners.forEach(unlisten => unlisten()); + } +} + +// Usage +const handler = new TauriEventHandler(); +await handler.setup(); +// ... later +handler.cleanup(); +``` diff --git a/skills/tauri/examples/mobile-setup.txt b/skills/tauri/examples/mobile-setup.txt new file mode 100644 index 0000000..23747f9 --- /dev/null +++ b/skills/tauri/examples/mobile-setup.txt @@ -0,0 +1,283 @@ +# Mobile Setup Guide (Tauri 2.0) + +## Prerequisites + +### iOS Development +- macOS computer +- Xcode 15+ installed +- iOS Simulator or physical device +- Apple Developer Account (for device testing) + +### Android Development +- Android Studio installed +- Android SDK Platform Tools +- Android device or emulator (API level 24+) + +## Project Configuration + +### Add Mobile Targets to tauri.conf.json + +```json +{ + "bundle": { + "active": true, + "targets": ["all"], + "iOS": { + "developmentTeam": "YOUR_TEAM_ID", + "frameworks": [] + }, + "android": { + "minSdkVersion": 24 + } + } +} +``` + +### Install Rust Targets + +```bash +# iOS targets +rustup target add aarch64-apple-ios +rustup target add aarch64-apple-ios-sim + +# Android targets +rustup target add aarch64-linux-android +rustup target add armv7-linux-androideabi +rustup target add i686-linux-android +rustup target add x86_64-linux-android +``` + +## iOS Setup + +### 1. Configure Xcode + +```bash +# Open Xcode project +open ios/Runner.xcworkspace + +# Or generate Xcode project if needed +npm run tauri ios init +``` + +### 2. Set Development Team + +In Xcode: +1. Select the project in the navigator +2. Choose "Signing & Capabilities" +3. Set "Team" to your development team +4. Enable "Automatically manage signing" + +### 3. Run on iOS Simulator + +```bash +# Start development +npm run tauri ios dev + +# Or build for iOS +npm run tauri ios build +``` + +### 4. Run on Physical Device + +Connect device via USB, then: +```bash +npm run tauri ios dev +``` + +Select your device when prompted. + +## Android Setup + +### 1. Install Android SDK + +```bash +# Via Android Studio SDK Manager +# Or via command line +sdkmanager "platform-tools" "platforms;android-33" +``` + +### 2. Enable USB Debugging + +On Android device: +1. Settings → About Phone +2. Tap "Build Number" 7 times to enable Developer Options +3. Settings → Developer Options +4. Enable "USB Debugging" + +### 3. Connect Device + +```bash +# Verify device is connected +adb devices + +# Run on Android device +npm run tauri android dev +``` + +### 4. Android Studio Configuration + +```bash +# Open Android project +open android/` + +# Or generate project +npm run tauri android init +``` + +## Mobile-Specific Considerations + +### Permissions + +Add to `android/app/src/main/AndroidManifest.xml`: +```xml + + +``` + +Add to `ios/Runner/Info.plist`: +```xml +NSCameraUsageDescription +We need camera access +``` + +### Platform-Specific Code + +```rust +#[cfg(target_os = "android")] +fn mobile_only_android() { + println!("Android specific code"); +} + +#[cfg(target_os = "ios")] +fn mobile_only_ios() { + println!("iOS specific code"); +} + +#[cfg(not(any(target_os = "android", target_os = "ios")))] +fn desktop_only() { + println!("Desktop specific code"); +} +``` + +### Mobile Plugins + +Tauri 2.0 plugins work on mobile: + +```typescript +// Works on all platforms +import { readTextFile } from '@tauri-apps/plugin-fs'; +import { fetch } from '@tauri-apps/plugin-http'; +import { open } from '@tauri-apps/plugin-shell'; + +// Mobile-specific +import { vibrate } from '@tauri-apps/plugin-haptics'; +``` + +### Orientation Control + +```rust +use tauri::{Manager, AppHandle}; + +#[tauri::command] +fn set_orientation(app_handle: AppHandle, orientation: &str) { + #[cfg(target_os = "android")] + { + use jni::{JNIEnv, objects::JClass, objects::JObject}; + + app_handle.android().run_on_android_thread( + |env, activity| { + // Set orientation via Android API + }, + |error| { + eprintln!("Error setting orientation: {}", error); + } + ); + } + + #[cfg(target_os = "ios")] + { + // iOS orientation handling + } +} +``` + +## Building for Production + +### iOS Production Build + +```bash +# Archive and export +npm run tauri ios build + +# Sign with distribution certificate +# Configure in Xcode → Signing & Capabilities +``` + +### Android Production Build + +```bash +# Generate APK +npm run tauri android build + +# Generate AAB for Play Store +# Configure in android/app/build.gradle +``` + +## Testing on Mobile + +### iOS Simulator + +```bash +# List available simulators +xcrun simctl list devices + +# Boot specific simulator +xcrun simctl boot "iPhone 15" + +# Run on simulator +npm run tauri ios dev +``` + +### Android Emulator + +```bash +# List emulators +emulator -list-avds + +# Start emulator +emulator -avd + +# Run on emulator +npm run tauri android dev +``` + +## Common Issues + +**"Team not set" error:** +- Set development team in Xcode +- Enable automatic signing + +**"Device not found" (Android):** +- Enable USB debugging +- Install OEM drivers +- Try different USB cable/port + +**"Provisioning profile error" (iOS):** +- Add device to Apple Developer account +- Update provisioning profiles + +**Build fails with linking errors:** +- Ensure all Rust targets installed +- Clean build: `cargo clean` +- Rebuild project + +## Mobile Best Practices + +1. **Test on real devices** - Simulators don't catch all issues +2. **Optimize bundle size** - Mobile has more constraints +3. **Handle permissions** - Request at appropriate times +4. **Test offline** - Mobile devices have intermittent connectivity +5. **Consider battery** - Avoid constant background operations +6. **Use platform idioms** - Follow iOS/Android design guidelines +7. **Test screen sizes** - Various device form factors +8. **Handle orientation** - Portrait and landscape diff --git a/skills/tauri/examples/plugin-usage.txt b/skills/tauri/examples/plugin-usage.txt new file mode 100644 index 0000000..cff8191 --- /dev/null +++ b/skills/tauri/examples/plugin-usage.txt @@ -0,0 +1,258 @@ +# Tauri Plugin Usage Examples + +## File System Plugin + +### Read File +```typescript +import { readTextFile, BaseDirectory } from '@tauri-apps/plugin-fs'; + +const contents = await readTextFile('config.json', { + dir: BaseDirectory.AppConfig +}); + +// Or with full path +const contents = await readTextFile('/path/to/file.txt'); +``` + +### Write File +```typescript +import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs'; + +await writeTextFile('output.txt', 'Hello, Tauri!', { + dir: BaseDirectory.AppData +}); +``` + +### List Directory +```typescript +import { readDir, BaseDirectory } from '@tauri-apps/plugin-fs'; + +const entries = await readDir('', { + dir: BaseDirectory.Home +}); + +entries.forEach(entry => { + console.log(entry.name); +}); +``` + +## HTTP Plugin + +### GET Request +```typescript +import { fetch } from '@tauri-apps/plugin-http'; + +const response = await fetch('https://api.example.com/data'); +const data = await response.json(); +``` + +### POST Request +```typescript +const response = await fetch('https://api.example.com/create', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ name: 'Tauri App' }) +}); +``` + +### With Options +```typescript +const response = await fetch('https://api.example.com/data', { + method: 'GET', + timeout: 30, // seconds + headers: { + 'Authorization': 'Bearer token123' + } +}); +``` + +## Dialog Plugin + +### Open File Dialog +```typescript +import { open } from '@tauri-apps/plugin-dialog'; + +const selected = await open({ + multiple: false, + filters: [{ + name: 'Text', + extensions: ['txt', 'md'] + }] +}); + +if (selected) { + console.log('Selected:', selected); +} +``` + +### Save File Dialog +```typescript +import { save } from '@tauri-apps/plugin-dialog'; + +const filePath = await save({ + filters: [{ + name: 'JSON', + extensions: ['json'] + }] +}); + +if (filePath) { + // Save file +} +``` + +### Message Dialog +```typescript +import { message } from '@tauri-apps/plugin-dialog'; + +await message('Operation completed successfully!', 'Info'); +``` + +## Notification Plugin + +### Show Notification +```typescript +import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/plugin-notification'; + +// Check permission +let permission = await isPermissionGranted(); +if (!permission) { + permission = await requestPermission(); +} + +// Send notification +if (permission) { + await sendNotification({ + title: 'Hello from Tauri!', + body: 'This is a native notification' + }); +} +``` + +## Shell Plugin + +### Execute Command +```typescript +import { Command } from '@tauri-apps/plugin-shell'; + +const command = Command.create('ls', ['-la']); +const output = await command.execute(); + +console.log('stdout:', output.stdout); +console.log('stderr:', output.stderr); +``` + +### Open External Program +```typescript +import { open } from '@tauri-apps/plugin-shell'; + +await open('https://tauri.app'); +await open('mailto:support@example.com'); +await open('/path/to/file.txt'); +``` + +## Clipboard Plugin + +### Read Clipboard +```typescript +import { readText } from '@tauri-apps/plugin-clipboard-manager'; + +const text = await readText(); +console.log('Clipboard:', text); +``` + +### Write to Clipboard +```typescript +import { writeText } from '@tauri-apps/plugin-clipboard-manager'; + +await writeText('Copied to clipboard!'); +``` + +## Global Shortcut Plugin + +### Register Hotkey +```typescript +import { register, Shortcut } from '@tauri-apps/plugin-global-shortcut'; + +await register(Shortcut.Modifiers, 'CommandOrControl+Shift+X', () => { + console.log('Hotkey pressed!'); +}); +``` + +### Unregister +```typescript +import { unregisterAll } from '@tauri-apps/plugin-global-shortcut'; + +await unregisterAll(); +``` + +## Updater Plugin + +### Check for Updates +```typescript +import { checkUpdate, installUpdate } from '@tauri-apps/plugin-updater'; + +try { + const { manifest, body } = await checkUpdate(); + + if (manifest) { + console.log('Update available:', manifest.version); + + // Install update + await installUpdate(); + + // Restart app + await relaunch(); + } +} catch (error) { + console.error('Update check failed:', error); +} +``` + +## OS Plugin + +### Platform Info +```typescript +import { platform, version, arch, tempdir } from '@tauri-apps/plugin-os'; + +console.log('Platform:', platform()); +console.log('Version:', version()); +console.log('Architecture:', arch()); +console.log('Temp dir:', tempdir()); +``` + +## Window Management + +### Window Controls +```typescript +import { getCurrentWindow } from '@tauri-apps/api/window'; + +const window = getCurrentWindow(); + +await window.setTitle('New Title'); +await window.setMaximizable(false); +await window.setResizable(true); +await window.minimize(); +await window.maximize(); +await window.unmaximize(); +await window.close(); +``` + +### Window Events +```typescript +import { getCurrentWindow } from '@tauri-apps/api/window'; + +const window = getCurrentWindow(); + +window.onResized(({ payload }) => { + console.log('New size:', payload); +}); + +window.onFileDropEvent((event) => { + event.payload.paths.forEach(path => { + console.log('Dropped:', path); + }); +}); +``` diff --git a/skills/tauri/skill.md b/skills/tauri/skill.md new file mode 100644 index 0000000..03f549b --- /dev/null +++ b/skills/tauri/skill.md @@ -0,0 +1,353 @@ +--- +description: "Comprehensive Tauri framework development companion - Build tiny, fast, secure desktop & mobile apps with Rust backend and web frontend. Covers: Tauri 2.0, project scaffolding, IPC commands, native APIs, cross-platform builds, mobile support, security, distribution." +disable-model-invocation: false +--- + +# Tauri Framework Development + +**Your expert companion for building applications with [Tauri](https://tauri.app/)** - the framework that lets you build smaller, faster, and more secure desktop and mobile applications with a web frontend. + +## Quick Start + +```bash +# Create a new Tauri app +npm create tauri-app@latest + +# Or use the /tauri-init command for guided setup +/tauri-init +``` + +## What is Tauri? + +Tauri is a framework for building tiny, blazingly fast binaries for all major desktop and mobile platforms. Developers can integrate any front-end framework that compiles to HTML, JS, and CSS for the user interface. The backend is a Rust-sourced binary with an API that the front-end can interact with. + +**Key advantages:** +- 🔥 **Smaller binaries** - 10-100x smaller than Electron apps +- ⚡ **Faster** - Uses system webviews (WebView2, WebKit, WKWebView) +- 🔒 **More secure** - Built-in security audits, capability-based permissions +- 🌍 **Cross-platform** - Windows, macOS, Linux, iOS, Android +- 🦀 **Rust backend** - Memory safety, performance, system access + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────────┐ +│ Tauri Application │ +├─────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────────┐ ┌──────────────────┐ │ +│ │ Frontend │ │ Rust Backend │ │ +│ │ (WebView) │◄───────►│ (src-tauri/) │ │ +│ │ │ IPC │ │ │ +│ │ React/Vue/ │ │ - Commands │ │ +│ │ Svelte/Solid │ │ - Events │ │ +│ │ Vanilla JS │ │ - Plugins │ │ +│ └──────────────────┘ │ - Resources │ │ +│ └──────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ System WebView (WRY) │ │ +│ │ Windows: WebView2 | macOS: WKWebKit | Linux: WebKitGTK │ +│ └──────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────┘ +``` + +## Available Commands + +| Command | Purpose | +|---------|---------| +| `/tauri-init` | Initialize new Tauri project with guided setup | +| `/tauri-add-plugin` | Add Tauri plugin (fs, http, shell, etc.) | +| `/tauri-build` | Build for specific platform with optimizations | +| `/tauri-capability` | Create permission capability file | +| `/tauri-ipc` | Design IPC interface between Rust and web | +| `/tauri-native` | Add native feature (tray, notifications, etc.) | + +## When to Use This Skill + +Invoke this skill when: +- Building cross-platform desktop applications +- Creating mobile apps with Rust backend +- Migrating from Electron to Tauri +- Need native system access from web app +- Implementing system tray or notifications +- Designing IPC between Rust and JavaScript +- Setting up Tauri 2.0 mobile apps +- Configuring build and distribution + +**Auto-triggers on:** +- "tauri app", "create-tauri-app", "tauri://" +- "desktop app with rust", "tauri command" +- "system tray desktop", "rust webview app" +- "tauri.conf.json", "src-tauri/" +- "invoke tauri", "tauri event" + +## Core Concepts + +### 1. Project Structure + +``` +my-tauri-app/ +├── src/ # Frontend source (your framework) +├── src-tauri/ # Rust backend +│ ├── Cargo.toml # Rust dependencies +│ ├── tauri.conf.json # Tauri configuration +│ ├── capabilities/ # Permission definitions +│ ├── src/ # Rust source code +│ │ ├── main.rs # Entry point +│ │ ├── lib.rs # Library exports +│ │ └── commands.rs # Your commands +│ └── icons/ # App icons +├── package.json # Frontend dependencies +└── tauri.conf.json # Frontend Tauri config +``` + +### 2. IPC Communication + +**Frontend → Rust (Commands):** +```typescript +import { invoke } from '@tauri-apps/api/core'; + +// Call Rust command +const result = await invoke('my_command', { param: 'value' }); +``` + +**Rust → Frontend (Events):** +```rust +use tauri::Emitter; + +// Emit event to frontend +window.emit("my-event", Payload { data: "value" })?; +``` + +**Frontend (Listen):** +```typescript +import { listen } from '@tauri-apps/api/event'; + +const unlisten = await listen('my-event', (event) => { + console.log(event.payload); +}); +``` + +### 3. Commands (Rust) + +```rust +#[tauri::command] +fn my_command(param: String) -> Result { + Ok(format!("Received: {}", param)) +} + +// Register in main.rs +fn main() { + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![ + my_command, + // other commands... + ]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +### 4. Capabilities & Permissions + +**Tauri 2.0 Security Model:** + +Create `capabilities/default.json`: +```json +{ + "identifier": "default", + "description": "Default capabilities", + "windows": ["main"], + "permissions": [ + "core:default", + "fs:read-file", + "fs:write-file", + "dialog:default" + ] +} +``` + +### 5. Configuration + +**tauri.conf.json key settings:** +```json +{ + "productName": "MyApp", + "version": "1.0.0", + "identifier": "com.example.myapp", + "build": { + "beforeDevCommand": "npm run dev", + "beforeBuildCommand": "npm run build", + "frontendDist": "../dist", + "withGlobalTauri": true + }, + "app": { + "windows": [{ + "title": "MyApp", + "width": 1200, + "height": 800, + "resizable": true, + "fullscreen": false + }] + }, + "bundle": { + "active": true, + "targets": ["dmg", "msi", "appimage", "deb"], + "icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png"] + } +} +``` + +## Platform Support + +### Desktop Platforms + +| Platform | Min Version | WebView | +|----------|-------------|---------| +| Windows | 7+ | WebView2 | +| macOS | 10.15+ | WKWebView | +| Linux | Ubuntu 18.04+ | WebKitGTK 4.1 | + +### Mobile Platforms (Tauri 2.0) + +| Platform | Min Version | WebView | +|----------|-------------|---------| +| iOS | 9+ | WKWebView | +| Android | 7+ (8+ recommended) | Android System WebView | + +## Common Plugins + +| Plugin | Purpose | +|--------|---------| +| `@tauri-apps/plugin-fs` | File system access | +| `@tauri-apps/plugin-http` | HTTP requests | +| `@tauri-apps/plugin-shell` | Shell command execution | +| `@tauri-apps/plugin-dialog` | File dialogs | +| `@tauri-apps/plugin-notification` | Native notifications | +| `@tauri-apps/plugin-global-shortcut` | Global hotkeys | +| `@tauri-apps/plugin-os` | Operating system info | +| `@tauri-apps/plugin-process` | Process management | +| `@tauri-apps/plugin-clipboard-manager` | Clipboard access | +| `@tauri-apps/plugin-updater` | Auto-update functionality | + +## Build & Distribution + +### Development +```bash +# Run dev server +npm run tauri dev + +# With Tauri CLI +cargo tauri dev +``` + +### Building +```bash +# Build for current platform +npm run tauri build + +# Build for specific target +cargo tauri build --target universal-apple-dmg +cargo tauri build --target nsis # Windows installer +cargo tauri build --target appimage # Linux +``` + +### Code Signing + +**macOS:** +```bash +# Sign and notarize +cargo tauri build --target universal-apple-dmg +``` + +**Windows:** +```bash +# Sign with certificate +cargo tauri signer sign +``` + +## Integration with Other Skills + +- **rust-patterns** - Rust code quality and patterns +- **react-dev** / **vue** / **svelte** - Frontend framework guidance +- **architecture** - System architecture decisions +- **test-driven-development** - Testing patterns for Rust +- **api-patterns** - Design command interfaces +- **ui-ux-pro-max** - Desktop UI/UX considerations + +## Troubleshooting + +**Common issues:** + +**WebView not loading:** +- Check `frontendDist` path in tauri.conf.json +- Verify `beforeBuildCommand` runs successfully +- Check browser console for errors + +**Command not found:** +- Ensure command is registered in `invoke_handler` +- Check function signature matches `#[tauri::command]` +- Verify frontend import path + +**Build failures:** +- Check Rust version: `rustc --version` (need 1.70+) +- Verify Node.js version: `node --version` (need 18+) +- Try cleaning: `cargo clean && cargo tauri build` + +**Mobile build issues:** +- Ensure Xcode / Android Studio installed +- Check mobile targets in tauri.conf.json +- Verify Rust targets installed: `rustup target add aarch64-apple-ios` + +## Best Practices + +1. **Use TypeScript** for type-safe IPC +2. **Generate types** with `@tauri-apps/cli` +3. **Handle errors** in all commands (return `Result`) +4. **Use capabilities** for security (don't allow everything) +5. **Test on all target platforms** early +6. **Optimize bundle size** (tree-shake frontend) +7. **Use async** for long-running operations +8. **Log appropriately** for debugging +9. **Version control** both frontend and Rust +10. **Follow Tauri conventions** for consistency + +## Resources + +### Official Documentation +- [Tauri Documentation](https://v2.tauri.app/) +- [Tauri GitHub](https://github.com/tauri-apps/tauri) +- [Tauri Guides](https://v2.tauri.app/start/) +- [Tauri Architecture](https://v2.tauri.app/concept/architecture/) + +### Community +- [Tauri Discord](https://discord.gg/tauri) +- [GitHub Discussions](https://github.com/tauri-apps/tauri/discussions) +- [Stack Overflow](https://stackoverflow.com/questions/tagged/tauri) + +### Examples +- [Tauri Examples](https://github.com/tauri-apps/tauri/tree/dev/examples) +- [Community Projects](https://tauri.app/showcase) + +## Credits + +### Tauri Framework + +**Tauri** is developed by The Tauri Programme within The Commons Conservancy. + +- **GitHub**: https://github.com/tauri-apps/tauri +- **Website**: https://tauri.app/ +- **License**: MIT / Apache 2.0 + +**Core Team:** +- Original Tauri Logo Designs by Alve Larsson, Daniel Thompson-Yvetot and Guillaume Chau +- Full contributor list: https://github.com/tauri-apps/tauri/graphs/contributors + +**Key Dependencies:** +- **WRY** - WebView library: https://github.com/tauri-apps/wry +- **TAO** - Window handling: https://github.com/tauri-apps/tao +- **Tauri CLI** - Command-line tools + +This skill builds on the excellent work of the Tauri open-source community. diff --git a/skills/tauri/templates/capabilities/default.json b/skills/tauri/templates/capabilities/default.json new file mode 100644 index 0000000..560b733 --- /dev/null +++ b/skills/tauri/templates/capabilities/default.json @@ -0,0 +1,26 @@ +{ + "identifier": "default", + "description": "Default capabilities for the application", + "windows": ["main"], + "permissions": [ + "core:default", + "core:window:default", + "core:window:allow-center", + "core:window:allow-maximize", + "core:window:allow-minimize", + "core:window:allow-unmaximize", + "core:window:allow-unminimize", + "dialog:default", + "fs:read-file", + "fs:write-file", + "fs:read-dir", + "fs:scope:read-file", + "fs:scope:write-file", + "fs:scope:read-dir", + "http:default", + "notification:default", + "shell:default", + "clipboard-manager:default", + "global-shortcut:default" + ] +} diff --git a/skills/tauri/templates/capabilities/fs-full.json b/skills/tauri/templates/capabilities/fs-full.json new file mode 100644 index 0000000..77111a5 --- /dev/null +++ b/skills/tauri/templates/capabilities/fs-full.json @@ -0,0 +1,24 @@ +{ + "identifier": "fs-full", + "description": "Full file system access - use with caution", + "windows": ["main"], + "permissions": [ + "fs:read-file", + "fs:write-file", + "fs:read-dir", + "fs:copy-file", + "fs:remove", + "fs:rename", + "fs:exists", + "fs:scope:read-file", + "fs:scope:write-file", + "fs:scope:read-dir", + "fs:scope:copy-file", + "fs:scope:remove", + "fs:scope:rename", + "fs:scope:exists", + "path:default", + "path:resolve", + "path:resolve-directory" + ] +} diff --git a/skills/tauri/templates/capabilities/network.json b/skills/tauri/templates/capabilities/network.json new file mode 100644 index 0000000..eba5eba --- /dev/null +++ b/skills/tauri/templates/capabilities/network.json @@ -0,0 +1,21 @@ +{ + "identifier": "network-full", + "description": "Full network access capabilities", + "windows": ["main"], + "permissions": [ + "http:default", + "http:allow-fetch", + "http:allow-fetch-cancel", + "http:allow-fetch-read-body", + "http:allow-fetch-send", + "http:allow-request", + "http:allow-fetch-delete", + "http:allow-fetch-post", + "http:allow-fetch-put", + "http:allow-fetch-patch", + "http:allow-fetch-head", + "http:allow-fetch-options", + "http:allow-fetch-connect", + "http:allow-fetch-trace" + ] +} diff --git a/skills/tauri/templates/src-tauri/commands/mod.rs b/skills/tauri/templates/src-tauri/commands/mod.rs new file mode 100644 index 0000000..3eefd61 --- /dev/null +++ b/skills/tauri/templates/src-tauri/commands/mod.rs @@ -0,0 +1,63 @@ +// Tauri Commands Module +// This module contains all the commands exposed to the frontend + +use serde::{Deserialize, Serialize}; + +/// Common result type for commands +pub type CommandResult = Result; + +/// Example payload structure +#[derive(Debug, Serialize, Deserialize)] +pub struct ExamplePayload { + pub data: String, + pub count: i32, +} + +// Basic example command +#[tauri::command] +pub fn greet(name: &str) -> CommandResult { + Ok(format!("Hello, {}! From Rust backend!", name)) +} + +// Example with structured payload +#[tauri::command] +pub fn process_data(payload: ExamplePayload) -> CommandResult { + Ok(format!("Processed: {} (count: {})", payload.data, payload.count)) +} + +// Async command example +#[tauri::command] +pub async fn async_operation(input: String) -> CommandResult { + // Simulate async work + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + Ok(format!("Async result from: {}", input)) +} + +// Error handling example +#[tauri::command] +pub fn command_with_error(should_fail: bool) -> CommandResult { + if should_fail { + Err("This command failed as requested".to_string()) + } else { + Ok("Command succeeded!".to_string()) + } +} + +// Complex command with multiple parameters +#[tauri::command] +pub fn complex_command( + text: String, + number: i32, + flag: bool, +) -> CommandResult { + Ok(format!( + "Text: {}, Number: {}, Flag: {}", + text, number, flag + )) +} + +// Export all commands +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + // This function is called on mobile platforms +} diff --git a/skills/tauri/templates/src-tauri/events.rs b/skills/tauri/templates/src-tauri/events.rs new file mode 100644 index 0000000..bbed136 --- /dev/null +++ b/skills/tauri/templates/src-tauri/events.rs @@ -0,0 +1,70 @@ +// Tauri Events Module +// This module demonstrates event emission from Rust to the frontend + +use serde::{Deserialize, Serialize}; +use tauri::{Emitter, EmitterExt}; + +/// Example event payload +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProgressEvent { + pub current: u32, + pub total: u32, + pub message: String, +} + +/// Emit a progress event +pub fn emit_progress(app: &tauri::AppHandle, current: u32, total: u32, message: &str) -> tauri::Result<()> { + app.emit("progress", ProgressEvent { + current, + total, + message: message.to_string(), + }) +} + +/// Emit a data update event +pub fn emit_data_update(app: &tauri::AppHandle, data: &str) -> tauri::Result<()> { + #[derive(Serialize)] + struct DataUpdate { + data: String, + timestamp: u64, + } + + app.emit("data-update", DataUpdate { + data: data.to_string(), + timestamp: std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(), + }) +} + +/// Emit an error event +pub fn emit_error(app: &tauri::AppHandle, error: &str) -> tauri::Result<()> { + #[derive(Serialize)] + struct ErrorEvent { + error: String, + timestamp: u64, + } + + app.emit("error", ErrorEvent { + error: error.to_string(), + timestamp: std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(), + }) +} + +/// Emit a notification event +pub fn emit_notification(app: &tauri::AppHandle, title: &str, body: &str) -> tauri::Result<()> { + #[derive(Serialize)] + struct NotificationEvent { + title: String, + body: String, + } + + app.emit("notification", NotificationEvent { + title: title.to_string(), + body: body.to_string(), + }) +} diff --git a/skills/tauri/templates/tauri.conf.json b/skills/tauri/templates/tauri.conf.json new file mode 100644 index 0000000..827c6d0 --- /dev/null +++ b/skills/tauri/templates/tauri.conf.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://schema.tauri.app/config/2.0.0", + "productName": "My Tauri App", + "version": "1.0.0", + "identifier": "com.example.my-tauri-app", + "build": { + "beforeDevCommand": "npm run dev", + "beforeBuildCommand": "npm run build", + "frontendDist": "../dist", + "withGlobalTauri": true + }, + "app": { + "windows": [ + { + "title": "My Tauri App", + "width": 1200, + "height": 800, + "resizable": true, + "fullscreen": false, + "center": true, + "decorations": true, + "transparent": false, + "alwaysOnTop": false, + "skipTaskbar": false + } + ], + "security": { + "csp": null, + "dangerousDisableAssetCspModification": false + } + }, + "bundle": { + "active": true, + "targets": ["dmg", "msi", "appimage", "deb"], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "publisher": "Example Publisher", + "copyright": "", + "category": "Productivity", + "shortDescription": "My amazing Tauri application", + "longDescription": "A comprehensive desktop application built with Tauri", + "macOS": { + "frameworks": [], + "minimumSystemVersion": "10.15", + "exceptionDomain": "", + "signingIdentity": null, + "entitlements": null, + "providerShortName": null, + "standalone": false + }, + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + } + }, + "plugins": {} +}