Skip to main content

ReactJS Remote Podcast Tutorial

Build a remote podcast room with mediasfu-reactjs@4.3.0. 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.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"}}
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.