A peer-to-peer messaging application where users can send messages directly to each other without the server accessing message content. The server only facilitates initial connection (signaling), after which all communication is direct between users via WebRTC DataChannels.
- True P2P Messaging: Messages go directly between peers, never through the server
- No Account Required: Just create a room and share the link
- Real-time Communication: Instant messaging via WebRTC DataChannels
- Connection Status: Visual indicator showing connection state
- Privacy First: Server only handles signaling, never sees message content
| Layer | Technology |
|---|---|
| Frontend | Next.js 16 (App Router), React 19, TypeScript |
| Styling | Tailwind CSS v4 |
| Signaling | Socket.io |
| P2P | WebRTC DataChannels |
| Package Manager | Bun |
- Bun installed
-
Clone the repository
git clone https://github.com/crafter-station/p2p-chat.git cd p2p-chat -
Install dependencies
# Frontend bun install # Signaling server cd signaling && bun install
-
Start the signaling server (Terminal 1)
cd signaling bun dev -
Start the frontend (Terminal 2)
bun dev
-
Open the app
- Navigate to http://localhost:3000
- Create a room and share the link with another user
NEXT_PUBLIC_SIGNALING_URL=http://localhost:3001PORT=3001
FRONTEND_URL=http://localhost:3000- Import repo to Vercel
- Set environment variable:
NEXT_PUBLIC_SIGNALING_URL= your Railway signaling server URL
- Create new project on Railway
- Set root directory to
signaling - Set environment variable:
FRONTEND_URL= your Vercel frontend URL
┌─────────────────────────────────────────────────────────────┐
│ FRONTEND │
│ (Next.js 16) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Landing │ │ Chat Room │ │ WebRTC Hook │ │
│ │ Page │ │ Component │ │ (P2P Logic) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ WebSocket (signaling only)
▼
┌─────────────────────────────────────────────────────────────┐
│ SIGNALING SERVER │
│ (Socket.io + Bun) │
│ │
│ • Room management (join/leave) │
│ • SDP offer/answer relay │
│ • ICE candidate relay │
│ • NO message storage, NO logging of content │
└─────────────────────────────────────────────────────────────┘
│
│ STUN (NAT traversal)
▼
┌─────────────────────────────────────────────────────────────┐
│ EXTERNAL SERVICES │
│ │
│ • Google STUN servers (free) │
│ • stun:stun.l.google.com:19302 │
└─────────────────────────────────────────────────────────────┘
- User creates/joins room via frontend
- Frontend connects to signaling server via WebSocket
- Signaling server relays SDP offers/answers and ICE candidates
- Once P2P connection established, all messages go directly between peers
- Signaling server never sees message content
# Frontend
bun dev # Start development server
bun build # Production build
bun start # Start production server
bun lint # Check for linting errors
bun format # Format code
# Signaling Server
cd signaling
bun dev # Start development server
bun run build # Compile TypeScriptMIT