100ms Integration for Video Conferencing on Website
100ms is a WebRTC platform with React SDK, ready-made UI components, and flexible pricing. Key feature—Rooms and Templates: you create a template in the dashboard (role settings, recording, quality), then create rooms based on it.
Creating a Room and Getting a Token
npm install @100mslive/roomkit-react @100mslive/react-sdk
// On server—Management Token for API
import jwt from 'jsonwebtoken';
function generateManagementToken(): string {
return jwt.sign(
{
access_key: process.env.HMS_ACCESS_KEY,
type: 'management',
version: 2,
iat: Math.floor(Date.now() / 1000),
nbf: Math.floor(Date.now() / 1000),
},
process.env.HMS_APP_SECRET!,
{ algorithm: 'HS256', expiresIn: '24h' }
);
}
// Create room
async function createRoom(name: string): Promise<string> {
const mgmtToken = generateManagementToken();
const response = await fetch('https://api.100ms.live/v2/rooms', {
method: 'POST',
headers: {
'Authorization': `Bearer ${mgmtToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name,
template_id: process.env.HMS_TEMPLATE_ID, // from 100ms Dashboard
}),
});
const room = await response.json();
return room.id;
}
// Get App Token for participant
async function getAppToken(roomId: string, userId: string, role: string): Promise<string> {
const mgmtToken = generateManagementToken();
const response = await fetch('https://api.100ms.live/v2/auth-token', {
method: 'POST',
headers: {
'Authorization': `Bearer ${mgmtToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
room_id: roomId,
user_id: userId,
role, // role from Template: 'host', 'guest', 'viewer'
}),
});
const { token } = await response.json();
return token;
}
// API endpoint
app.post('/api/video/join', authenticate, async (req, res) => {
const { sessionId } = req.body;
let session = await db.videoSessions.findById(sessionId);
if (!session.hmsRoomId) {
const roomId = await createRoom(`session-${sessionId}`);
session = await db.videoSessions.update(sessionId, { hmsRoomId: roomId });
}
const isHost = session.hostId === req.user.id;
const token = await getAppToken(session.hmsRoomId, req.user.id, isHost ? 'host' : 'guest');
res.json({ token });
});
React Component with Roomkit
import {
HMSRoomProvider,
useHMSActions,
useHMSStore,
selectIsConnectedToRoom,
selectPeers,
selectLocalPeer,
HMSPeer,
} from '@100mslive/react-sdk';
function VideoConference({ authToken, userName }: { authToken: string; userName: string }) {
return (
<HMSRoomProvider>
<VideoRoom authToken={authToken} userName={userName} />
</HMSRoomProvider>
);
}
function VideoRoom({ authToken, userName }) {
const hmsActions = useHMSActions();
const isConnected = useHMSStore(selectIsConnectedToRoom);
const peers = useHMSStore(selectPeers);
const localPeer = useHMSStore(selectLocalPeer);
useEffect(() => {
hmsActions.join({ authToken, userName, settings: { isAudioMuted: false, isVideoMuted: false } });
return () => {
hmsActions.leave();
};
}, [authToken]);
if (!isConnected) {
return <div className="flex items-center justify-center h-64">Connecting...</div>;
}
return (
<div>
<div className="grid grid-cols-2 gap-4 p-4">
{peers.map(peer => (
<PeerTile key={peer.id} peer={peer} />
))}
</div>
<div className="flex gap-3 justify-center p-4">
<button onClick={() => hmsActions.setLocalAudioEnabled(!localPeer?.audioEnabled)}
className="p-3 rounded-full bg-gray-800 text-white">
{localPeer?.audioEnabled ? '🎤' : '🔇'}
</button>
<button onClick={() => hmsActions.setLocalVideoEnabled(!localPeer?.videoEnabled)}
className="p-3 rounded-full bg-gray-800 text-white">
{localPeer?.videoEnabled ? '📹' : '📷'}
</button>
<button onClick={() => hmsActions.leave()}
className="p-3 rounded-full bg-red-600 text-white">
Leave
</button>
</div>
</div>
);
}
function PeerTile({ peer }: { peer: HMSPeer }) {
const videoRef = useRef<HTMLVideoElement>(null);
const hmsActions = useHMSActions();
const videoTrack = useHMSStore(selectCameraStreamByPeerID(peer.id));
useEffect(() => {
if (videoRef.current && videoTrack) {
hmsActions.attachVideo(videoTrack.id, videoRef.current);
}
return () => {
if (videoRef.current && videoTrack) {
hmsActions.detachVideo(videoTrack.id, videoRef.current);
}
};
}, [videoTrack]);
return (
<div className="relative bg-gray-900 rounded-xl overflow-hidden aspect-video">
<video ref={videoRef} autoPlay muted={peer.isLocal} playsInline className="w-full h-full object-cover" />
<span className="absolute bottom-2 left-2 text-white text-sm bg-black/50 px-2 rounded">
{peer.name} {peer.isLocal && '(you)'}
</span>
</div>
);
}
Timeline
100ms integration with room creation, tokens, and React component—2–3 days. With roles, recording, and webhooks—4–5 days.







