A Netless small whiteboard app that switches between different scene screens, for interactive classrooms: set questions, students answer, and show work.
- Roles: Teacher and student. Teacher controls flow (publish, finish, show to class); students answer and submit.
- Flow states: Waiting → Publishing question → Answering → Finished → Announcing results.
- i18n:
enandzh-CN. - Drawing tools: Pencil, eraser, shapes, text, arrows, etc. (via whiteboard SDK.)
- WindowManager: Insert as an app with
scenePathand teacheruid.
npm add @netless/app-little-white-boardPeer dependencies (see package.json):
| Dependency | Description |
|---|---|
@netless/window-manager |
Multi-window / app management |
white-web-sdk |
Interactive whiteboard SDK |
@netless/appliance-plugin |
Drawing tools plugin (required) |
Drawing (pencil, eraser, shapes, text, etc.) depends on appliance-plugin. You must install and enable it, or the small whiteboard will not draw correctly.
- Docs: appliance-plugin (English) · 中文
- Multi-window: Use
ApplianceMultiPlugin. Add it toinvisiblePluginsinjoinRoom, then after mounting WindowManager callApplianceMultiPlugin.getInstance(manager, { options: { cdn: { fullWorkerUrl, subWorkerUrl } } }), and setsupportAppliancePlugin: trueinmanagerConfig. - Styles:
import '@netless/appliance-plugin/dist/style.css'.
Register with WindowManager before use:
import LittleBoard from "@netless/app-little-white-board";
WindowManager.register({
kind: "LittleBoard",
src: LittleBoard,
appOptions: {
/** language: "en" | "zh-CN" */
language: "en",
/** Whether to allow pan/zoom on the canvas */
disableCameraTransform: true,
/** Called when user clicks to insert image; must upload and return image info */
async onClickImage() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
uuid: Date.now().toString(),
src: "https://p5.ssl.qhimg.com/t01a2bd87890397464a.png",
centerX: 0,
centerY: 0,
width: 100,
height: 100,
uniformScale: false,
});
}, 1000);
});
},
/** Optional: callback when app mounts */
onMount: (appId: string, userId: string) => {
console.log("LittleBoard Mount", appId, userId);
!isWritable && manager?.setReadonly(true);
},
/** Optional: callback when teacher publishes question */
onPublishQuestion: (appId: string, userId: string) => {
console.log("LittleBoard PublishQuestion", appId, userId);
},
/** Optional: callback when student commits answer */
onCommit: (appId: string, userId: string) => {
console.log("LittleBoard Commit", appId, userId);
},
},
});Add the small whiteboard to the room:
manager.addApp({
kind: "LittleBoard",
options: {
title: "Little Board app",
/** Whiteboard scene path (required) */
scenePath: "/LittleBoard",
},
attributes: {
/** Teacher uid — only this user can control the app */
uid: isWritable && sessionStorage.getItem("uid"),
},
});- Single controller: Only one user can control the app (navigate, click inside it). Set
attributes.uidto the teacher's uid. - Dependencies & plugin: See Dependencies above; appliance-plugin must be enabled.
Typical flow using Fastboard Demo:
- Open Fastboard Demo.
- Join as teacher: Enter the teacher name and join.

- Share room link with students so they can open the same room.

- Open small whiteboard from the left toolbar.

- Teacher: Draw/write, then click Publish to push content to all students.

- Students: Answer on their board, then click Commit to submit.

- Teacher: Click Finish to end the round.

- Teacher: View submissions; click Show to class to display a student’s work (and teacher feedback) to everyone.

Run the example in the repo:
cd exampleand install:pnpm i- Get roomToken and room uuid and set them in
whiteWebSdk.joinRoom(e.g.roomToken). - Run:
pnpm dev
