LUPYD Real-Time Calling Flow
Call Invitation
Caller sends an invite with session metadata
Offer / Answer
ICE candidates and SDP exchanged
Lupyd servers relay signaling messages only, so a relay operator can start or end a call but cannot join the media path.
Caller Endpoint
Captures audio and video
DTLS-SRTP media path
Direct peer to peer
Recipient Endpoint
Decodes and renders the stream
Group calls fan out one encrypted sender stream per participant, so every recipient holds its own keys.
Call signaling establishes the session while WebRTC handles the peer-to-peer audio and video connection.
Calling in LUPYD began with a simple goal: let people start a conversation without leaving the app. Delivering that experience meant coordinating real-time media, call signaling, and app state across WebRTC, React, Tauri, Rust, and Android.
Starting With 1-to-1 Calling
We started with one-to-one audio and video calls. WebRTC carries the media between participants; LUPYD handles the signaling and application state needed to start, update, and end each call.
A call passes through several connected stages: an invitation arrives, the recipient accepts, the peers establish a connection and negotiate media, then both sides clean up when the call ends. Each transition needs to be reflected consistently in the app.
Getting a call to connect is only the first milestone. The harder work is keeping every layer in sync as the call changes state, especially when events arrive close together or the user acts outside the call screen.
Beyond the Call Screen
A call should remain manageable when the app is no longer in the foreground. Users need to see that a call is active and take essential actions without reopening the call screen.
On Android, that experience depends on connecting the app to native support for ongoing call notifications and foreground call handling. Actions such as accepting, muting, unmuting, or ending a call need to pass between Android and LUPYD so the interface and call state stay aligned.
A single call can involve several parts of the stack, each with a distinct responsibility:
- React: Call UI and application state
- WebRTC: Real-time audio and video
- Tauri: Application and native bridge
- Rust: Native application logic
- Android: Notifications and foreground call handling
Adding Group Calling
One-to-one calls were a starting point. Group conversations bring additional needs: a meeting model, participant management, and controls that work for everyone in the call.
For group calls, LUPYD uses Cloudflare RealtimeKit for the meeting infrastructure and calling interface. It provides microphone and camera controls, device settings, meeting controls, and a minimized meeting window. This lets people stay connected while continuing to use LUPYD.
The Real Challenge: Call State
The central challenge in real-time apps is keeping state consistent across the interface, the signaling flow, and the underlying connection.
An incoming call might be accepted, cancelled, rejected, or disconnected while other events are still in flight. The app has to manage active sessions, pending offers, ICE candidates, native actions, and cleanup without leaving a call in a contradictory state.
This work changed how I think about calling features. A WebRTC connection is one piece; the full experience depends on independent layers responding in a coordinated way.
What I Learned
The biggest lesson for me was that getting a call connected is only the beginning.
The experience is really tested when someone minimizes the app, responds to a notification, changes audio or video settings, joins a group meeting, or ends a call from outside the call screen. Those moments are where coordination across the stack matters most.
Building calling for LUPYD gave me hands-on experience across React, WebRTC, Tauri, Rust, and Android. More than anything, it showed me that a reliable calling experience comes from making those technologies work together as one system.
- ✓ WebRTC handles peer-to-peer audio and video while Lupyd manages call signaling and application state.
- ✓ Android foreground services and notifications keep calls usable when the app is minimized.
- ✓ Group calling adds participant management and meeting controls through Cloudflare RealtimeKit.
- ✓ Reliable calling depends on keeping call state synchronized across React, Tauri, Rust, and Android.