Build an Intercom-Style Support Video Call UI on iOS
TL;DR
An Intercom-style support video call on iOS is built from three pieces: WebRTC for the live audio and video, CallKit for the native incoming-call and in-call screen, and a PushKit VoIP push to wake the app when an agent calls. Intercom runs the support conversation, but the video layer is yours to build. Start from a real call-screen template so the hardest part, the in-call UI and its states, is already shaped.
What Intercom does and does not give you
Intercom is a customer messaging and support platform. It is excellent at live chat, a shared inbox, bots, and help content, and many apps embed its messenger to talk to users. What it does not hand you is a native one-to-one support video call on iOS, with a full-screen agent feed, a picture-in-picture of the caller, and the system call screen you get from a phone call. So when someone searches for an “Intercom customer support video call UI for iOS,” they are really asking how to add a video layer alongside the support conversation Intercom already runs.
That split is the useful part. Keep Intercom for the conversation, the routing, and the history, and build the call as its own feature on top. The two connect at a single point: a button in the support thread that starts a call.
The three pieces of an iOS support video call
A working support call on iOS is almost always the same three layers. The media is WebRTC, the open standard that carries live audio and video peer to peer; on React Native, react-native-webrtc wraps it and pulls more than 170,000 weekly downloads. The native call experience is CallKit, which gives you the real incoming-call screen, the in-call controls, and correct behavior when a phone call or another audio app interrupts. And the wake-up is PushKit, a VoIP push that launches your app to report the incoming call even when it is closed.
Skip CallKit and you can still show a custom in-app call screen, which is fine when the app is already open. Skip PushKit and a closed app cannot receive a call at all. Most support tools want both, because an agent calling a user who is not currently in the app is the whole point.
Designing the in-call screen
The in-call screen carries the experience, and it has more states than people expect. There is connecting, ringing, connected, reconnecting, on hold, the agent’s camera off, the user’s camera off, muted, and ended. Each one needs an honest visual, because a frozen “connected” screen during a dropped link is worse than a clear “reconnecting” label. The standard layout puts the remote agent feed full-screen, the local camera in a small draggable tile, and a row of controls for mute, camera flip, camera off, and end. The agent’s name and a support badge belong on screen so the user knows who they are talking to.
This is the part worth not building from scratch. A free VP0 call-screen design ships these states and controls as an iOS template with a machine-readable source page, so pasting the link into Claude Code or Cursor gives the agent the full state model instead of a single happy-path screen. The same call-screen shape powers a React Native WebRTC video call kit and a vet telemedicine call clone, because a support call, a doctor call, and a vet call are the same UI with different branding.
Handling the incoming call (CallKit and VoIP push)
The flow that trips teams up is the incoming side. When an agent starts a call, your server sends a VoIP push through PushKit. iOS launches the app in the background, and you must immediately report the call to CallKit, or the system penalizes the app for taking a VoIP push without showing a call. CallKit then presents the native incoming-call UI, the user answers, and only then does WebRTC negotiate the media and your in-call screen takes over.
Get the order right and it feels like a real phone call. Get it wrong, usually by doing WebRTC work before reporting to CallKit, and you get dropped pushes and an app the system starts throttling. Camera and microphone access also need their Info.plist usage strings and a permission prompt before the first call, or the call connects with a black frame and silence.
Common mistakes building a support video call UI
The frequent failures are structural. Expecting Intercom to provide the video call leads to a long search for a setting that does not exist. Building only the in-app call screen and skipping CallKit means a closed app can never ring. Taking a VoIP push without reporting to CallKit gets the app throttled by iOS. Designing only the connected state leaves users staring at a frozen screen when the link drops. And forgetting the camera and microphone permission strings ships a call that joins blind and mute.
Key takeaways: a support video call on iOS
- Intercom runs the conversation, not the call. Keep it for chat and build the video layer separately.
- Three layers do the work: WebRTC for media, CallKit for the native call UI, PushKit for the VoIP wake-up.
- The in-call screen is mostly states. Connecting, reconnecting, camera off, muted, and ended all need honest visuals.
- Report to CallKit the instant a VoIP push arrives, before any WebRTC work, or iOS throttles the app.
- Start the call screen from a template. A free VP0 design gives an agent the full state model rather than a happy-path screen.
Frequently asked questions
How can I add an Intercom customer support video call to an iOS app? Keep Intercom for the support conversation and build the call as a separate feature triggered from the thread. Use WebRTC for the live audio and video, CallKit for the native incoming-call and in-call screen, and a PushKit VoIP push so a closed app can still ring when an agent calls. Intercom does not provide native one-to-one video itself, so the video layer is yours to add on top of the messaging it already handles.
What is the safest way to build this with Claude Code or Cursor? Give the agent a real call-screen structure with every state, not a single connected view. A free VP0 call template has a machine-readable source page, so Claude Code or Cursor builds against the full model of ringing, connecting, reconnecting, muted, and ended, plus the control row. That avoids the common result where an AI tool produces a pretty happy-path screen that falls apart the moment a call drops or a camera turns off.
Can VP0 provide a free SwiftUI or React Native template for a support video call screen? Yes. VP0 has free call-screen designs in SwiftUI and React Native, with the in-call layout, the draggable local tile, the control row, and the call states already built. Each exposes an AI-readable source page, so your agent extends a working call UI instead of inventing the state handling, which is the part that usually goes wrong.
Do I need CallKit and PushKit for a support call? For a call that can reach a user who is not currently in the app, yes. PushKit delivers the VoIP push that wakes a closed app, and CallKit shows the native incoming-call screen and manages audio when other calls interrupt. If you only ever start calls while the app is open and on screen, you can use a custom in-app screen without them, but most support tools want to reach users who are not actively in the app.
What common errors happen when vibe coding a video call UI? The big ones are taking a VoIP push without immediately reporting it to CallKit, which gets the app throttled, and shipping only the connected state so a dropped link shows a frozen screen. Missing camera and microphone permission strings produce a black, silent call. And expecting Intercom to supply the video sends people hunting for a setting that is not there. Build the state model first and wire the incoming-call order carefully.
Questions VP0 users ask
How can I add an Intercom customer support video call to an iOS app?
Keep Intercom for the support conversation and build the call as a separate feature triggered from the thread. Use WebRTC for the live audio and video, CallKit for the native incoming-call and in-call screen, and a PushKit VoIP push so a closed app can still ring when an agent calls. Intercom does not provide native one-to-one video itself, so the video layer is yours to add on top of the messaging it already handles.
What is the safest way to build this with Claude Code or Cursor?
Give the agent a real call-screen structure with every state, not a single connected view. A free VP0 call template has a machine-readable source page, so Claude Code or Cursor builds against the full model of ringing, connecting, reconnecting, muted, and ended, plus the control row. That avoids the common result where an AI tool produces a pretty happy-path screen that falls apart the moment a call drops or a camera turns off.
Can VP0 provide a free SwiftUI or React Native template for a support video call screen?
Yes. VP0 has free call-screen designs in SwiftUI and React Native, with the in-call layout, the draggable local tile, the control row, and the call states already built. Each exposes an AI-readable source page, so your agent extends a working call UI instead of inventing the state handling, which is the part that usually goes wrong.
Do I need CallKit and PushKit for a support call?
For a call that can reach a user who is not currently in the app, yes. PushKit delivers the VoIP push that wakes a closed app, and CallKit shows the native incoming-call screen and manages audio when other calls interrupt. If you only ever start calls while the app is open and on screen, you can use a custom in-app screen without them, but most support tools want to reach users who are not actively in the app.
What common errors happen when vibe coding a video call UI?
The big ones are taking a VoIP push without immediately reporting it to CallKit, which gets the app throttled, and shipping only the connected state so a dropped link shows a frozen screen. Missing camera and microphone permission strings produce a black, silent call. And expecting Intercom to supply the video sends people hunting for a setting that is not there. Build the state model first and wire the incoming-call order carefully.
Part of the Native Hardware, Sensors & Device Features hub. Browse all VP0 topics →
Keep reading
Bike Sharing Dock Availability UI Kit: Free Starting Point
Where to find a free bike sharing dock availability UI kit and how to wire it to live GBFS station data: pin states, dock counts, and stale-data UX.
React Native WebRTC Video Call UI Kit (Free Design)
Build a video call UI in React Native with WebRTC: local and remote video, mute and camera controls, and call states, from a free VP0 design.
Build a Live Translation Closed Captions Overlay on iOS
Live captions transcribe speech in real time and stay readable over anything. Here is how to build a live translation closed captions overlay on iOS.
Floating Keyboard Avoidance UI on iPad: The Honest Fix
The iPad has four keyboards and three break height math. UIKeyboardLayoutGuide, scroll-to-reveal, and when the right avoidance is none at all.
Biological Age Calculator Dashboard UI for iOS: Honest
Design a biological age dashboard: the estimate framed honestly, trends over absolutes, factor breakdowns tied to evidence, and zero longevity fear-mongering.
Municipal Waste Collection Calendar App UI Guide
How to build a waste collection calendar app: address-based schedules, color-coded bin system, evening-before reminders, iCal feeds, and holiday shifts.