Case StudyEU client
5 mins

Real-Time Therapy Platform for iOS and Android: Video, Live Transcription, Socket-Driven EMDR

A mobile therapy platform with real-time video, live multilingual transcription, and socket-driven EMDR. Built for European users, so encryption and identifier aliasing were designed in rather than added late. The delivery blocker was an iOS bitcode fix that Expo silently discarded on every build.

Core Role

Full-Stack / Release Engineer

Tech Stack

Expo, React Native, Agora, Socket.IO, AWS S3, iOS, Android

CareAi is a mobile therapy platform for European users: real-time video, live multilingual transcription, socket-driven EMDR sessions, and AI-assisted summaries. Building it for medical data in Europe meant encryption and identifier aliasing shaped the data model early rather than being retrofitted. The hardest delivery problem wasn't a feature โ€” it was an iOS bitcode fix that Expo discarded on every build, because it was being applied to a folder Expo regenerates.

Ownership and status. Sole. Software case study, not infrastructure work. I built the real-time media integration, the transcription agent, the EMDR socket layer, the privacy controls and the release fixes. Shipped to both stores for client testing.

2 stores
Shipped to App Store and Play Store after clearing the iOS AgoraRTC build blocker
EN + FR
Live multilingual speech-to-text streamed into the therapist dashboard during sessions
Encrypted + aliased
At rest and in transit, with patient identifiers replaced by aliases

The app

The patient-facing surfaces the release had to keep working: browsing therapists, booking, and the profile and session screens either side of a consultation.

Home
Browsing therapists
Therapist detail, ahead of booking
Scheduled appointments
Patient profile
Running on iOS โ€” the build path that the AgoraRTC bitcode failure blocked

How a session runs in real time

Two channels carry a live session: Agora for media and transcription, and Socket.IO for the therapist-controlled EMDR state. They run side by side inside the same call.

Two channels, one session โ€” sockets for EMDR state, Agora for media.
1Sockets

Real-time EMDR from the therapist dashboard

EMDR โ€” Eye Movement Desensitization and Reprocessing โ€” guides patients through specific visual and auditory patterns to help process trauma, and it had to be fully interactive from the therapist side.

The app already relied on socket-based communication for real-time features, so EMDR leveraged that. On the therapist's web dashboard, a slider or buttons control the animation โ€” dot direction, color, speed, sound, and background. Each change is sent as a JSON payload over the socket. The patient, connected in the same video session, receives it instantly and updates the EMDR state in real time โ€” showing, hiding, or changing patterns mid-session as if therapist and patient were in the same room.

The video consultation screen โ€” the session both parties see.
2Media + STT

Live video and multilingual transcription

Video was the backbone of the app, and the requirement was not just stable streaming but speech-to-text transcripts for English and French. I built an Agora agent that joins the call, captures live audio, and sends the transcription to S3 for storage and real-time display. After some trial and error it ran smoothly, giving therapists live transcripts they could reference mid-session.

Chat sits alongside the live session so context is never lost.
3AI assist

Summaries built from real session context

I built an AI assistant that uses previous session context and the live transcription from the call. It summarizes key points, highlights potential concerns, and makes sessions easier to review later. The goal was never to replace therapist judgment โ€” it was to cut manual note-taking and keep important context from getting lost.

Engineering decision
Chose

Agora for video plus STT

Over

Building the real-time media layer from scratch

Why: Agora provided reliable video infrastructure and speech-to-text support out of the box, so the work could focus on the transcription agent and session logic instead of media plumbing.

Data handling

Built primarily for European users and carrying medical data, so two controls went in early: encryption at rest and in transit, and patient identifiers replaced with aliases so an exposed internal record doesn't carry direct identity.

Designing that in up front slowed the early work, mostly because it constrained how transcripts and chat could be stored and joined later.

What I'm not claiming: that the product is GDPR compliant. I implemented specific technical controls. Compliance is a legal determination involving data-processing agreements, retention policy, lawful basis and erasure handling โ€” none of which is an engineering sign-off, and the data lifecycle work below was never completed.

The iOS build blocker

Everything worked in simulators, but the App Store build exposed a different problem: AgoraRTC bitcode errors on iOS.

The common forum fixes for stripping bitcode did not work in our Expo setup. Debugging on an M1 Mac, I found the reason: the script was modifying the local ios/ folder, which Expo regenerates and ignores during the real build. Moving the fix into a post-build Expo script โ€” run after pod install โ€” stripped bitcode from the AgoraRTC framework automatically, and the build went through.

Engineering decision
Chose

A post-build Expo script that strips AgoraRTC bitcode after pod install

Over

Patching the local ios/ folder, which Expo regenerates and ignores

Why: Expo owns the native project generation, so any manual edit to ios/ is discarded at build time โ€” the fix has to run inside Expo's own build lifecycle to survive.

This is the class of bug that hides between tools: the fix was correct, the failure mode was that a generated folder was silently reverting it. Most of the delivery risk on this project sat outside feature code.

What I'd watch in production

The app shipped for client testing, so these are not measured results โ€” they are the first signals I'd instrument if I owned this longer-term:

  • Agora call quality โ€” call-drop and reconnect rates, since a dropped call interrupts an active therapy session.
  • Transcription latency and accuracy per language โ€” English vs. French, since the transcript feeds both the therapist view and the AI summaries.
  • EMDR socket desync โ€” whether the patient's EMDR state ever drifts from what the therapist dashboard sent, and how fast it recovers.
  • S3 encryption and access auditing โ€” who and what touches stored transcripts, given the medical data involved.
  • Data lifecycle โ€” retention windows and erasure requests across transcripts, chat and session records. This was not built, and it is the gap between the controls that exist and any real compliance position.

Key results

  • Real-time EMDR fully controlled from the therapist dashboard over sockets
  • Multilingual (EN/FR) live transcription integrated via Agora STT
  • AI assistant for session summaries built from real session context
  • Encryption at rest and in transit with aliased patient identifiers โ€” technical controls, not a compliance claim
  • iOS AgoraRTC bitcode blocker resolved with a post-build Expo script
  • Deployed to both the App Store and Play Store for client testing