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 using `uv `_ for Python development.
.. code-block:: bash
# Install uv (if not already installed).
curl -LsSf https://astral.sh/uv/install.sh | sh
# Run any example directly (uv handles dependencies automatically).
cd ~/viser
uv run --extra examples python examples/00_getting_started/00_hello_world.py
Linting, formatting, type-checking
----------------------------------
For code quality, we use ``pyright`` for type checking and ``ruff`` for linting
and formatting.
.. code-block:: bash
# Check static types.
uv run --extra dev pyright
# Lint and auto-fix issues.
uvx ruff check --fix
# Format code.
uvx ruff format
Running tests
-------------
.. code-block:: bash
uv run --extra dev pytest
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:
.. code-block:: bash
cd ~/viser
uv run python sync_client_server.py --sync-messages --sync-version
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``
Wire Format
^^^^^^^^^^^
Messages are sent over WebSocket using a hybrid format that separates lightweight
metadata from binary array data.
**Encoding (Python server):**
1. Binary arrays (numpy) are extracted from messages and replaced with tagged
placeholder dicts: ``{"__binary_index": i, "dtype": "`_
2. Install dependencies.
.. code-block:: bash
cd ~/viser/src/viser/client
npm install
**Launching client.**
To launch the client, we can run:
.. code-block:: bash
cd ~/viser/src/viser/client
npm run dev
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``.