APPSOCOMDocs

Classrooms

Teachers run the class and students take part. Moderation, waiting rooms, breakouts and attendance all happen on our servers, so they hold even if someone modifies their app.

Give each token a role (teacher, student or observer), as described in Join tokens. Anyone with the moderate permission can use the controls below.

Teacher controls

ts
room.mute(userId);                          // turn off their mic (they can turn it back on)
room.mute(userId, ["mic", "camera"]);
room.muteAll(["mic"], { lock: true });      // everyone who isn't a teacher, and keep them muted
room.setPermissions(userId, { mic: true }); // allow again
room.setPermissions(userId, { screen: true }); // let a student present
room.stopScreenShare(userId);
room.remove(userId);                        // { ban: true } keeps them out until the room empties
room.lockRoom(true);                        // only teachers can join now
room.setSpotlight([teacher.userId]);        // whose video everyone should see large

When a permission is taken away, the person's track is cut off on our servers within about 3 seconds, even if their app ignores the request. Teachers can't remove each other, and muteAll never mutes teachers.

Raised hands

ts
room.raiseHand();
room.lowerHand(userId);        // teachers: someone else's
room.lowerAllHands();
room.on("hands", (raised) => showQueue(raised)); // first raised first

Class chat

ts
room.sendChat("Can you repeat that?");
room.sendChat("I'm stuck on 3b", { to: teacher.userId }); // private, student ↔ teacher
room.on("chat", (m) => addLine(m.fromName, m.text, m.to));
room.setChatEnabled(false);                                // teachers

People who join late get the last 100 public messages. Private messages always have a teacher on one side, and they aren't stored.

Waiting room

ts
// teachers
room.setWaitingRoom(true);
room.on("waiting-list", (list) => showLobby(list));
room.admit(userId); // or "*" for everyone
room.deny(userId);

// students: joinRoom() waits until they're let in
const room = await joinRoom({ url, token, onWaiting: () => show("Waiting for your teacher…") });

People in the waiting room see and hear nothing until they're admitted. Someone admitted once goes straight back in if they reconnect.

Breakout rooms

ts
room.startBreakouts([
  { name: "Table 1", userIds: ["u_1", "u_2"] },
  { name: "Table 2", userIds: ["u_3", "u_4"] },
]);
room.moveToGroup("u_5", "g2");   // null = main room
room.visitGroup("g1");           // teachers drop in
room.sendChat("2 minutes left", { everywhere: true });
room.endBreakouts();

Moving between groups is instant, with no new token or connection. Each group only sees, hears and chats with its own members. Our servers enforce this too.

Attendance

bash
curl -H "Authorization: Bearer $APPSOCOM_API_KEY" https://api.appsocom.dev/rooms/math-101/attendance
curl -H "Authorization: Bearer $APPSOCOM_API_KEY" "https://api.appsocom.dev/rooms/math-101/attendance?format=csv"

You get one row per student, with first join, last leave, total time and number of sessions. Attendance is kept for 30 days after the last activity. Use a new room ID for each class session if you want separate reports.

From your backend

Everything above also works from your server. See the REST API, for example PATCH /rooms/:roomId {"waitingRoom":true} or POST /rooms/:roomId/mute.