About Workshop Chat
A fully static, serverless peer-to-peer chat built for live PHP workshops — no sign-up, no database, nothing stored on a server.
Two roles
Controller
The workshop host opens the app and starts a room. A 5-digit PIN and QR code appear — these go on the beamer. The controller's view shows the full chat feed, a participant list, and lets the host assign team colours.
Participant
Attendees open /chat/?room=<name> (from the QR code or a link) and type the PIN. After choosing a display name they're live in the chat, able to send messages and share syntax-highlighted code snippets in PHP, JavaScript, Python, HTML, CSS, or plain text.
Connection diagram
(signaling only)
Cloud
(signaling only)
data channel (DTLS)
PeerJS server not involved
⚠️ If a direct path cannot be established (strict firewall / symmetric NAT), traffic may route via a TURN relay server — see Privacy below.
Step-by-step connection flow
-
1Controller registers a Peer ID On session start the controller generates a random 5-digit PIN and registers the Peer ID
phpgrn-{PIN}on the PeerJS signaling server. The server hands back a confirmation — no message content is involved. -
2QR code & join URL generated The app builds a join URL (
/chat/?room=name) and encodes it in a QR code entirely in the browser — no server call. If Network relay mode is enabled,&relay=1is appended so participants automatically inherit the relay setting. -
3Participant scans / types the PIN The participant's browser sends an SDP offer to
phpgrn-{PIN}via the PeerJS signaling server. The controller receives it and replies with an SDP answer. ICE candidates (network addresses) are also exchanged through this channel. -
4Direct WebRTC data channel opens Once ICE negotiation succeeds the browsers connect directly, encrypted with DTLS. The PeerJS signaling server is no longer involved. All chat messages, code snippets, history packets, and colour assignments travel through this channel.
-
5Controller relays to all participants The topology is a star: every participant connects to the controller, not to each other. When a participant sends a message the controller receives it and rebroadcasts it to all other connected participants. This keeps things simple and gives the controller full visibility.
-
6Session ends — everything is wiped When the controller closes the tab a
session-endmessage is broadcast. Each participant clears its feed, resets state, and returns to the start screen. Nothing is written to disk anywhere.
Privacy & data
Open-source libraries & services
This app is built entirely on open-source tools and free tiers. We gratefully acknowledge:
Simplifies WebRTC peer-to-peer connections with a clean JavaScript API. Provides the public signaling server and TURN relay infrastructure used to establish connections between browsers.
MIT LicenseAutomatic syntax detection and highlighting for code snippets. Used here with the GitHub light theme for clean, readable code blocks in PHP, JavaScript, Python, HTML, CSS, and plain text.
BSD 3-Clause LicenseProvides free TURN relay servers (50 GB/month) for when Network relay mode is needed. The host registers once and pastes credentials into the Start a Room form — no credentials are stored server-side by this app.
Free tier availableGenerates QR codes entirely in the browser using HTML5 Canvas. Used to encode the join URL so participants can scan it from the beamer without typing a long URL.
MIT LicenseFree CDN for open-source libraries, maintained by Cloudflare. Serves Highlight.js and QRCode.js. No tracking; files are delivered over HTTPS from global edge nodes.
Free / OpenA fast, global CDN for npm packages. Used to load the PeerJS client library directly from the npm registry.
Free / OpenServes the entire GroningenPHP website as a static site directly from the GitHub repository — no web server to manage and free for open-source projects.
Free for public repos