Client components (TypeScript)

Ship prebuilt TypeScript widgets alongside resumable Rust UI — Three.js, charts, editors — without forcing them through rs2js or #[island].

When to use

  • Heavy third-party JS (Three.js, WebGPU, D3, Monaco)
  • Canvas/WebGL widgets with their own render loop
  • Code you prefer to author in TypeScript rather than js!

For counters, forms, filters, and most UI — stick with #[component] + resumable handlers. Client components complement resumability; they do not replace it.

Product map

LayerBrand nameRust / TSRole
CoreResumaresumaSignals, view!, resumability, runtime
Full-stackResuma Flowresuma::flowPages, routing, loaders, actions
Compile-timeResuma Macrosresuma-macrosview!, #[component], rs2js
Browser runtimeResuma Runtimeruntime/loader.js + core.js resumability
TS widgetsResuma Clientclient/resuma-client.tsbootClientComponent mount contract

1. TypeScript entry

// client/components/hero-particles.ts
import { bootClientComponent } from '../resuma-client';

function initHeroParticles(root: HTMLElement) {
  // mount canvas, WebGPU/WebGL, return cleanup
  return () => { /* dispose */ };
}

bootClientComponent('hero-particles', initHeroParticles);

2. Rust mount point

use resuma::prelude::*;

FlowApp::new()
    .client_asset("hero-particles", include_bytes!("../static/client/hero-particles.js"))
    // …
    .page("/", || view! {
        {client_component(
            ClientComponent::new("hero-particles").class("hero-particles")
        )}
    })

3. Build client bundles

npm install
npm run build:client   # esbuild: client/components/*.ts → static/client/*.js
cargo run

Mount contract

Rust emits a mount root + module script:

<div data-r-client="hero-particles" id="r-client-hero-particles" class="hero-particles"></div>
    <script type="module" src="/static/client/hero-particles.js" defer></script>

Optional props via ClientComponent::props(...)data-r-client-props JSON on the root element.

Live example

This docs site uses hero-particles on the home page — WebGPU particles with WebGL fallback, built from TypeScript in client/components/hero-particles.ts.

See also

  • Islands — lazy resumable boundaries for Rust UI
  • js! — inline client JS from Rust handlers
  • Package overview — Resuma vs Resuma Flow vs Macros