Remote Session
A remote session mirrors a scene that lives on a server. The server owns the real VTK pipeline; the browser receives serialized object state plus binary blobs, registers them into a local WebAssembly scene, and renders. This is the model used by trame and the data viewer.
Use a remote session when the data is large, generated server-side, or shared across clients. For purely in-browser work, reach for a Standalone Session instead.
Create one from a runtime:
import { loadAsync } from "@kitware/vtk-wasm";
const runtime = await loadAsync({ url: VTK_WASM_BUNDLE_URL });
const remote = runtime.createRemoteSession();Wire up the network
A remote session does not know how to reach your server. You supply three async fetchers through bindNetwork — one for state, one for blobs, one for status — and the session calls them whenever it needs data:
remote.bindNetwork(fetchState, fetchHash, fetchStatus);Each fetcher wraps one server RPC. The trame server side lives in protocol.py; a typical client implementation just forwards the arguments over your transport (e.g. session.call("vtklocal.get.state", [vtkId])).
fetchState(vtkId) => Promise<string>— given an object id, return that object's serialized state as a JSON string (the wire format). Backsvtklocal.get.state.fetchHash(hash) => Promise<Uint8Array>— given a content hash, return the corresponding binary blob. The transport may hand you aBlobor aTypedArray, so convert the result to aUint8Arraybefore returning. Backsvtklocal.get.hash.fetchStatus(renderWindowId) => Promise<Status>— given a render window id, return a manifest of what exists and what changed since last time, so the session knows what to pull on the nextupdateAsync. Backsvtklocal.get.status. The returned object carries:ids—[id, mtime]pairs for every object reachable from the render windowhashes— content hashes of the blobs those objects referencecameras— ids of the active cameras;force_pushandignore_idsselect which to push to the server or leave alone (e.g. to keep the client's local camera)interactor— the interactor id for the render window
Hydrate a scene
The example below stands in for a server with a handful of canned object states: a render window that owns a renderer whose Background is gray. The three fetchers read from that in-memory scene exactly as they would read from the wire, so the session hydrates and renders without any backend.
The state objects mirror what vtklocal.get.state returns: each carries an Id, a ClassName, its SuperClassNames, and the properties to apply. References to other objects are { "Id": n }, and fetchStatus advertises every object so the session knows what to pull on the first updateAsync. This scene has no binary data, so fetchHash is never called.
Bring your own canvas
The session never creates, moves, or removes canvas elements — you own them. Create a <canvas> and associate it with a render window via bindCanvas, passing either the element itself or the id of one already in the DOM:
const canvas = document.createElement("canvas");
remote.bindCanvas(renderWindowId, canvas); // pass the element directly…
// remote.bindCanvas(renderWindowId, "my-canvas"); // …or the id of a canvas in the DOM
remote.setSizeAsync(renderWindowId, 800, 600); // size the canvas + render windowPassing the element directly registers it with Emscripten's specialHTMLTargets, so the canvas needs neither an id nor to be attached to the document — handy for off-screen or framework-managed canvases. (On builds that don't expose specialHTMLTargets, the canvas must have an id so a CSS selector can be used instead.)
When the canvas goes away, unbindCanvas removes the listeners, unregisters the target, and forgets the mapping, leaving the element itself untouched.
Drive updates
Call updateAsync to pull the latest server state for a render window and render it.
await remote.updateAsync(renderWindowId);To surface download progress (state + blob counts), register a callback with addProgressCallback; it returns a function that removes the callback.
Reading state
Once synchronized, inspect objects locally without another round trip via getState and getStateValue, or get a controllable proxy with getVtkObject.
Objects are owned by the server
The server owns the scene's object lifecycle, so a remote session cannot create or destroy objects from the client. The remote.vtk namespace exists only to control existing objects: use getVtkObject (or remote.vtk.getVtkObject(id)) to obtain a proxy for an object the server already created.
Calling a constructor such as remote.vtk.vtkActor() or proxy.delete() is a no-op: it logs a warning to the console and returns undefined / false rather than mutating the scene. To add or remove objects, do it on the server and pull the change in with update.
const actor = remote.getVtkObject(actorId); // ✅ control an existing object
actor.visibility = false;
remote.vtk.vtkActor(); // ⚠️ warns, returns undefined
actor.delete(); // ⚠️ warns, returns falseCleaning up
remote.dispose() frees the C++ session and detaches the interaction listeners from your canvases (the canvas elements are left in place). As with standalone sessions, using works too:
using remote = runtime.createRemoteSession();Reference: RemoteSession · VtkWasmRuntime