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 <noreply@anthropic.com>
This commit is contained in:
uroma
2026-01-23 18:39:20 +00:00
Unverified
parent cd5c39811d
commit 51ae409ecb
11 changed files with 1359 additions and 0 deletions

View File

@@ -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<ExamplePayload>('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<string>('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
});
```

View File

@@ -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<ProgressPayload>('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();
```

View File

@@ -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
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
```
Add to `ios/Runner/Info.plist`:
```xml
<key>NSCameraUsageDescription</key>
<string>We need camera access</string>
```
### 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 <name>
# 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

View File

@@ -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);
});
});
```