tauri-development
SKILL.md
Tauri Development Skill
Expert guidance for Tauri 2.0 desktop application development with Rust backend and React TypeScript frontend.
Overview
This skill provides comprehensive guidance for:
- Creating Tauri commands with proper specta type binding
- Integrating Rust backend with React TypeScript frontend
- Handling desktop-specific patterns and constraints
- Optimizing frontend-backend communication
- Following Tauri 2.0 best practices
When This Skill Applies
This skill activates when:
- Creating or modifying Tauri commands
- Setting up specta type bindings
- Debugging frontend-backend communication issues
- Implementing desktop-specific features
- Optimizing Tauri application performance
- Handling Tauri-specific error cases
Core Tauri Principles
Command Definition Pattern
All Tauri commands must follow this pattern:
use serde::{Deserialize, Serialize};
use specta::Type;
#[derive(Serialize, Deserialize, Type, Clone)]
#[specta(inline)]
pub struct MyDto {
pub field: String,
}
#[tauri::command]
#[specta::specta]
pub async fn my_command(
dto: MyDto,
state: State<'_, TauriAppState>,
) -> ApiResponse<ResultType> {
// Implementation
}
Key Requirements:
#[tauri::command]- Required for all commands#[specta::specta]- Required for TypeScript type generation#[specta(inline)]- Required on DTOs for proper type exportApiResponse<T>- Unified return type for error handling
Frontend Command Usage
✓ Correct:
import { commands } from '../bindings';
const result = await commands.myCommand({ field: "value" });
if (!result.success) {
message.error(result.message);
return;
}
const data = result.data;
✗ Incorrect:
// ✗ Don't use raw invoke
import { invoke } from '@tauri-apps/api/core';
const result = await invoke('my_command', { dto });
Common Patterns
State Management
Use dependency injection for services:
pub struct TauriAppState {
pub db: Arc<SqlitePool>,
pub material_service: Arc<MaterialService>,
}
pub async fn get_state() -> TauriAppState {
TauriAppState {
db: Arc::new(pool),
material_service: Arc::new(MaterialService::new(pool)),
}
}
Error Handling
Always use ApiResponse for top-level commands:
use crate::utils::error::{api_err, api_ok, ApiResponse};
#[tauri::command]
#[specta::specta]
pub async fn some_command() -> ApiResponse<Data> {
match inner_logic().await {
Ok(data) => api_ok(data),
Err(e) => api_err(format!("操作失败: {}", e)),
}
}
Async/Await Best Practices
- Use
asyncfor external-facing commands - Use sync functions for pure computations
- Never block the async runtime with
std::thread::sleep - Use
tokio::time::sleepinstead
Tauri-Specific Considerations
Desktop Application Constraints
- No console.log - Use Ant Design message components
- File paths - Use
path.resolvefor cross-platform compatibility - Native dialogs - Use Tauri APIs for file dialogs
- System integration - Leverage native OS features
Performance Optimization
- Use
moka::future::Cachefor frequently accessed data - Implement proper connection pooling for SQLite
- Use
rayonfor CPU-intensive parallel computations - Minimize bridge calls between frontend and backend
Security Considerations
- Validate all user input on both frontend and backend
- Use SQL parameter binding (never string concatenation)
- Sanitize file paths to prevent directory traversal
- Implement proper error handling without exposing sensitive info
Common Pitfalls
❌ Blocking Async Runtime
// ✗ Blocks entire runtime
pub async fn bad() {
std::thread::sleep(Duration::from_secs(1));
}
✅ Proper Async Sleep
// ✓ Async-friendly
pub async fn good() {
tokio::time::sleep(Duration::from_secs(1)).await;
}
❌ SELECT * in Queries
// ✗ Inefficient, unclear
sqlx::query_as!("SELECT * FROM materials WHERE code = ?", code)
✅ Explicit Column Selection
// ✓ Clear intent, optimized
sqlx::query_as!(
Material,
"SELECT code, name, price FROM materials WHERE code = ?",
code
)
Type Generation Workflow
- Define Rust types with
#[specta::specta]and#[specta(inline)] - Run
npm run tauri buildor development server - Types are automatically generated in
frontend/src/bindings.ts - Import and use types in TypeScript code
Testing Guidelines
Backend Testing
- Unit tests for pure functions
- Integration tests for database operations
- Use test database fixtures
Frontend Testing
- Test command success/error paths
- Mock Tauri commands in tests
- Verify type safety across the bridge
When to Use This Skill
Activate this skill when:
- Creating or modifying Tauri commands
- Debugging frontend-backend communication
- Optimizing Tauri application performance
- Handling Tauri-specific error cases
- Planning new features with Tauri constraints
Quick Reference
Essential Tauri Command Template
#[tauri::command]
#[specta::specta]
pub async fn command_name(
dto: RequestDto,
state: State<'_, TauriAppState>,
) -> ApiResponse<ResponseData> {
with_service(state, |ctx| async move {
ctx.service.do_work(dto).await
})
.await
}
Frontend Command Call Template
import { commands } from '../bindings';
const result = await commands.commandName({ field: "value" });
if (!result.success) {
message.error(result.message);
return;
}
const data = result.data;
Required Attributes Checklist
-
#[tauri::command]on all commands -
#[specta::specta]on all commands -
#[specta(inline)]on all DTOs - Return type
ApiResponse<T> - Use
commandsfrom bindings (notinvoke) - Handle errors with message component
- No console.log in desktop app
Common Issues & Solutions
| Issue | Solution |
|---|---|
| Types not generated | Run dev server or rebuild |
| Command not found | Check #[tauri::command] attribute |
| Type mismatch | Verify #[specta(inline)] on DTOs |
| Runtime blocking | Use async/await, not blocking calls |
| Console logs in app | Use message component instead |
Frontmatter Fields Summary
| Field | Value | Purpose |
|---|---|---|
#[tauri::command] |
- | Exposes function to frontend |
#[specta::specta] |
- | Enables type generation |
#[specta(inline)] |
- | Inlines type in bindings.ts |
ApiResponse<T> |
- | Unified error handling |
Additional Resources
Project References
Official Documentation
Weekly Installs
2
Repository
cacr92/wereplyGitHub Stars
1
First Seen
5 days ago
Security Audits
Installed on
amp2
cline2
openclaw2
opencode2
cursor2
kimi-cli2