Local-First Desktop Tool
This walkthrough traces a small Tauri app that stores local data and exports files.
Flow
User clicks "Save"
-> React form validates obvious UI errors
-> `saveRecord()` frontend wrapper calls `invoke`
-> Rust command validates payload and app state
-> Rust writes through SQLite/store/filesystem layer
-> Command returns serializable response
-> UI updates local view
Files
src/records/RecordForm.tsx
src/tauri-api.ts
src-tauri/src/commands.rs
src-tauri/src/state.rs
src-tauri/capabilities/default.json
src-tauri/tauri.conf.json
Native Boundary
The frontend can ask to save a record. It cannot choose arbitrary filesystem paths, spawn processes, or write directly to app data.
Rust owns:
- Payload validation beyond UI convenience checks.
- App data directory selection.
- Database or store migration rules.
- Export path validation.
- Error messages safe for the UI.
Capability Review
Start with core:default. Add filesystem, SQL, store, dialog, or opener permissions only if the implementation actually uses official plugins for those operations.
If the app exports files, prefer a Rust command that receives a user-approved path from a dialog flow rather than a renderer-controlled arbitrary path.
Test Walkthrough
frontend test: form calls wrapper with expected payload
mockIPC test: wrapper uses expected command and handles errors
Rust test: invalid payload rejected
Rust test: export path validation rejects traversal or empty path
release smoke: save, restart, load, export
Release Walkthrough
build release artifact
launch without dev server
create record
restart app
verify record persists
export file
inspect logs
record signing and WebView2 state