Skip to main content

Vue Classroom Workshop Tutorial

Build an interactive classroom with mediasfu-vue@1.3.0. The supplied room includes participants, messages, polls, breakouts, whiteboard, media, and leave.

Prerequisites​

  • Node.js 18 to 20, Vue 3, HTTPS or localhost, and teacher/learner profiles.
  • Authenticated create/join routes with teacher and learner policy.

Project files​

package.json
{"private":true,"scripts":{"dev":"vite"},"dependencies":{"mediasfu-vue":"1.3.0","vue":"3.5.13"},"devDependencies":{"@vitejs/plugin-vue":"5.2.1","typescript":"5.9.3","vite":"5.4.19"}}
src/room-gateway.ts
import type { CreateJoinRoomResult, CreateRoomOnMediaSFUType, JoinRoomOnMediaSFUType } from 'mediasfu-vue'; async function postRoom(url: string, payload: unknown): Promise<CreateJoinRoomResult> { const response = await fetch(url, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) throw new Error(`Room request failed (HTTP ${response.status}).`); return response.json() as Promise<CreateJoinRoomResult>; } export const createRoom: CreateRoomOnMediaSFUType = ({ payload }) => postRoom('/api/mediasfu/create-room', payload); export const joinRoom: JoinRoomOnMediaSFUType = ({ payload }) => postRoom('/api/mediasfu/join-room', payload);
src/App.vue
<script setup lang="ts">import { MediasfuGeneric } from 'mediasfu-vue'; import 'mediasfu-vue/dist/mediasfu-vue.css'; import { createRoom, joinRoom } from './room-gateway';</script>
<template><main><h1>Classroom workshop</h1><p>Open Messages, Polls, Breakouts, or Whiteboard.</p><MediasfuGeneric :return-u-i="true" :connect-media-s-f-u="true" :create-media-s-f-u-room="createRoom" :join-media-s-f-u-room="joinRoom" /></main></template>
src/main.ts
import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');
index.html
<!doctype html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>Classroom</title></head><body><div id="app"></div><script type="module" src="/src/main.ts"></script></body></html>
vite.config.ts
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [vue()] });
tsconfig.json
{"compilerOptions":{"target":"ES2022","lib":["DOM","ES2022"],"strict":true,"module":"ESNext","moduleResolution":"Bundler","skipLibCheck":true,"noEmit":true},"include":["src"]}

Use restricted, revocable, uncommitted credentials only on an isolated local backend. Before distribution, external testing, or production, reusable Cloud credentials remain only on the authenticated backend.

Backend​

Keep src/room-gateway.ts in this project and implement its two API routes using the complete public production room credential boundary. The backend authorizes teacher and learner roles; the browser never receives a Cloud credential.

Run​

npm install
npm run dev

Expected result​

Teacher and learner exchange a message, complete a poll, enter/leave a breakout, and open/close the whiteboard according to room permissions.

Recovery​

If a breakout move fails, keep the learner in the main room. Refresh current room state before retrying interrupted poll or whiteboard actions.

Cleanup​

End polls and breakouts, close the whiteboard, clear app-owned drafts, use Leave, and expire backend room authority.