Anonymous, serverless, end-to-end encrypted group chat using WebRTC peer-to-peer connections via BitTorrent trackers.
๐ Live Demo (when running locally)
Pentagram.foo is a privacy-first chat application that requires no servers, accounts, or personal data. All communication happens directly between users through WebRTC peer-to-peer connections, coordinated via public BitTorrent trackers.
- ๐ Zero-Server Architecture: No central servers, all P2P via WebRTC
- ๐ป Anonymous by Design: No accounts, emails, or personal data required
- ๐ก๏ธ Privacy-First: End-to-end encrypted with Ed25519 signatures
- โก Instant Access: Share links to create/join rooms immediately
- ๐ฏ KISS Implementation: Simple, maintainable codebase
- Modern browser with WebRTC support (Chrome 80+, Firefox 72+, Safari 14+)
- Node.js (v18+) and bun or npm.
# Clone the repository
git clone https://github.com/your-repo/pentagram.foo.git
cd pentagram.foo
# Install dependencies
bun install
# or
npm install
# Start development server
bun run dev
# or
npm run dev
# Open browser
http://localhost:3000- Choose Username: Enter any username (no registration needed)
- Create/Join Room: Enter room name and optional password
- Share Link: Copy room link to invite others
- Start Chatting: Messages are encrypted and signed automatically
| Component | Technology | Purpose |
|---|---|---|
| Frontend | Alpine.js v3.14.9 | Reactive UI framework |
| P2P Networking | Trystero v0.21.6 | WebRTC abstraction |
| Signaling | BitTorrent Trackers | Serverless peer discovery |
| Cryptography | @noble/ed25519 | Message signing/verification |
| Styling | Tailwind CSS | Utility-first styling |
| Build | Vite | Development and bundling |
pentagram-foo/
โโโ index.html # Single Page Application
โโโ src/
โ โโโ main.js # Application entry point
โ โโโ styles.css # Tailwind CSS styles
โ โโโ components/
โ โ โโโ pentagram-app.js # Main Alpine component
โ โ โโโ connection-status.js # P2P status monitor
โ โโโ services/
โ โโโ room-manager.js # Trystero P2P management
โ โโโ crypto-utils.js # Ed25519 cryptography
โ โโโ storage-manager.js # localStorage abstraction
โโโ tests/ # Playwright test suites
โโโ docs/ # Documentation
Each user automatically gets:
- Ed25519 Key Pair: Generated client-side, never transmitted
- Digital Signatures: All messages cryptographically signed
- Identity Portability: Export/import keys as JSON files
- No Registration: Identity exists only in browser storage
- Transport: WebRTC DTLS (built-in P2P encryption)
- Session: Trystero AES-GCM (session data encryption)
- Room: Optional password-based room encryption
- Message: Ed25519 signatures for authenticity
- No Data Persistence: Messages only exist during session
- No Server Logs: Direct peer-to-peer communication
- Anonymous Identities: No real-world correlation
- Ephemeral Rooms: Exist only while users connected
Pentagram.foo uses BitTorrent trackers for WebRTC signaling:
// Default tracker configuration
relayUrls: [
'wss://tracker.webtorrent.dev',
'wss://tracker.openwebtorrent.com',
'wss://tracker.webtorrent.io',
'wss://tracker.btorrent.xyz',
'wss://spacetradersapi-chatbox.herokuapp.com'
]Benefits:
- Decentralized: No single point of failure
- Battle-tested: Mature BitTorrent infrastructure
- Free: No API keys or accounts needed
- Redundant: Multiple trackers for reliability
interface ChatMessage {
id: string // UUID for deduplication
content: string // Message text
username: string // Sender's chosen username
timestamp: number // Unix timestamp
signature: number[] // Ed25519 signature (as array)
}
interface UserInfo {
username: string // Display name
publicKey: number[] // Ed25519 public key (as array)
joinedAt: number // Join timestamp
}The application uses Alpine.js for reactive UI management:
Alpine.data('pentagramApp', () => ({
// Persisted state
username: Alpine.$persist('').as('pentagram-username'),
identity: Alpine.$persist(null).as('pentagram-identity'),
// Session state
isConnected: false,
peers: new Map(),
messages: [],
// Services
roomManager: null,
cryptoManager: null,
// Lifecycle
async init() {
await this.initializeServices()
await this.initializeIdentity()
this.loadRoomFromURL()
}
}))Message signing and verification:
// Sign outgoing message
const signature = await cryptoManager.signMessage(messageText)
const message = {
content: messageText,
signature: Array.from(signature),
// ... other fields
}
// Verify incoming message
const isValid = await cryptoManager.verifyMessage(
message.content,
new Uint8Array(message.signature),
peer.publicKey
)// Join room via BitTorrent trackers
const room = await roomManager.joinRoom(roomId, password)
// Setup communication channels
const [sendMessage, getMessage] = room.makeAction('message')
const [sendUserInfo, getUserInfo] = room.makeAction('userInfo')
// Handle peer events
room.onPeerJoin(peerId => {
// Send user info to new peer
sendUserInfo({ username, publicKey }, peerId)
})- Location:
src/services/room-manager.js - Key Concept: Using BitTorrent trackers as signaling servers
- Innovation: No backend infrastructure required
- Location:
src/services/crypto-utils.js - Key Concept: Ed25519 signatures for message authenticity
- Security: Keys never leave the browser
- Location:
src/components/pentagram-app.js - Key Concept: Graceful degradation when P2P fails
- UX: Clear status indicators and error handling
- Location: Alpine.js
$persistusage - Key Concept: Identity survives browser refresh
- Privacy: Data stays local, exportable for backup
- Location: Message handling in
pentagram-app.js - Key Concept: Signed messages with verification
- Performance: Direct peer-to-peer, no relay servers
- Location:
src/components/connection-status.js - Key Concept: Real-time tracker connection status
- UX: Visual feedback for P2P network health
- Location: URL handling and room link generation
- Key Concept: Shareable URLs with optional passwords
- Usability: One-click room joining
- Location:
handleIncomingMessage()function - Key Concept: Reject messages with invalid signatures
- Security: Prevents message spoofing
- Location: Error handling throughout room management
- Key Concept: Informative error messages for P2P issues
- Reliability: Fallback states and retry mechanisms
- Location: CDN-based dependency loading
- Key Concept: No build step required for basic usage
- Accessibility: Lower barrier to entry
# Install Playwright (if needed)
npm install @playwright/test
# Run all tests
npx playwright test
# Run specific test suites
npx playwright test tests/basic-functionality.spec.js
npx playwright test tests/crypto-identity.spec.js
npx playwright test tests/p2p-connection.spec.js
# Interactive testing
npx playwright test --ui- Basic Functionality: UI components, form validation
- Cryptographic Identity: Key generation, signing, verification
- P2P Connections: Room joining, peer discovery, messaging
- Error Handling: Network failures, invalid data
- Multi-User Chat: Open multiple browser tabs/windows
- Cross-Browser: Test in Chrome, Firefox, Safari
- Network Conditions: Test with slow/intermittent connections
- Identity Management: Export/import keys, clear data
โ Implemented:
- Anonymous identity system (Ed25519)
- P2P room management (Trystero + BitTorrent)
- Secure messaging with signatures
- Real-time peer discovery
- Connection quality monitoring
- Identity export/import
๐ In Progress:
- Voice communication (WebRTC audio streams)
- Progressive Web App features
- Performance optimizations
๐ Planned:
- File sharing
- Emoji reactions
- Message history
- Mobile optimizations
# Development dependencies
npm install
# Start development server
npm run dev
# Run tests
npm run test
# Code formatting
npm run format- JavaScript: ES2022, async/await patterns
- Alpine.js: Composition API, avoid deep nesting
- CSS: Tailwind utilities, minimal custom CSS
- Security: Input sanitization, CSP headers
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Run tests (
npm run test) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Trystero: Excellent WebRTC P2P library
- Alpine.js: Lightweight reactive framework
- @noble/ed25519: Pure JavaScript Ed25519 implementation
- BitTorrent Community: Decentralized tracker infrastructure
- WebRTC Specification: Enabling direct peer communication
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Security: Report vulnerabilities via private disclosure
Built with โค๏ธ for privacy, decentralization, and user freedom.
No servers โข No accounts โข No tracking โข Just pure P2P communication