Building a Video Meeting System: Nothing is Impossible in a Few Weeks

Most developers assume that building an online video meeting system like Google Meet or Zoom requires years of development, a large team of DevOps, WebRTC experts, and massive infrastructure.

But the truth is: with Jitsi Meet – an open-source video platform with Docker support – you can deploy your own secure, customizable meeting server in just weeks.

In this article, I’ll share how I successfully integrated Jitsi Meet into a user management system (NestJS backend / Next.js frontend), allowing users to create, join, and manage meeting rooms.

Note: This is a simplified demo. The system works as a lobby-style app with a list of meeting rooms and limited participants. You can adapt or extend it based on your business model, for example:

  • Online teaching platforms
  • Telehealth / doctor appointment apps
  • Anonymous chat with topic-based rooms
  • ...etc

Getting Started with Jitsi Meet

git clone https://github.com/jitsi/docker-jitsi-meet
cd docker-jitsi-meet
cp env.example .env
docker-compose up -d

This gives you a full-featured Jitsi server at https://meet.mycompany.com.


Securing Access: Authenticated Users Only

ENABLE_AUTH=1
ENABLE_GUESTS=0
AUTH_TYPE=jwt
JWT_APP_ID=my-app-id
JWT_APP_SECRET=your-256-bit-secret

This ensures only users with a valid JWT token can join meetings — no anonymous guests.

You can also configure NGINX to block direct access and only allow embedding via iframe from your app:

if ($http_referer !~* ^https://app\.mycompany\.com) {
  return 403;
}

Integration with User System and Role Management

The backend issues a signed JWT token with user info and role:

...(isOwner ? { affiliation: 'owner' } : { affiliation: 'member' })

This allows:

  • Owner (host) to mute/kick/share
  • Member (participant) to join only

➡️ Great for classroom models, webinars, or secure consultations.


Real-time User Tracking via WebSocket

Use WebSocket to:

  • Track who joined/left
  • Update participant count in real time
  • Highlight the host
  • Allow kick/ban if a user is unauthorized or suspicious
socket.emit('joinRoom', { roomId, userId });
socket.on('userJoined', (data) => {
  // update participant UI
});

Extend further to support:

  • Hand raising
  • Real-time shared notes
  • Live chat

✨ Features You Can Add Later

  • Meeting history and logs
  • Email invites
  • Granular role-based permissions
  • Auto-recording with Jibri
  • Analytics and reporting

Integration Workflow

[Frontend lobby UI]
     |
     | -- click "Join and chat now!"
     ↓
[Request JWT from backend (roomId, userId)]
     ↓
[Backend generates JWT with role + affiliation]
     ↓
[Frontend embeds iframe with Jitsi + token]
     ↓
[Jitsi verifies JWT, assigns role: owner/member]
     ↓
[Client opens WebSocket to join room]
     ↓
[Socket updates real-time participants + roles]
     ↓
[Frontend displays custom meeting UI based on role]

JWT Token Generator (TypeScript)

import jwt from 'jsonwebtoken';

export function generateMeetingToken({ roomName, user, isOwner }: any): string {
  const payload = {
    aud: 'my-app-id',
    iss: 'my-app-id',
    sub: 'meet.mycompany.com',
    room: roomName,
    context: {
      user: {
        id: user.id,
        name: user.name,
        email: user.email,
        avatar: user.avatar,
      },
    },
    moderator: isOwner,
    ...(isOwner ? { affiliation: 'owner' } : { affiliation: 'member' }),
    exp: Math.floor(Date.now() / 1000) + 3600,
  };

  return jwt.sign(payload, 'your-256-bit-secret');
}

Embedding Jitsi with IFrame

const MeetingRoom = ({ roomName, token }: { roomName: string; token: string }) => {
  const jitsiUrl = `https://meet.mycompany.com/${roomName}?jwt=${token}`;

  return (
    <iframe
      src={jitsiUrl}
      allow="camera; microphone; fullscreen; display-capture"
      style={{ width: '100%', height: '100%', border: 0 }}
      title="My Jitsi Meeting"
    />
  );
};

Use in full screen, modal, or custom layout as needed.


Mock UI Demo

Illustrates lobby, iframe embed, Jitsi interface and token-based login


✅ Deployment Checklist

  • Use a custom domain (avoid meet.jit.si for production)
  • Always issue JWT from backend
  • Use short token TTL (~15 minutes)
  • Enforce Referer check in NGINX
  • Enable HTTPS (Let's Encrypt)
  • Integrate socket for real-time features

Final Thoughts

It’s absolutely possible to build your own video meeting platform in just a few weeks.

With Jitsi + NestJS, you can build a secure, private, role-based meeting system that scales and adapts to your internal tools or SaaS products.

This is a minimal demo. Feel free to adapt it for classrooms, teleconsultation, 1:1 calling, or livestreaming to thousands.


References


⚠️ Disclaimer: All code snippets here are simplified for demonstration. For production, handle retries, token refresh, logging, and security carefully.