Skip to main content

ReactJS Remote Podcast Tutorial

Build a remote podcast room with mediasfu-reactjs@4.4.2. The supplied room handles speaker media, remote playback, recording controls, notices, and exit.

Prerequisites​

  • Node.js 18 to 20, React 18, HTTPS or localhost, and two speaker profiles.
  • Authenticated create/join routes and a recording disclosure/consent policy.

Project files​

package.json
{"private":true,"scripts":{"dev":"vite"},"dependencies":{"mediasfu-reactjs":"4.4.2","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"}}
src/App.tsx
import { ModernMediasfuGeneric, type CreateRoomOnMediaSFUType, type JoinRoomOnMediaSFUType } 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);
export default function App() { return <main><header><h1>Remote podcast</h1><p>Prove every speaker's audio before opening Recording.</p></header><ModernMediasfuGeneric connectMediaSFU={true} createMediaSFURoom={createRoom} joinMediaSFURoom={joinRoom} /></main>; }
src/main.tsx
import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App'; createRoot(document.getElementById('root')!).render(<StrictMode><App /></StrictMode>);
index.html
<!doctype html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>Remote podcast</title></head><body><div id="root"></div><script type="module" src="/src/main.tsx"></script></body></html>
vite.config.ts
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()] });
tsconfig.json
{"compilerOptions":{"target":"ES2022","lib":["DOM","ES2022"],"strict":true,"module":"ESNext","moduleResolution":"Bundler","skipLibCheck":true,"noEmit":true,"jsx":"react-jsx"},"include":["src"]}

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

Backend​

Implement the two API routes using the complete public production room credential boundary. The backend authorizes the speakers and recording policy; the browser never receives a MediaSFU Cloud credential.

Run​

npm install
npm run dev

Expected result​

Both speakers hear each other. After the product's disclosure and consent, an authorized user opens Recording, starts it, sees the in-room recording state, and stops it before ending the room.

Recovery​

Do not start recording until every required speaker has working remote audio. If start/stop fails, retain an accurate visible state and offer a deliberate retry. Configure recording storage, retrieval, retention, and export in the authenticated backend before release.

Cleanup​

Stop recording before host end, stop app-owned tracks, clear local episode drafts, and expire room authority. Apply the product's recording retention rules.