# whiteboard: a self-hosted NodeJS collaborative sketchboard

> This whiteboard gives you remote cursors, per-user undo, image and PDF drop, WebDAV save and a REST API, and it runs from a single NodeJS process or one Docker container. The trade-off is that it ships as a web application you host yourself, with configuration in yaml and no built-in account system described in the docs.

**cracker0dks/whiteboard** — Lightweight collaborative Whiteboard / Sketchboard

- Repository: https://github.com/cracker0dks/whiteboard
- Stars: 844 · Forks: 230
- Language: JavaScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/cracker0dks-whiteboard

## A drawing surface where every participant sees the others

The project is described as a lightweight NodeJS collaborative Whiteboard or Sketchboard that can easily be customized. The collaboration features are what separate it from a local drawing app. Remote user cursors are shown while drawing, so you can see where other people are working rather than only seeing their marks appear. Undo and redo is per user, which is the detail that makes shared canvases bearable: one person cannot undo someone else's work by accident. There is also an indicator that shows the smallest screen participating, which tells you whether the person on a phone is struggling to see the board. The other half of the feature list is object handling. You can drag and drop images or PDFs from a PC and from a browser, resize, move, rotate and draw images onto the canvas or into the background, and write text and sticky notes. The board can be saved to an image and to JSON, and loaded back from JSON.

## Socket.io carries the session, the REST API covers the edges

Looking at the dependency list tells you how the collaboration actually works. socket.io and socket.io-client are both present, which is the pairing that carries live cursor positions and drawing events between the browser and the server, and a whiteboard cannot be collaborative without that channel. Express 5 serves the pages and the API, and the package.json names the REST surface explicitly: the apidoc block describes the REST API of the collaborative whiteboard server, with the name Whiteboard API. The build scripts generate that documentation with apidoc from the scripts directory, so the API reference is produced from the source rather than maintained by hand, and it is served alongside the app. The remaining dependencies are the drawing and storage layer. html2canvas turns the board into an image for the save feature, jquery-ui-rotatable supplies the rotate handle on selected objects, dompurify sanitises content, formidable handles uploads, webdav provides the WebDAV save target, and uuid identifies boards. The package is declared with type module, so the server code is ES modules.

## Running it takes npm install and one start command

The install path without Docker is four steps. You need the latest NodeJS, version 12 or newer, then you clone the app, then you run npm install inside the folder, then you run npm run start:prod and surf to http://YOURIP:8080. The commands are:

```bash
npm install
npm run start:prod
```

The prod script is a wrapper: it runs the build first, which is webpack with config/webpack.build.js, and then the start script, which regenerates the API docs into ./dist/apidoc/ and runs the server with the production mode flag. For development the project gives a separate entry point. After installing, you run npm run start:dev to start the backend and a frontend development server, and the site is then reachable on http://localhost:8080. That dev script also generates the apidoc output into ./public/apidoc/ and starts the server with the development mode flag, so the difference between the two is a webpack production bundle versus a live-reloading one, not a different application.

## One container, three volumes, a yaml config on the host

The Docker route is a single command in the README:

```bash
docker run -d -p 8080:8080 rofl256/whiteboard
```

The compose file shows what a real deployment needs, and it is more informative than the one-liner. The image is rofl256/whiteboard, it restarts always, it maps port 8080, and the command is --config=./config.default.yml, which is how you point the server at a config file. Three volumes are mounted: ./data/uploads to /opt/app/public/uploads, ./data/config.yml to /opt/app/config.default.yml as read only, and ./data/savedBoards to /opt/app/savedBoards. So uploaded images, the configuration and the saved boards all live on the host and survive a container replacement. The repository ships a config.default.yml at the root alongside a config directory, and the yaml is parsed with js-yaml, with ajv present for validation. The Dockerfile builds in two stages on node:24, compiles the frontend in the first stage, and the final image is node:24-alpine with NODE_ENV=production, exposing port 8080 and running npm run start as its entrypoint.

## Keybindings for every function, aimed at pen displays

The keyboard shortcut table is unusually complete, and the reason for it is stated: the shortcuts are especially useful if you work with interactive displays such as XP-Pen Artist, Huion Kamvas and Wacom Cintiq, devices with quick buttons, six to eight of them plus a scroll wheel. By default the buttons on these displays are mapped to standard Photoshop keyboard shortcuts, and the mapping can be changed to suit other software. The overrides live in a file, ./src/js/keybinds.js, and the README notes that the listed shortcuts are predefined ones you can override there. The table itself covers the whole application, from Clear the whiteboard on Ctrl + Shift + Del through tool selection, colour selection, thickness adjustment, saving as image, saving as JSON, saving to WebDav, loading saved JSON, sharing the board, hiding the toolbar with Tab, and arrow-key nudging of a selected object. It also records the modifier that constrains drawing: holding Shift gives a square with the rectangle tool and an angle line with the line tool, and that one is marked as not changeable. Windows and Linux and macOS are given separate columns, since Command replaces Ctrl and Alt replaces Option in several places.

## Persistence options are image, JSON and WebDAV

Three save paths are documented, and they cover different needs. Saving as image produces a picture of the board through html2canvas, which is what you want for pasting into a document rather than for continuing the work. Saving as JSON writes the board state, and loading a saved JSON back into the whiteboard is a separate shortcut, which means the JSON is the format that can be reloaded and edited. Saving to WebDav pushes the board to a WebDAV target, with a dedicated shortcut for it and the webdav package in the dependency list. The board identifier is part of the URL scheme, since the README has a section on URL parameters for changing the WhiteboardID, and the sharing shortcut and the WebDAV shortcut are separate actions rather than one combined save. What the documentation does not describe is any notion of user identity. The features list names no accounts, no roles and no permissions, and the per-user undo is scoped to a client rather than to a named account, so persistence is organised around board identifiers rather than around people. If your use case needs a record of who drew what, that is not in the feature set.

## MIT licensed, with tests for both node and the browser

The licence is MIT, recorded in the LICENSE file at the root. The repository is not archived and the last push was on 2026-10-22, so the code is moving, and the recent release tags look healthy: v1.9.0 on 2026-09-05 and v1.9.1 on 2026-10-03, with v1.8.1 back on 2024-09-17 before that. Note that the version field in package.json reads 1.0.0 even though the tags are in the 1.9 range, so the manifest version is not the thing to track. The tooling shows a project that takes its own tests seriously. The test script runs jest through node with the experimental-vm-modules flag, and a separate test:browser script builds the frontend and then runs playwright, with a playwright.config.js at the root and an e2e-browser directory. The jest config ignores both node_modules and the e2e-browser directory, so the node suite and the browser suite are kept separate. There is also prettier for formatting, with a lint-staged setup for pre-commit runs and husky wired up as the prepare script, plus an.editorconfig and a.prettierrc.json. The projects listed as using the whiteboard, Meetzi, LAMS and Accelerator, are described as WebRtc conference tools and a collaboration learning platform, which tells you the intended integration shape is embedding the board in another application.

## Conclusion

Adopt whiteboard if you want a self-hosted collaborative sketch surface that your team can run on one machine or in one container, and you need a REST API or WebDAV persistence rather than a hosted SaaS. Do not adopt it if you need built-in user accounts, role permissions, or an audit trail, because the documented feature set does not describe any of those. Before you commit, run the container with --config=./config.default.yml, confirm how your WebDAV target is configured, and check that the upstream demo at cloud13.de, which the README says resets every night, is representative enough to base a decision on.

## FAQ

### How do I install the whiteboard app?

Without Docker, install NodeJS version 12 or newer, clone the app, run npm install in the folder, then run npm run start:prod and open http://YOURIP:8080. With Docker, run docker run -d -p 8080:8080 rofl256/whiteboard and open the same address.

### What collaboration features does the whiteboard support?

It shows remote user cursors while drawing, has an undo and redo function for each user, and shows an indicator of the smallest screen participating. It also supports drag and drop of images or PDFs, text and sticky notes, and saving to image, JSON or WebDAV.

### How is the whiteboard configured?

Configuration is yaml. The repository ships a config.default.yml at the root, the Docker compose file runs the server with the command --config=./config.default.yml, and the compose file mounts ./data/config.yml to /opt/app/config.default.yml as read only.

### Can I change the keyboard shortcuts in the whiteboard?

Yes. The predefined shortcuts are documented in a table, and the overrides live in the file ./src/js/keybinds.js. The mapping is aimed at pen displays such as XP-Pen Artist, Huion Kamvas and Wacom Cintiq, whose quick buttons are mapped to Photoshop shortcuts by default.

## Sources

- [cracker0dks/whiteboard on GitHub](https://github.com/cracker0dks/whiteboard)
- [Issues](https://github.com/cracker0dks/whiteboard/issues)
- [License: MIT](https://github.com/cracker0dks/whiteboard/blob/master/LICENSE)
- [README](https://github.com/cracker0dks/whiteboard/blob/master/README.md)
- [Releases](https://github.com/cracker0dks/whiteboard/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cracker0dks-whiteboard
