Fullstack DevelopmentUpdated -11 min read

Building Scalable Telehealth Platforms with Next.js and Node.js for the European Market

A Next.js and Node.js architecture guide for telehealth: WebRTC, EHR interfaces, authorization, recovery and jurisdiction-specific requirements.

Ala Ben Aicha

Building Scalable Telehealth Platforms with Next.js and Node.js for the European Market

Introduction

The European telehealth market has matured significantly since the pandemic-driven surge of 2020. What started as a quick fix for lockdown-era healthcare has become a permanent part of the care delivery landscape. But building a telehealth platform for the European market is fundamentally different from building one for the US — the regulatory environment, data protection requirements, and integration landscape demand specific architectural decisions.

This guide describes implementation patterns for a telehealth architecture. The examples are illustrative; they do not demonstrate a certified or legally compliant deployment.

Architecture Overview

A production telehealth platform for the European market needs these core components:

┌─────────────────────────────────────────────────────────┐
│                    Client Layer                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
│  │   Next.js    │  │  React Native│  │   Patient    │  │
│  │   Web App    │  │  Mobile App  │  │   Portal     │  │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘  │
└─────────┼──────────────────┼─────────────────┼──────────┘
          │                  │                 │
          ▼                  ▼                 ▼
┌─────────────────────────────────────────────────────────┐
│                    API Gateway                           │
│            (Authentication + Rate Limiting)              │
└────────┬──────────┬──────────┬──────────┬───────────────┘
         │          │          │          │
         ▼          ▼          ▼          ▼
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐
│ Consult  │ │ Schedule │ │ Clinical │ │  Signaling   │
│ Service  │ │ Service  │ │  Notes   │ │  Server      │
│ (Node.js)│ │ (Node.js)│ │ (Node.js)│ │  (WebSocket) │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘
     │            │            │               │
     ▼            ▼            ▼               ▼
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐
│PostgreSQL│ │PostgreSQL│ │  FHIR    │ │    TURN      │
│          │ │          │ │  Server  │ │    Server    │
└──────────┘ └──────────┘ └──────────┘ └──────────────┘
                              │
                              ▼
                    ┌──────────────────┐
                    │   EHR Systems    │
                    │ (Epic, Cerner,   │
                    │  local systems)  │
                    └──────────────────┘

Video Consultation with WebRTC

Why WebRTC

WebRTC is the standard for browser-based real-time communication. For telehealth, it offers:

  • Encrypted transport — WebRTC protects media transport; end-to-end protection across media servers requires a specific design. See RFC 8827.
  • No plugin required — works in modern browsers
  • Adaptive bitrate — adjusts quality based on network conditions
  • Low latency — essential for clinical conversations

Signaling Server Architecture

WebRTC requires a signaling server to coordinate peer connections. I build this with Socket.io on Node.js:

// Signaling server — handles WebRTC session negotiation
import { Server } from 'socket.io';

interface ConsultationRoom {
  clinicianId: string;
  patientId: string;
  startedAt: Date;
  recordingConsent: boolean;
}

const rooms = new Map<string, ConsultationRoom>();

io.on('connection', (socket) => {
  socket.on('join-consultation', async ({ roomId, role, userId }) => {
    // Verify user is authorized for this consultation
    const authorized = await verifyConsultationAccess(roomId, userId, role);
    if (!authorized) {
      socket.emit('error', { code: 'UNAUTHORIZED' });
      return;
    }

    socket.join(roomId);

    // Notify the other participant
    socket.to(roomId).emit('participant-joined', { role, userId });
  });

  socket.on('offer', ({ roomId, sdp }) => {
    socket.to(roomId).emit('offer', { sdp });
  });

  socket.on('answer', ({ roomId, sdp }) => {
    socket.to(roomId).emit('answer', { sdp });
  });

  socket.on('ice-candidate', ({ roomId, candidate }) => {
    socket.to(roomId).emit('ice-candidate', { candidate });
  });
});

TURN Server for NAT Traversal

In real-world deployments, many hospital networks use strict firewalls that block peer-to-peer WebRTC connections. A TURN (Traversal Using Relays around NAT) server is essential:

  • Choose TURN locations and processors against the approved hosting and transfer requirements. GDPR does not impose a universal EU-only hosting rule; international transfers need their applicable safeguards.
  • Use coturn — the industry-standard open-source TURN server
  • Configure TLS on TURN (TURNS) for encrypted relay traffic
  • Plan for bandwidth — TURN relay traffic can be significant at scale

Recording and Consent

Before enabling recording, establish the lawful basis, applicable health-data condition, notice, authorization and retention rules with the responsible organization. Record the required permissions and provide a clear recording indicator. Encrypt stored recordings and control access. Erasure requests must be assessed against applicable retention obligations; deletion is not unconditional. See GDPR, Articles 6, 9, 17 and Chapter V.

Scheduling and Appointment Management

Calendar Integration

A telehealth scheduling system needs to handle:

  • Clinician availability — recurring schedules with exception handling
  • Time zones — critical for cross-border consultations in Europe
  • Buffer time — gaps between appointments for documentation
  • Waitlist management — filling cancellation slots automatically

I use date-fns with date-fns-tz for time zone handling in Node.js:

import { zonedTimeToUtc, utcToZonedTime, format } from 'date-fns-tz';

function getAvailableSlots(clinicianId: string, date: Date, patientTimezone: string): TimeSlot[] {
  // Fetch clinician's schedule in their timezone
  const clinicianTz = 'Europe/Zurich';
  const schedule = getClinicianSchedule(clinicianId, date);

  return schedule.availableSlots.map((slot) => ({
    // Store in UTC, display in patient's timezone
    startUtc: zonedTimeToUtc(slot.start, clinicianTz),
    endUtc: zonedTimeToUtc(slot.end, clinicianTz),
    displayTime: format(
      utcToZonedTime(zonedTimeToUtc(slot.start, clinicianTz), patientTimezone),
      'HH:mm',
      { timeZone: patientTimezone }
    )
  }));
}

Pre-Consultation Workflow

European telehealth platforms should include a pre-consultation workflow:

  1. Patient intake form — symptoms, reason for visit, medication changes
  2. Document upload — lab results, referral letters, imaging reports
  3. Insurance verification — validate coverage for telehealth services (varies by country)
  4. Technical check — camera, microphone, and network quality test before the appointment
  5. Waiting room — virtual waiting area with estimated wait time

EHR Integration

FHIR-Based Clinical Data Exchange

The telehealth platform must integrate with the patient's EHR for clinical context. I use FHIR APIs for this:

// Fetch patient context before consultation
async function getPatientContext(patientFhirId: string): Promise<PatientContext> {
  const [conditions, medications, allergies] = await Promise.all([
    fhirClient.search('Condition', {
      patient: patientFhirId,
      'clinical-status': 'active'
    }),
    fhirClient.search('MedicationStatement', {
      patient: patientFhirId,
      status: 'active'
    }),
    fhirClient.search('AllergyIntolerance', {
      patient: patientFhirId,
      'clinical-status': 'active'
    })
  ]);

  return { conditions, medications, allergies };
}

Clinical Documentation

After the consultation, the clinician generates a clinical note. This should be structured as a FHIR Encounter resource linked to:

  • Condition resources for new or updated diagnoses
  • MedicationRequest for new prescriptions
  • ServiceRequest for referrals or lab orders
  • DocumentReference for the clinical note itself

European Regulatory Considerations

GDPR Compliance for Telehealth

Specific GDPR considerations for telehealth platforms:

  • Lawful processing — identify an Article 6 basis and an applicable Article 9 condition; Article 9(2)(h) is not a standalone authorization for every telehealth service.
  • Video data — encryption is one security control; assess authorization, media-server trust boundaries, signalling metadata and operational procedures as well.
  • Session metadata — who called whom, when, and for how long is personal data and must be protected accordingly
  • Cross-border consultations — if a clinician in one EU country consults with a patient in another, data processing occurs in both jurisdictions

National Telehealth Regulations

Confirm professional practice rules, reimbursement conditions, patient information, hosting and record-retention requirements for each target country. Do not assume that teleconsultation is fully reimbursed or that a single EU configuration covers every national setting. Make billing, consent and documentation policies configurable against the approved requirements.

Medical Device Classification

If your telehealth platform includes clinical decision support, AI-based triage, or diagnostic tools, it may qualify as a medical device under the EU MDR. Pure video consultation platforms typically do not, but the line blurs quickly when you add clinical functionality.

Performance and Reliability

Network Resilience

Healthcare video consultations cannot tolerate the same failure rates as consumer video calls. Build for resilience:

  • Automatic reconnection — if a connection drops, reconnect within seconds without losing the consultation context
  • Bandwidth adaptation — gracefully degrade video quality before dropping to audio-only
  • Fallback to phone — if WebRTC fails entirely, offer a click-to-call option as a last resort
  • Connection quality indicators — show both participants the current connection quality

Monitoring

Monitor these metrics in production:

  • Connection success rate — percentage of consultations that establish a video connection successfully
  • Average setup time — time from "Join" click to video being visible
  • Dropped connection rate — percentage of consultations interrupted by network issues
  • Audio/video quality scores — WebRTC provides statistics for packet loss, jitter, and round-trip time

Conclusion

Building a telehealth platform for the European market requires more than just a video call feature. It demands careful attention to GDPR compliance, EHR integration through FHIR APIs, country-specific regulatory requirements, and the kind of reliability that clinical workflows demand. The Next.js + Node.js stack provides the flexibility and performance needed, but the architecture decisions — particularly around data residency, encryption, and clinical integration — are what make or break a European telehealth product.

If you are building a telehealth platform for the European market and need architecture guidance or implementation support, I would be happy to discuss your requirements.

TelehealthNext.jsNode.jsWebRTCFHIRGDPRReactHealthcareFull Stack

Related reading and services

Let's Continue the Conversation

Have questions about this topic? I'd love to hear from you.