Call Rust from the frontend
Declare once. Generate bindings. Register a typed handler.
Experimental source release. Production hardening and published SDK packages are still in progress.
Declare the contract#
List the declaration in build.shellApi.definitions and set build.shellApi.namespace to myapp. tuff dev regenerates bindings as the contract changes; tuff build and tuff package also generate them automatically. The generator derives binary codecs and command identities from the typed declaration.
export namespace myapp {
export namespace commands {
export function ping(message: string): Promise<string>;
}
}Register the handler#
The Rust handler accepts generated endpoint argument types. generate_handler! checks that handlers belong to the same application and builds the dispatch registry. Duplicate registration or mismatched endpoint shapes fail validation.
#[tuffite::command(shell_api::commands::Ping)]
fn ping(_app: &mut App, message: String) -> Result<String, tuffite::CommandError> {
Ok(format!("Hello, {message}"))
}
// Register explicitly in the exported Builder:
// .commands(tuffite::generate_handler![ping])Invoke the generated facade#
The application facade uses the bundled framework transport. Permit the canonical method or a suitable pattern such as myapp.* in a capability matching the frontend origin. Import the generated module before accessing the facade.
import './generated/index.js';
const answer = await window.myapp.commands.ping('Tuffite');