Docs

Meetings

Rooms have a schedule window, an invite code, visibility (public or private), capacity, and host/moderator roles.

Creating a meeting

text
Create room
   ↓
Validate title, type, schedule, visibility
   ↓
Check host plan limits (duration / participants)
   ↓
Insert room + host membership (+ allowlist if private)
   ↓
Ready — share invite or open /room/[roomId]

Create always stores type: "meeting". The schema also has a webinar enum value, but the create UI does not expose it. Status is derived against startTime / endTime (waiting / active / ended).

Joining

text
Open invite or room URL
   ↓
Meeting exists and not ended
   ↓
Within schedule (before endTime)
   ↓
Visibility / allowlist / guest rules
   ↓
Capacity soft-check (listParticipants)
   ↓
Mint LiveKit JWT
   ↓
Browser connects to LiveKit

Soft capacity uses LiveKit listParticipants before token issue. Concurrent joins can race; LiveKit maxParticipants (product default 50) is the hard SFU bound.

Public vs private

Public

Anyone with a valid invite can join under normal schedule and capacity rules — including guests (signed cookie, no account).

Private

Only authenticated users whose account email is on the room’s allowlist (or the host) may join. Checks are server-side against the session email — typing an email in the UI is not proof of access. Guests cannot join private rooms. Unauthorized users never receive a LiveKit token.

Schedule and end

Join and token mint reject at/after endTime. The meeting UI warns at 10 and 5 minutes before end. Hosts can end/delete from the dashboard. Ending in Postgres does not instantly kick every LiveKit peer.

Roles

RoleNotes
HostRoom owner. Gets LiveKit roomAdmin. Full moderation.
ModeratorPromoted member. Mute / camera off / remove via server RoomService APIs (not raw roomAdmin on the client).
ParticipantAuthenticated member without elevated grants.
GuestPublic rooms only. Identity guest:{roomId}:{guestId}.