Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules
docs/.vitepress/dist
docs/.vitepress/cache
docs/api
docs/public/demo/playground
docs/public/demo/simple-app
examples/cpp/vtk
Expand Down
83 changes: 33 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,52 @@
# vtk-wasm
# @kitware/vtk-wasm

## Project Structure and Build Scripts
JavaScript bindings for loading and driving [VTK](https://www.vtk.org) compiled to WebAssembly — build 3D visualizations in the browser with no C++ required.

This repository provides the infrastructure to bundle the pure JavaScript library for loading VTK.wasm.
**Full documentation, guides, and API reference:** https://kitware.github.io/vtk-wasm/

The full usage documentation of vtk-wasm can be found at: https://kitware.github.io/vtk-wasm/
## Usage

### File Structure
Install the package:

- `dist/` — Bundled output files.
- `examples/` — Example applications demonstrating vtk-wasm usage.
- `docs/` — Documentation and guide pages.
- `src/` — Source code for the library.
- `README.md` — Project documentation.
- `package.json` — Project metadata and build scripts.

### Build Scripts

The following scripts are available in `package.json`:
```bash
npm install @kitware/vtk-wasm
```

- **`npm run docs:dev`** - Starts a local development server for the guide pages with live reloading
- **`npm run docs:build`** - Builds the guide pages for VTK.wasm
- **`npm run build`** — Builds the ESM and UMD bundles for both RemoteSession and StandaloneSession.
- **`npm run build:esm`** — Builds only the ESM bundles.
- **`npm run build:examples`** — Builds the example applications.
- **`npm run build:vtk`** — Builds only the UMD bundle for StandaloneSession.
- **`npm run build:viewer`** - Builds the vtkWASMViewer JavaScript library.
- **`npm run clean`** — Cleans the `dist/` directory.
- **`npm run lint`** — Runs code linting on the source files.
Load the runtime, create a session, and use its `vtk` namespace:

### Bundles
```js
import { loadVtkWasm } from "@kitware/vtk-wasm";

- **ESM Bundles:** For both RemoteSession and StandaloneSession.
- **UMD Bundle:** For StandaloneSession, exposed as the `VTK` namespace for use in browser environments.
const runtime = await loadVtkWasm({ url: VTK_WASM_BUNDLE_URL });
const session = runtime.createStandaloneSession();
const vtk = session.vtk;

Refer to the `package.json` for the full list of scripts and configuration details.
const cone = vtk.vtkConeSource();
// ... build and render your scene
```

### ESM imports
No build step? Load the UMD bundle from a CDN and use the global `vtkWASM`:

```js
import { RemoteSession } from "@kitware/vtk-wasm/remote"
import { createVtkObjectProxy, createNamespace } from "@kitware/vtk-wasm/vtk"
import { ExportViewer, createViewer } from "@kitware/vtk-wasm/viewer"
```html
<script src="https://unpkg.com/@kitware/vtk-wasm/vtk-umd.js"></script>
```

### RemoteSession progress
See the [Loading VTK.wasm guide](https://kitware.github.io/vtk-wasm/guide/js/loading) to get started and the [API reference](https://kitware.github.io/vtk-wasm/api/) for every export.

```js
import { RemoteSession } from "@kitware/vtk-wasm/remote"
## Contributing

const session = new RemoteSession()
const removeProgress = session.addProgressCallback(({ active, state, hash }) => {
// state: { current, total }, hash: { current, total }
// active is true while states/blobs are being fetched
})
Requires [Node.js](https://nodejs.org/) (LTS).

// Later, to stop listening:
removeProgress()
```bash
npm install # install dependencies
npm run build # build the ESM + UMD bundles into dist/
npm run docs:dev # run the documentation site locally
npm run lint # lint the source
```

### UMD imports
### Repository layout

```js
import "@kitware/vtk-wasm/viewer.css";
import "@kitware/vtk-wasm/viewer-umd.js";

import "@kitware/vtk-wasm/vtk-umd.js";
```
- `src/` — library source.
- `examples/` — example applications.
- `docs/` — documentation site (VitePress); the API reference is generated from source JSDoc.
- `dist/` — build output.
37 changes: 32 additions & 5 deletions docs/.vitepress/config.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
import { existsSync, readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { defineConfig } from "vitepress";
import { withMermaid } from "vitepress-plugin-mermaid";

// API reference sidebar generated by TypeDoc (npm run docs:api). Falls back to
// an empty list so the docs still build before the API has been generated.
const __dirname = dirname(fileURLToPath(import.meta.url));
const apiSidebarFile = resolve(__dirname, "../api/typedoc-sidebar.json");

// TypeDoc marks every group `collapsed: true`; expand them by default.
const expandSidebar = (items) =>
items.map((item) =>
item.items
? { ...item, collapsed: false, items: expandSidebar(item.items) }
: item,
);

const apiSidebar = existsSync(apiSidebarFile)
? expandSidebar(JSON.parse(readFileSync(apiSidebarFile, "utf-8")))
: [];

// https://vitepress.dev/reference/site-config
export default defineConfig({
export default withMermaid(defineConfig({
base: "/vtk-wasm",
title: "VTK.wasm",
description: "Guides and documentation around VTK.wasm",
Expand Down Expand Up @@ -50,6 +71,7 @@ export default defineConfig({
nav: [
{ text: "Home", link: "/" },
{ text: "News", link: "/news" },
{ text: "API", link: "/api/" },
{ text: "Guides", link: "/guide/" },
{ text: "Roadmap",
items: [
Expand Down Expand Up @@ -91,10 +113,11 @@ export default defineConfig({
{
text: "For JavaScript developers",
items: [
{ text: "Getting started", link: "/guide/js/" },
{ text: "Loading VTK.wasm", link: "/guide/js/loading" },
{ text: "Standalone Session", link: "/guide/js/standalone-session" },
{ text: "Primer on VTK.wasm", link: "/guide/js/primer" },
{ text: "HTML Script Tag", link: "/guide/js/plain" },
{ text: "Bundler Integration", link: "/guide/js/bundler" },
{ text: "Remote Session", link: "/guide/js/remote-session" },
{ text: "Adding VTK.wasm to a Project", link: "/guide/js/integration" },
],
},
{
Expand All @@ -113,6 +136,10 @@ export default defineConfig({
],
},
],
"/api/": [
{ text: "API Reference", link: "/api/" },
...apiSidebar,
],
"/roadmap/": [
{ text: "Overview", link: "/roadmap/" },
{ text: "Module Availability", link: "/roadmap/modules" },
Expand All @@ -124,4 +151,4 @@ export default defineConfig({
{ icon: 'github', link: 'https://github.com/Kitware/vtk-wasm' }
]
},
});
}));
28 changes: 0 additions & 28 deletions docs/guide/js/bundler.md

This file was deleted.

31 changes: 0 additions & 31 deletions docs/guide/js/index.md

This file was deleted.

79 changes: 79 additions & 0 deletions docs/guide/js/integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Adding VTK.wasm to a Project

There are two ways to get VTK.wasm into a web project:

- **HTML Script Tag** — load a prebuilt bundle from a CDN, no build step required. Best for quick prototypes, demos, and embedding into existing pages.
- **Bundler** — install the `@kitware/vtk-wasm` package and `import` it. Best for application development with a tool like Vite.

Either way you end up calling [`loadVtkWasm`](./loading.md); only how it reaches the page differs.

## HTML Script Tag

Use VTK.wasm directly in an HTML file using a `<script>` tag without a build step.

The following examples rely on loading the `vtk.umd.js` bundle from a CDN. To focus on the initialization part, we've externalized the JS/WASM scene code since that part does not change.

### Load WASM as a module

In this example we pre-load the WASM module, so we don't need to provide any URL when loading it.

::: code-group
<<< ../../public/demo/plain-javascript-preload.html
<<< ../../public/demo/example.js
:::

### Defer WASM loading

Since we didn't pre-load the WASM module here, we provide the URL where the WASM bundle can be found.

::: code-group
<<< ../../public/demo/plain-javascript.html
<<< ../../public/demo/example.js
:::

<iframe src="/vtk-wasm/demo/plain-javascript.html" style="width: 100%; height: 40vh; border: none;"></iframe>

[Full Screen Viewer](../../demo/plain-javascript.html){target="_blank"}

### Defer WASM loading with annotation

Here we tag the script to autoload WASM directly from the VTK repository's package registry and create a global `vtk` namespace. You can customize the wasm architecture and version by changing the `data-url`.

::: code-group
<<< ../../public/demo/plain-javascript-annotation-wasm-registry.html
<<< ../../public/demo/example.js
:::

<iframe src="/vtk-wasm/demo/plain-javascript-annotation-wasm-registry.html" style="width: 100%; height: 40vh; border: none;"></iframe>

[Full Screen Viewer](../../demo/plain-javascript-annotation-wasm-registry.html){target="_blank"}

The `data-config` attribute on the annotation `<script>` accepts the same settings as the options object passed to `loadVtkWasm(...)` — for example, add `data-config='{"rendering": "webgpu"}'` to switch the rendering backend. See [Loading VTK.wasm](./loading.md) for what each option does, or the [`loadVtkWasm` reference](/api/@kitware/vtk-wasm/functions/loadVtkWasm) for the exact option types.

## Bundler

Modern web development relies on a package manager to bring in project dependencies. This section covers how published releases are used within a JavaScript project.

### Project setup

In this simple example we use [Vite](https://vite.dev/) with Vanilla JavaScript. The full code is available for reference [here](https://github.com/Kitware/vtk-wasm/tree/main/examples/js/simple-app). Use a concrete version, or `"latest"`, for the `@kitware/vtk-wasm` package. Here, the example uses a relative path to the `vtk-wasm` project root so the in-repo documentation stays relevant.

::: code-group
<<< ../../../examples/js/simple-app/package.json
<<< ../../../examples/js/simple-app/index.html
<<< ../../../examples/js/simple-app/src/main.js [src/main.js]
<<< ../../../examples/js/simple-app/src/example.js [src/example.js]
<<< ../../../examples/js/simple-app/src/style.css [src/style.css]
```bash [Install/Build]
npm install
npm run build
```
:::

Here, the VTK.wasm bundle is downloaded in the browser directly from the GitLab package registry. See the `src/main.js` file for the relevant code.

### Result

<iframe src="/vtk-wasm/demo/simple-app/index.html" style="width: 100%; height: 25vh; border: none;"></iframe>

[Full Screen Viewer](../../demo/simple-app/index.html){target="_blank"}
75 changes: 75 additions & 0 deletions docs/guide/js/loading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Loading VTK.wasm

Everything starts with a single call: [`loadVtkWasm(options)`](/api/@kitware/vtk-wasm/functions/loadVtkWasm) returns a [`VtkWasmRuntime`](/api/@kitware/vtk-wasm/classes/VtkWasmRuntime) — a loaded WebAssembly module that acts as the factory for sessions.

```mermaid
flowchart TD
ST["HTML script tag (global vtkWASM)"]
BD["Bundler import"]
AN["Annotation script tag"]

ST --> LF["loadVtkWasm(options)"]
BD --> LF
LF --> RT["VtkWasmRuntime — cached per url + config"]

RT -->|createStandaloneSession| SS["StandaloneSession"]
RT -->|createRemoteSession| RS["RemoteSession"]

SS --> NS["session.vtk: create & render objects"]
RS --> RW["bindNetwork + bindCanvas + update"]

AN -.->|auto: loads + standalone session| NS

NS --> DS["session.dispose()"]
RW --> DS
RT --> DR["runtime.dispose()"]
```

```js
import { loadVtkWasm } from "@kitware/vtk-wasm";

const runtime = await loadVtkWasm({
url: "https://gitlab.kitware.com/api/v4/projects/13/packages/generic/vtk-wasm32-emscripten/9.6.20260228/vtk-9.6.20260228-wasm32-emscripten.tar.gz",
});
```

First you need `loadVtkWasm` on the page. Pick whichever fits your setup (see [Adding VTK.wasm to a Project](./integration.md)):

- [HTML Script Tag](./integration.md#html-script-tag) — no build step; `loadVtkWasm` lives on the global `vtkWASM` object.
- [Bundler](./integration.md#bundler) — `import { loadVtkWasm } from "@kitware/vtk-wasm"`.

For the complete, generated list of exported functions and classes, see the [API Reference](/api/).

## Choosing options

`loadVtkWasm` takes one options object. The most common choices are conceptual; the full list with types is in the [API reference](/api/@kitware/vtk-wasm/functions/loadVtkWasm).

- **Where to load from** — `url` points at a directory or a `.tar.gz` bundle. Skip it when the module is already loaded as a script. `wasmBaseName` (default `"vtk"`) and `urlIsGzip` adjust how the bundle is located.
- **Rendering backend** — `rendering: "webgl"` (default) or `"webgpu"`. WebGPU requires async execution and is switched on automatically.
- **Execution mode** — `exec: "sync"` (default) or `"async"`. Async unlocks WebGPU and non-blocking calls but requires [JavaScript Promise Integration (JSPI)](https://v8.dev/blog/jspi) support in the browser.
- **Console output** — pass `print` / `printErr` to pipe C++ `std::cout` / `std::cerr` to JavaScript.

## Runtimes are cached

Runtimes are cached per `(url, wasmBaseName, rendering, exec)`. Calling `loadVtkWasm` again with the same options returns the existing runtime instead of fetching and instantiating a second copy, so it is safe to call from multiple places.

## Creating sessions

A runtime does nothing on its own — it creates **sessions**:

```js
const session = runtime.createStandaloneSession(); // in-browser rendering
// or
const remote = runtime.createRemoteSession(); // server-driven rendering
```

- [Standalone Session](./standalone-session.md) — create and render VTK objects entirely in the browser.
- [Remote Session](./remote-session.md) — mirror a scene driven by a server.

## Releasing a runtime

Call [`runtime.dispose()`](/api/@kitware/vtk-wasm/classes/VtkWasmRuntime#dispose) (or use a `using` declaration) to drop it from the shared cache. Note that Emscripten cannot reclaim a runtime's heap before a page reload — disposing the **sessions** is what actually frees C++ memory.

---

**Reference:** [`loadVtkWasm`](/api/@kitware/vtk-wasm/functions/loadVtkWasm) · [`VtkWasmRuntime`](/api/@kitware/vtk-wasm/classes/VtkWasmRuntime)
Loading