3D visualization interface for spatial data using Viam's APIs — frame systems, geometries, point clouds, drawings — for motion-related monitoring, testing, and debugging.
📚 viamrobotics.github.io/visualization is our guide to a few popular use cases. It covers:
- Running locally — set up the app and drive it from Go via
client/api. - Embedding
<Visualizer />— drop the visualizer into your own Svelte app. - Implementing WorldStateStoreService — produce
Transforms for a Viam WorldStateStoreService module withdraw. - A live playground rendering a snapshot.
make setup # one-time: install Node 22, pnpm, Go, buf, project deps
make up # http://localhost:5173For manual setup, machine configs, multiple instances, and troubleshooting see the local-usage guide.
Run the dev server with HMR:
pnpm devSee CLAUDE.md for contributor conventions.
The visualizer also builds as a desktop app with Electron. It wraps the same static build the browser gets and bundles the Go draw server as a sidecar. A packaged app starts the sidecar on a free port and stops it when the app quits, so the draw-service panel is live with nothing else running. You need Go and nlopt with its static library (etc/setup.sh installs it). Electron itself comes from pnpm install.
An unpackaged run does not start the sidecar, because pnpm dev already runs a draw server on 3030. Set VIAM_VISUALIZER_SIDECAR=1 to start it anyway, after pnpm build:sidecar. That builds the sidecar alone, into dist-sidecar/, and fails if the binary links any non-system library. A platform where nlopt cannot be linked statically can build with GOFLAGS=-tags=nomotionplan, which drops IK inspection from the sidecar. Windows always builds that way, because RDK's nlopt solver does not support Windows, so the Windows desktop app has no IK inspection.
pnpm electron:dev # dev server in a desktop window, with HMR
pnpm electron:start # the static build in a desktop window
pnpm electron:build # packaged app for this platform under dist-desktop/The main process and preload live in electron/, and packaging is configured in electron-builder.yml. The app version follows version in package.json. An unpackaged run on macOS still shows "Electron" as its Dock name, because that comes from the stock Electron binary. A packaged app shows "Viam Visualizer".
The app connects on boot when started with --launch-file <path>. The file is JSON, version 1, written by the Viam CLI with 0600 permissions. The app deletes it after reading, unless it is not JSON or has no version key:
{
"version": 1,
"host": "<part fqdn>",
"partId": "<part id>",
"partName": "<part name>",
"machineName": "<machine name>",
"signalingAddress": "https://app.viam.com:443",
"serviceHost": "https://app.viam.com",
"credentials": { "type": "access-token", "payload": "<jwt>" }
}credentials is alternatively { "type": "api-key", "authEntity": "<key id>", "payload": "<key>" }. A second launch with a new file switches the running window to that machine. On macOS, open -a <app> <path> works too, and is the only form that reaches an app already running, since open drops --args then. With no flag the app behaves like the browser build.
Every GitHub release carries desktop bundles built by electron-release.yml, named viam-visualizer-<version>-<platform>-<arch><suffix> with platform one of darwin, linux, windows and arch one of aarch64, x86_64. The suffixes are .dmg and .app.tar.gz on macOS, .AppImage and .deb on Linux, and .exe (portable) and -setup.exe (installer) on Windows, plus a checksums.txt with one sha256 name line per asset. The macOS .app.tar.gz unpacks to Viam Visualizer.app, with the executable at Contents/MacOS/Viam Visualizer.
Note
Currently, the macOS bundles are ad-hoc signed and not notarized. A downloaded bundle is blocked on first launch. Allow it under System Settings → Privacy & Security → Open Anyway, or run xattr -d com.apple.quarantine on the .app.
The visualizer exposes a cameraControls object on window. Open the browser console and call methods on it to move the camera or tweak its settings at runtime. Full API: https://github.com/yomotsu/camera-controls#properties.