Skip to main content

Overview

The CloudGaming client is a single-page HTML5 application that:
  • Requests a host assignment from the matchmaker
  • Establishes WebRTC connection via the signaling server
  • Receives video/audio streams from the Windows host
  • Sends keyboard, mouse, and gamepad input back to the host
  • Provides on-screen controls and connection status
Technology: Pure HTML5, vanilla JavaScript, WebRTC API - no build step required.

File Structure

The client consists of a single HTML file with embedded CSS and JavaScript:

Configuration

Updating Service URLs

The client reads configuration from a <script> block in index.html. Update these values before deployment:
1

Open index.html

2

Locate the config object

Search for the configuration near the top of the <script> section:
3

Update URLs for production

The signalingUrl is typically returned by the matchmaker, so it’s used as a fallback. The matchmaker response takes precedence.

CORS Configuration

Ensure your backend services allow requests from your client domain: Signaling Server (Server/.env):
Matchmaker (Server/mm_server/Matchmaker.js):

Local Development

For local testing:
For WebRTC to work properly:
  • Use localhost for local development (secure context)
  • Use HTTPS in production (required for getUserMedia, clipboard, etc.)

Production Deployment

The client is a static site and can be deployed to any hosting platform.

Vercel

1

Install Vercel CLI

2

Deploy

Vercel will:
  • Upload the static files
  • Configure HTTPS automatically
  • Provide a production URL (e.g., https://cloudgaming.vercel.app)
3

Configure custom domain (optional)

In Vercel dashboard:
Add DNS records as instructed by Vercel.
The included vercel.json configures headers and routing:

Cloudflare Pages

1

Push to Git repository

2

Create Cloudflare Pages project

  1. Go to Cloudflare Dashboard → Pages
  2. Connect to Git → Select repository
  3. Configure build:
    • Framework preset: None
    • Build command: (leave empty)
    • Build output directory: Client/html-server
3

Deploy

Cloudflare will automatically:
  • Build and deploy on every push
  • Provide HTTPS
  • Distribute globally via CDN
  • Provide a URL: https://cloudgaming.pages.dev

Netlify

1

Install Netlify CLI

2

Deploy

Or use drag-and-drop deployment:
  1. Visit app.netlify.com/drop
  2. Drag the Client/html-server/ folder
  3. Netlify provides instant HTTPS deployment

AWS S3 + CloudFront

1

Create S3 bucket

2

Upload files

3

Create CloudFront distribution

This provides:
  • HTTPS via AWS Certificate Manager
  • Global CDN distribution
  • Custom domain support

GitHub Pages

1

Create gh-pages branch

2

Enable GitHub Pages

  1. Go to repository → Settings → Pages
  2. Source: Deploy from branch gh-pages
  3. Folder: / (root)
  4. Save
Your client will be available at:

Docker / Self-Hosted

For self-hosting with nginx:
Create Dockerfile in Client/html-server/:
Build and run:

WebRTC Configuration

ICE Servers

The client receives ICE servers (STUN/TURN) from the matchmaker. For testing, you can hardcode fallback servers:
For production, ensure the matchmaker is configured with TURN servers (see Matchmaker Deployment).

Firewall and NAT

For WebRTC to work:
  • STUN: UDP ports 3478, 19302 (usually not blocked)
  • TURN: TCP/UDP ports 3478, 443 (may require configuration)
  • RTC: UDP ports 49152-65535 (ephemeral range, often blocked by corporate firewalls)
If clients are behind restrictive NATs or firewalls, TURN servers are required for connectivity.

Client Features

Controls

The client includes on-screen controls:
  • Fullscreen toggle: Expands video to fullscreen
  • Settings: Adjust quality, latency, input settings
  • Disconnect: Close the streaming session
  • Stats overlay: Display connection statistics (FPS, latency, bitrate)

Keyboard and Mouse Capture

Input capture activates when the user clicks on the video stream:

Gamepad Support

The client automatically detects and forwards gamepad input:

Mobile/Touch Support

The client includes basic touch controls:
  • Touch drag: Mouse movement
  • Single tap: Left click
  • Long press: Right click
  • Pinch zoom: Disabled (to prevent accidental zoom)
For production mobile deployment, consider implementing an on-screen virtual gamepad or custom touch controls.

Troubleshooting

Symptoms: Matchmaker returns 404 or {"found": false}Solutions:
  • Verify at least one Windows host is running and sending heartbeats
  • Check matchmaker /api/hosts endpoint: curl https://matchmaker.yourdomain.com/api/hosts
  • Ensure host and matchmaker are using the same HOST_SECRET
  • Check region matching (client requests us-east but hosts are eu-west)
Symptoms: Cannot connect to signaling serverSolutions:
  • Verify signaling server is running: curl https://signaling.yourdomain.com/healthz
  • Check browser console for WebSocket errors
  • Ensure signalingUrl uses wss:// (secure WebSocket) for HTTPS sites
  • Check CORS and ALLOWED_ORIGINS in signaling server config
  • Verify firewall/load balancer allows WebSocket upgrades
Symptoms: Connection established but black screenSolutions:
  • Check browser console for WebRTC errors
  • Verify host is capturing and encoding video (check host logs)
  • Test with chrome://webrtc-internals (Chrome) or about:webrtc (Firefox)
  • Ensure video codec is supported (H.264 is universally supported)
  • Check if <video> element has autoplay and playsinline attributes
Symptoms: Visible input delay or choppy videoSolutions:
  • Check network latency: Use browser DevTools Network tab
  • Verify host encoding settings (lower preset, cbr rate control)
  • Enable hardware acceleration in browser settings
  • Reduce video bitrate or resolution on host
  • Check CPU/GPU usage on both client and host
  • Test with chrome://webrtc-internals to see packet loss and jitter
Symptoms: Keyboard/mouse input not reaching the hostSolutions:
  • Click on the video to activate pointer lock
  • Check browser console for input capture errors
  • Verify host input injection is enabled (injectionPolicy: "REQUIRE_FOREGROUND")
  • Ensure target game window is in foreground on host
  • Test with simple applications (Notepad) before games
  • Check if DataChannels are established in chrome://webrtc-internals
Symptoms: Access-Control-Allow-Origin errorsSolutions:
  • Add client domain to signaling server ALLOWED_ORIGINS
  • Enable CORS in matchmaker (currently allows all origins by default)
  • Use a reverse proxy (nginx, Cloudflare) to add CORS headers
  • For development, use http://localhost (not 127.0.0.1 or file://)
Symptoms: iceConnectionState remains checking or goes to failedDiagnosis:
Solutions:
  • Check if TURN servers are configured in matchmaker
  • Test TURN connectivity: Trickle ICE
  • Verify firewall allows UDP on ephemeral ports (49152-65535)
  • For corporate networks, use TURN over TCP port 443
  • Check browser console for ICE candidate gathering errors

Performance Optimization

Client-Side

  • Hardware acceleration: Ensure it’s enabled in browser settings
  • Browser choice: Chrome/Edge have best WebRTC performance
  • Close other tabs: Reduce CPU/memory pressure
  • Wired connection: WiFi adds latency and packet loss
  • Disable browser extensions: Ad blockers can interfere with WebRTC

CDN and Caching

For global deployments:
For Cloudflare:

Security Best Practices

Production security checklist:
  • Always serve client over HTTPS
  • Implement authentication before allowing connections
  • Rate limit matchmaker API requests
  • Add Content Security Policy (CSP) headers
  • Validate all user input before sending to host
  • Monitor for abuse (rapid connection attempts, etc.)
  • Use environment variables for service URLs (if using a build step)
  • Keep WebRTC implementation up to date

Content Security Policy

Add CSP headers to prevent XSS attacks:
Or configure in web server (nginx example):

Next Steps