"A command is just a Rust function with a sticker on it — and a name on a list. Miss the list and it vanishes."
Two Steps, Always Both
Exposing native power to your frontend is two steps, and forgetting the second is the most common beginner bug:
- Mark the function with the
#[tauri::command]attribute. This tells Tauri's macro machinery to generate the IPC glue for it. - Register it in
tauri::generate_handler![]inside your Builder. This is what actually puts the command in the router the webview talks to.
Do step 1 but not step 2 and you'll get a runtime error like 'command greet not found' — the function exists, but nothing wired it into the bridge. Whenever a command 'isn't found,' check the handler list first.
What a Command Can Take and Return
Command parameters can be plain types (String, numbers, booleans), your serde structs, or special Tauri types you'll meet later (State, AppHandle, Window). The return type is whatever serializes — a value for an infallible command, or Result<T, E> for one that can fail. Tauri injects the special types automatically; you only pass the data arguments from the frontend.
The Classic First Command
Every Tauri project starts with a greet command, and it's worth typing once to feel the whole loop: a function in Rust, a sticker, a name on the list, and an invoke from the web side (next lesson). Once you've felt one command travel the bridge, every other command is the same shape with different cargo.