Getting Started
This tutorial walks you through building a full-stack application with Tairitsu. You'll learn how a single WASM component can run both in the browser and on the server.
What You'll Build
A simple single-page guestbook application — server-side rendering with client-side interactivity.
Table of Contents
- 1Why Tairitsu?
- 2Installation
- 3Your First Component
- 4Adding State with Signals
- 5Defining a WIT Interface
- 6Running in the Browser
- 7Server-Side Rendering
- 8Deploying to a Registry
- 9Where to Go Next
Why Tairitsu?
Traditional web frameworks keep server and client as separate concerns:
Tairitsu uses the WASM Component Model to define a single WIT interface that both sides implement:
The same component renders HTML on the server and handles click events in the browser — through the same typed interface.
Installation
# Install Rust
|
# Install just (task runner)
# Install the WASM target
# Build and install the Tairitsu CLI
# Verify
Your First Component
Create a new project:
Edit src/lib.rs:
use ;
use VNode;
Start the dev server:
Open http://localhost:3000. You'll see your component rendered in the browser.
What's Happening Under the Hood
- 1The Rust code is compiled to wasm32-wasip2 as a WASM component
- 2tairitsu dev starts an axum server that instantiates the component
- 3The component renders its VDOM tree
- 4browser-glue bridges WIT ABI calls to real DOM operations
- 5The browser displays the HTML
Adding State with Signals
Tairitsu uses Signals for reactive state — similar to SolidJS or Leptos.
use ;
use ;
Key concepts:
- Signal::new(value) — create reactive state
- signal.get() — read current value (subscribes to changes)
- signal.set(new_value) — update value (triggers re-render)
- signal.clone() — cheap Arc-based clone for sharing across closures
Effects
React to signal changes:
use create_effect;
let count = new;
let count_clone = count.clone;
create_effect;
Defining a WIT Interface
WIT (WebAssembly Interface Types) defines the contract between your component and the host:
// wit/guestbook.wit
interface guestbook {
record entry {
id: u32,
name: string,
message: string,
}
list-entries: func() -> result<list<entry>, string>;
add-entry: func(name: string, message: string) -> result<entry, string>;
}
Use wit_interface! to generate Rust bindings:
use wit_interface;
wit_interface!
Running in the Browser
For browser-only execution (no server):
Your component runs entirely client-side. Uses the WebPlatform backend (web-sys) for DOM operations.
Server-Side Rendering
For production SSR:
The component renders to HTML on the server, sends it to the browser, then hydrates for interactivity. The same component code handles both phases.
Streaming SSR
Enable streaming for progressive HTML delivery:
# Cargo.toml
[dependencies]
tairitsu-ssr = { features = ["streaming"] }
// Server streams HTML as it renders
app.render_to_stream.await
Deploying to a Registry
Build and push your component:
On any wasmtime-compatible host:
use ;
let mut registry = new;
registry.pull.await?;
let container = registry.run?;
// Call into the component dynamically
let result = container.call_guest_raw_desc?;
Where to Go Next
| Topic | Document |
|---|---|
| All hooks (use_memo, use_resource, Suspense) | hooks API |
| Styling with scss! macro | style crate |
| Routing | Router module |
| WIT pipeline internals | WIT Pipeline |
| Debugging with MCP | Debug Agent |