ReactJS Host Dashboard Tutorial
Build a host dashboard with mediasfu-reactjs@4.3.0. The supplied room renders
participants, requests, permissions, media, alerts, and role-aware exit.
Prerequisites
- Node.js 18 to 20, React 18, HTTPS or
localhost, and two browser profiles. - Authenticated create/join routes shown below.
- A backend policy that identifies hosts and allowed moderation actions.
Project files
{"private":true,"scripts":{"dev":"vite"},"dependencies":{"mediasfu-reactjs":"4.3.0","react":"18.2.0","react-dom":"18.2.0"},"devDependencies":{"@types/react":"18.3.24","@types/react-dom":"18.3.7","@vitejs/plugin-react":"4.3.4","typescript":"5.9.3","vite":"5.4.19"}}
import { useState } from 'react';
import { ModernMediasfuGeneric, type CreateRoomOnMediaSFUType, type JoinRoomOnMediaSFUType, type Participant } from 'mediasfu-reactjs';
async function postRoom<T>(url: string, payload: unknown): Promise<T> {
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<T>;
}
const createRoom: CreateRoomOnMediaSFUType = ({ payload }) => postRoom('/api/mediasfu/create-room', payload);
const joinRoom: JoinRoomOnMediaSFUType = ({ payload }) => postRoom('/api/mediasfu/join-room', payload);
type RoomState = { participants?: Participant[] };
export default function App() {
const [room, setRoom] = useState<RoomState>({});
return <main><header><h1>Host dashboard</h1><p>Open Participants and Requests to manage the current room.</p></header>
<ModernMediasfuGeneric connectMediaSFU={true} createMediaSFURoom={createRoom} joinMediaSFURoom={joinRoom} sourceParameters={room} updateSourceParameters={setRoom} />
<output aria-live="polite">Current participants: {room.participants?.length ?? 0}</output>
</main>;
}
import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App';
createRoot(document.getElementById('root')!).render(<StrictMode><App /></StrictMode>);
<!doctype html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>Host dashboard</title></head><body><div id="root"></div><script type="module" src="/src/main.tsx"></script></body></html>
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()] });
{"compilerOptions":{"target":"ES2022","lib":["DOM","ES2022"],"strict":true,"module":"ESNext","moduleResolution":"Bundler","skipLibCheck":true,"noEmit":true,"jsx":"react-jsx"},"include":["src"]}
For isolated local development, your backend may use restricted, revocable development credentials that are never committed. Before distribution, external testing, or production rooms, reusable Cloud credentials must remain only on the authenticated backend.
Backend
The complete backend request flow is in the public production room credential
boundary. Have /api/mediasfu/create-room and
/api/mediasfu/join-room authenticate the caller before they forward a room
request. The browser never receives a MediaSFU Cloud credential.
Run
npm install
npm run dev
Expected result
Create a room as host and join from the second profile. Open Participants and Requests, apply an allowed action, and confirm the room state changes for both people. A participant cannot use host-only controls.
Recovery
Disable moderation during reconnect. Treat a denied action as policy, not a network retry. If no participant is selected or room state has changed, ask the host to choose again rather than applying an action to stale state.
Cleanup
Use participant Leave for a local exit and the supplied host End flow only for the room-wide action. Clear app-held selection state and expire temporary room authority on the backend.