Adding New Tauri Commands
This guide walks through adding a new backend command that the React frontend can call. The process touches both the Rust backend and the TypeScript bridge layer.
Overview
The communication flow:
React component → getBackend().someApi.method()
→ TauriAdapter → invoke("command_name", { args })
→ Rust #[tauri::command] fn command_name()Step 1: Add the Rust Command
Create the command function with the #[tauri::command] attribute in the appropriate file under tauri-.
For example, to add a command to commands/:
#[tauri::command]
pub fn example_get_count(
state: tauri::State<'_, AppState>,
) -> Result<usize, String> {
let project_root = state.project_root.lock().unwrap();
// ... implementation
Ok(42)
}Commands can:
Accept
tauri::State<AppState>to access shared stateAccept
tauri::Windowfor window operationsReturn
Result<T, String>for error handlingAccept any
serde::Deserializearguments
Step 2: Register in lib.rs
Add the command to the generate_handler![] macro in tauri-:
.invoke_handler(tauri::generate_handler![
// ... existing commands
commands::files::example_get_count,
])Step 3: Add to BackendAPI Interface
Add the method signature to the BackendAPI interface in packages/:
export interface BackendAPI {
// ... existing APIs
example: {
getCount: () => Promise<number>;
};
}Step 4: Implement in TauriAdapter
Add the real implementation in packages/ that calls invoke():
export function createTauriAdapter(): BackendAPI {
return {
// ... existing adapters
example: {
getCount: () => invoke<number>("example_get_count"),
},
};
}The invoke() function maps to the Rust command name. Arguments are passed as a single object:
// TypeScript
invoke<boolean>("messages_write", { filename, content });
// Maps to Rust
#[tauri::command]
pub fn messages_write(filename: String, content: String) -> Result<bool, String>Step 5: Implement in MockAdapter
Add a mock implementation in packages/ so the command works in tests and Storybook:
example: {
getCount: async () => {
return files.size;
},
},Step 6: Call from React
Use getBackend() to access the API from any React component:
import { getBackend } from "@takazudo/backend-bridge";
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
getBackend().example.getCount().then(setCount);
}, []);
return <div>Count: {count}</div>;
}The getBackend() function returns the initialized backend adapter — TauriAdapter in the real app, or MockAdapter in tests.
Checklist
When adding a new command, make sure you have:
Rust function with
#[tauri::command]attributeCommand registered in
lib.rsgenerate_handler![]Type added to
BackendAPIinterface intypes.tsImplementation in
TauriAdapter(tauri-adapter.ts)Mock implementation in
MockAdapter(mock-adapter.ts)REST implementation in
RestAdapter(rest-adapter.ts) if applicableFrontend code calling via
getBackend()