At IT PLUS I built a custom real-time video meeting solution from scratch to carry live classes with chat, presence, and screen sharing. The backend was PHP with Laravel, the signalling layer used Socket.io with Node.js, and the clients were Angular on the web and Ionic on mobile. This article explains how the parts fit and what production taught me.
Where each part lives
Clear ownership keeps a live system easy to reason about. Each tier owns one job and trusts the others to do theirs.
- Laravel owns truth. Rooms, schedules, membership, and roles live in MySQL behind Laravel. Only Laravel can create a meeting, add a member, or close a room.
- Socket.io owns the moment. Join, leave, mute state, raised hands, and typing notices travel as live events. The signalling server never stores business truth, it relays what is happening now.
- Angular and Ionic own the room view. The web client and the mobile client render the same events, join with the same token, and recover with the same steps.
Signalling without storing truth
Signalling is a relay, not a store. The client asks Laravel for a short lived meeting token, opens a Socket.io connection with that token, joins a named room, and then exchanges session offers and network candidates through the room. The server checks the token, places the socket in the room, and forwards each message to the right peer.
- Check before join. Every socket proves its meeting and user before it enters a room, so no guest can list or enter other rooms.
- One room per meeting. A room name maps to one Laravel meeting record, which keeps logs and moderation aligned with the database.
- Keep events small. Presence, mute, hand raise, slide change, and chat notices stay tiny and frequent, while media travels on its own path.
- Leave is an event. Close, refresh, or lost signal all end in the same cleanup, roster update, and notice to the host.
Rooms and permissions in Laravel
Laravel stays the authority even while the meeting is live. Socket.io asks Laravel who may enter, who may speak, and when the room ends.
- Token per seat. Laravel mints a token that binds user, meeting, and role together for a short life.
- Roles stay simple. Host, presenter, and viewer cover most classes without tangled rules.
- Close means close. When Laravel marks a meeting ended, the signalling layer tells every socket to leave and blocks rejoin.
Angular on the web and Ionic on mobile
Both clients speak the same event names and handle the same states, which keeps fixes in one place in spirit even with two code bases.
- Same join flow. Fetch token from Laravel, connect signalling, join room, publish local media, subscribe to remote media.
- Same roster model. One list of who is present, who is muted, and who raised a hand drives both layouts.
- Plan for weak networks. Muted entry, clear reconnecting state, and calm rejoin beat any clever trick.
What production taught me
Live rooms fail in ordinary ways. The fixes are habits, not heroics.
- Log the room, not only the server. Meeting id, user id, and event name on every signalling log line turn a vague report into a traceable story.
- Guard the host path. Mute all, lower hands, lock room, and end meeting must work even when the room is noisy.
- Test with real devices. An old phone on mobile data finds flaws that a fast laptop never shows.
- Keep media and signalling apart in your head. When voices lag, check media first. When roster or chat lags, check signalling first.
Built this way, the system stays explainable. Laravel holds the records, Socket.io carries the live moment, Angular and Ionic show it, and each layer can be fixed without rebuilding the others.
Login to comment
To post a comment, you must be logged in. Please login. Login
Comments (0)