concept-collection / trystero-messaging-demo
trystero-messaging-demo / README.md
4.7 KBPreviewCodeBlameHistoryRaw

Trystero P2P Messaging Demo#

A tiny serverless, peer-to-peer messaging web app built on Trystero. Everyone who opens the app lands in the same room, sees everyone else who is connected, and can send text messages and large binary payloads directly to any other peer (or broadcast to all) — with live progress bars and SHA-256 integrity checks.

No backend, no accounts, no infrastructure. Peer discovery happens over the public Nostr relay network (Trystero's default strategy); after that, all data travels directly browser-to-browser over WebRTC, end-to-end encrypted.

Built with Vite + React + TypeScript.

▶ Live demo: https://concept-collection.github.io/trystero-messaging-demo/ (open it in two tabs to see peers connect)

Quick start#

npm install
npm run dev

Open the printed URL (e.g. http://localhost:5173). Then open the same URL in another browser tab, another browser, or another device. Within a few seconds the two tabs discover each other and appear in each other's peer list.

The first connection can take a few seconds while peers find each other on the Nostr relays. A couple of relays in the default list may be offline at any time — Trystero connects to several for redundancy, so this is expected and harmless.

What it demonstrates#

How it maps to the Trystero API#

Everything P2P lives in src/useRoom.ts:

import {joinRoom, selfId} from 'trystero' // default export = Nostr strategy

const room = joinRoom({appId: APP_ID}, roomId)

const chat = room.makeAction<string>('chat')
const binary = room.makeAction('binary')

room.onPeerJoin = peerId => name.send(myName, {target: peerId})
room.onPeerLeave = peerId => { /* drop from roster */ }

chat.onMessage = (text, {peerId}) => { /* show it */ }

binary.send(bytes, {
  target: peerId,            // or omit to broadcast
  metadata: {fileName, mime, size, transferId},
  onProgress: pct => updateBar(pct)
})
binary.onReceiveProgress = (pct, {peerId, metadata}) => updateBar(pct)
binary.onMessage = (data, {peerId, metadata}) => { /* data is an ArrayBuffer */ }

Rooms#

Everyone shares one room (lobby) by default. To use an isolated room, add a hash to the URL, e.g. http://localhost:5173/#my-room. Anyone using the same #hash is in the same room; the change is shareable as a link.

Project layout#

src/
  config.ts            APP_ID + room handling
  useRoom.ts           Trystero wrapper hook (presence, names, text + binary)
  util.ts              byte formatting, SHA-256, random payload generator
  types.ts             shared types
  App.tsx              layout + target selection
  components/
    Header.tsx         identity, room, relay/peer status
    PeerList.tsx       pick who to message (a peer or "Everyone")
    Composer.tsx       send text / file / random binary
    TransferList.tsx   live progress bars
    MessageLog.tsx     message + transfer history

Scripts#

Command Description
npm run dev Start the Vite dev server
npm run build Type-check and build for production
npm run preview Preview the production build locally

Notes#