tuffite0.1
A FOUNDATION FOR YOUR NEXT APP

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.

typescript
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.

rust
#[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.

javascript
import './generated/index.js';
const answer = await window.myapp.commands.ping('Tuffite');