Development

In this note, we outline current practices, tools, and workflows for viser development. We assume that the repository is cloned to ~/viser.

Python install

We recommend an editable install for Python development, ideally in a virtual environment (eg via conda).

# Install package.
cd ~/viser
pip install -e .

# Install example dependencies.
pip install -e .[examples]

After installation, any of the example scripts (~/viser/examples) should be runnable. A few of them require downloading assets, which can be done via the scripts in ~/viser/examples/assets.

Linting, formatting, type-checking.

First, install developer tools:

# Using pip.
pip install -e .[dev]
pre-commit install

For code quality, rely primarily on pyright and ruff:

# Check static types.
pyright

# Lint and format.
ruff check --fix .
ruff format .

Client-Server Synchronization

The viser frontend and backend communicate via a shared set of message definitions and enforce version compatibility to prevent security issues and crashes from mismatched versions.

Message Definitions

  • On the server, messages are defined as Python dataclasses in ~/viser/src/viser/_messages.py.

  • On the client, these are defined as TypeScript interfaces in ~/viser/src/viser/client/src/WebsocketMessages.ts.

There is a 1:1 correspondence between the Python dataclasses and the TypeScript interfaces.

Version Compatibility

Viser implements strict version compatibility checking between client and server:

  1. The client includes its version in the WebSocket subprotocol name (e.g., viser-v0.2.23)

  2. The server extracts the client version from the subprotocol and compares it with its own version

  3. If versions don’t match, the connection is rejected with code 1002 (protocol error) and an informative message

  4. This ensures that client and server components always operate with compatible functionality

Synchronization Script

To synchronize message definitions and version information between the Python backend and TypeScript frontend, use the sync_client_server.py script:

cd ~/viser
python sync_client_server.py

This script:

  1. Generates TypeScript interfaces from Python dataclasses

  2. Creates the VersionInfo.ts file with the current server version

  3. Formats the generated files using prettier

Always run this script after:

  • Changing message definitions in _messages.py

  • Updating the version in __init__.py

Client development

For client development, we can start by launching a relevant Python script. The examples are a good place to start:

cd ~/viser/examples
python 05_camera_commands.py

When a viser script is launched, two URLs will be printed:

  • An HTTP URL, like http://localhost:8080, which can be used to open a pre-built version of the React frontend.

  • A websocket URL, like ws://localhost:8080, which client applications can connect to.

If changes to the client source files are detected on startup, viser will re-build the client automatically. This is okay for quick changes, but for faster iteration we can also launch a development version of the frontend, which will reflect changes we make to the client source files (~/viser/src/viser/client/src) without a full build. This requires a few more steps.

Installing dependencies.

  1. Install nodejs.

  2. Install yarn.

  3. Install dependencies.

    cd ~/viser/src/viser/client
    yarn install
    

Launching client.

To launch the client, we can run:

cd ~/viser/src/viser/client
yarn start

from the viser/src/viser/client directory. After opening the client in a web browser, the websocket server address typically needs to be updated in the “Server” tab.

Formatting.

We use prettier. This can be run via one of:

  • prettier -w .

  • npx prettier -w .

from ~/viser/src/viser/client.