Back to Insights
Architecture

Architecting a Real-Time Frontend for WebRTC Applications

Jan 20, 2026
12 min read

Real-time applications are unforgiving.

Latency is visible.

State inconsistencies are obvious.

Poor UX decisions are amplified.

When building Medivue, a doctor–patient communication platform with chat, voice, and video, I learned quickly that real-time frontend architecture is less about APIs and more about predictability, resilience, and user perception.

This article breaks down how I think about real-time frontends—specifically for WebRTC-based applications.

Real-Time Frontend Is a System, Not a Feature

In traditional web apps:

  • • UI reacts to user actions
  • • Backend responds
  • • State flows in one direction

In real-time apps:

  • • State changes without user input
  • • Network conditions are unstable
  • • Multiple systems compete to update the UI

This changes everything.

The frontend becomes an orchestrator, not just a renderer.

Managing Real-Time State Without Losing Control

The Core Problem

In WebRTC applications, state comes from multiple sources:

  • User interactions
  • Signaling server (Socket.IO)
  • Peer connection events
  • Media device changes
  • Network interruptions

If all of this flows directly into React state, chaos follows.

The Approach I Took

I separated state into three clear layers:

UI State

  • • Modals
  • • Button states
  • • Local UI feedback

Session State

  • • Call status (idle, ringing, connected, ended)
  • • Participant roles
  • • Permissions

Connection State

  • • WebRTC peer status
  • • ICE connection state
  • • Media stream readiness

Each layer had clear ownership and limited responsibility.

This prevented cascading re-renders and made debugging far easier.

Handling Latency in the UI (Not Just the Network)

Latency is inevitable.

Bad UX is not.

Common Mistake

Waiting for server confirmation before updating the UI.

This makes interfaces feel slow—even when the backend is fast.

What Worked Better

I adopted optimistic UI updates wherever possible:

  • Button feedback happens immediately
  • UI reflects intent, not confirmation
  • Backend failures are handled gracefully after

Example: When a user initiates a call:

  • 1. UI transitions to "Calling" instantly
  • 2. Ringing indicators appear
  • 3. Connection events update the UI progressively

The user never feels like the app is "thinking".

UX Considerations for Calls and Chat

Real-time UX is about clarity under uncertainty.

For Video & Voice Calls

Key principles:

  • • Always show current state
  • • Never leave the user guessing
  • • Transitions matter more than visuals

Important details:

  • • Clear "connecting" vs "connected" states
  • • Visible mic/camera status
  • • Explicit call ended feedback

Even a 1–2 second ambiguity creates anxiety in communication apps.

For Chat Interfaces

Chat is deceptively complex.

Things I accounted for:

  • • Message ordering under latency
  • • Temporary "sending" states
  • • Clear sender identity
  • • Persistent history across refresh

Chat UX must feel reliable, even when the network is not.

WebRTC Events Are Not UI Events

One of the biggest lessons from Medivue:

WebRTC events should never directly control UI.

Examples:

  • • ontrack
  • • onicecandidate
  • • connectionstatechange

These events are technical signals, not UX decisions.

Instead:

1

Events update connection state

2

Connection state updates session state

3

Session state drives UI

This separation prevents UI flicker, race conditions, and inconsistent visuals.

Designing for Failure (Because It Will Happen)

Real-time apps fail in many ways:

• Network drops

• Peer disconnects

• Permissions denied

• ICE negotiation fails

Ignoring this leads to broken experiences.

I designed Medivue assuming:

  • • Calls will fail sometimes
  • • Users need clear recovery paths
  • • Silence is the worst feedback

Every failure state had:

  • Explicit messaging
  • Clear next action
  • Calm, non-alarming tone

Performance Is Part of UX

In real-time applications:

  • • Heavy animations hurt more than help
  • • Frame drops during calls are unacceptable
  • • Visual polish must never interfere with media streams

Because of this:

Animations were minimal during calls

Media components were isolated from re-renders

UI updates were intentional, not reactive

The call experience stayed stable and predictable.

Lessons Learned Building Medivue

If I had to summarize everything into a few principles:

→ Separate UI, session, and connection state

→ Design UX for uncertainty, not ideal conditions

→ Treat WebRTC events as data, not commands

→ Optimize for perceived responsiveness

→ Reduce visual noise during real-time interactions

Real-time systems reward clarity and restraint far more than cleverness.

Closing Thought

Architecting a real-time frontend isn't about mastering WebRTC APIs.

It's about understanding:

  • How users perceive delays
  • How systems fail
  • How to keep interfaces calm under pressure

Medivue reinforced something I now apply everywhere:

A stable UI builds trust faster than a flashy one.

Why This Matters in My Portfolio

This project demonstrates:

System-level frontend thinking

Real-time UX decision-making

Practical WebRTC experience

Performance-aware UI design

These are exactly the challenges modern product teams face.