Skip to content

Prototype direct Personal WP desktop access#3758

Draft
akirk wants to merge 1 commit into
WordPress:trunkfrom
akirk:personal-wp-desktop-webrtc-trunk
Draft

Prototype direct Personal WP desktop access#3758
akirk wants to merge 1 commit into
WordPress:trunkfrom
akirk:personal-wp-desktop-webrtc-trunk

Conversation

@akirk
Copy link
Copy Markdown
Member

@akirk akirk commented Jun 6, 2026

What this explores

This is a smaller, trunk-based alternative to #3746. It keeps the same product goal: let someone open the Personal WP instance running on their phone from a desktop browser while the phone remains nearby and connected.

The main difference is transport. #3746 proxies WordPress HTTP requests and responses through the PHP relay. This PR uses the PHP relay only for rendezvous and WebRTC signaling, then sends WordPress HTTP traffic over a direct browser-to-browser WebRTC DataChannel.

Related PRs:

User flow

On the phone:

  1. Open Personal WP.
  2. Open Site Tools.
  3. In the "Use on desktop" section, start desktop access.
  4. The phone shows a desktop URL and a six-digit access code.
  5. Keep the phone tab open while using the desktop.

On the desktop:

  1. Open /connect on the same Personal WP deployment.
  2. Enter the six-digit code from the phone.
  3. The desktop navigates to the shared viewer URL.
  4. The viewer connects to the phone via WebRTC.
  5. The iframe loads WordPress through the existing Playground scoped URL shape.

While connected, the desktop page renders the WordPress instance that is still running on the phone.

Architecture

The PHP relay stores only session and signaling data in one MySQL table:

CREATE TABLE mywp_desktop_access_sessions (
  session_id varchar(64) NOT NULL PRIMARY KEY,
  access_code varchar(7) NOT NULL UNIQUE,
  payload json NOT NULL,
  created_at_ms bigint unsigned NOT NULL,
  last_activity_ms bigint unsigned NOT NULL,
  KEY access_code_idx (access_code),
  KEY last_activity_idx (last_activity_ms)
);

The JSON payload contains:

  • session id
  • access code
  • host/guest heartbeat state
  • WebRTC offer
  • WebRTC answer
  • ICE candidates
  • small sequence counters

It does not expose a /relay/:session/request/* HTTP proxy in this branch.

The request path is:

  1. Desktop iframe requests /scope:default/....
  2. The Playground service worker sees the scoped request.
  3. The service worker posts a serialized request to the desktop viewer page.
  4. The desktop viewer sends that request over a WebRTC DataChannel.
  5. The phone receives it and calls playgroundClient.request(...).
  6. The phone serializes the response and sends it back over the DataChannel.
  7. The desktop service worker builds a Response for the iframe.

So WordPress request/response bodies are intended to stay out of PHP and MySQL in this approach.

Difference from #3746

#3746:

  • Adds a PHP HTTP relay endpoint for WordPress requests.
  • Stores queued HTTP request/response payloads on the relay temporarily.
  • Needs relay request handling, response handling, batching/backpressure work, and URL/redirect handling.
  • Works even when phone and desktop cannot establish a direct peer connection, as long as both can reach the relay.

This PR:

  • Is based directly on trunk.
  • Uses a compact signaling-only PHP relay backed by a single MySQL table.
  • Does not include the old request relay, request batching, URL rewriting, or TunnelHost HTTP polling implementation.
  • Sends WordPress HTTP traffic over WebRTC DataChannel.
  • Has a smaller diff than the stacked HTTP relay branch.

Privacy and data handling

This approach reduces what the relay sees. MySQL still temporarily stores WebRTC setup metadata, but it should not store WordPress HTTP bodies, cookies, admin requests, HTML, CSS, JS, media, or form submissions.

The desktop and phone exchange those request/response payloads directly over the WebRTC DataChannel.

Server configuration

The relay reads DB configuration from these env/server variables, in order:

  • PLAYGROUND_RELAY_DB_HOST, MYWP_DB_HOST, DB_HOST
  • PLAYGROUND_RELAY_DB_USER, MYWP_DB_USER, DB_USER
  • PLAYGROUND_RELAY_DB_PASSWORD, MYWP_DB_PASSWORD, DB_PASSWORD
  • PLAYGROUND_RELAY_DB_NAME, MYWP_DB_NAME, DB_NAME
  • PLAYGROUND_RELAY_DB_PORT, MYWP_DB_PORT, DB_PORT

PLAYGROUND_RELAY_PUBLIC_BASE_URL may be set to force generated desktop share URLs.

The table is created lazily with CREATE TABLE IF NOT EXISTS.

Caveats

This is a prototype.

The WebRTC peer connection currently uses no STUN or TURN servers:

iceServers: []

That keeps the first version focused on same-network/direct connectivity. It may fail on networks where the browsers cannot discover a usable direct route. Adding STUN would likely improve direct connection setup. Adding TURN would improve reliability further, but TURN would relay encrypted WebRTC traffic and change the privacy tradeoff.

The phone tab must stay open. The desktop is a viewer/control surface for the running phone Playground runtime.

Installing apps via postMessage from the desktop viewer is still reported as unsupported for now.

Validation

Ran:

  • php -l packages/playground/personal-wp/public/relay.php
  • npm exec nx typecheck playground-personal-wp
  • npm exec nx typecheck playground-remote

I did not run the full build or deployment scripts.

@akirk akirk force-pushed the personal-wp-desktop-webrtc-trunk branch from aa0319e to 07016be Compare June 6, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant