Minimal E2E-encrypted chat server. فارسی (Persian) → HTTP + WebSocket only. End-to-end encryption between users; server stores only username→pubkey and temporary offline queue (deleted after delivery). Everything else on client. Works fully offline—no external scripts or CDNs.
- End-to-end encryption — Messages encrypted between clients; server never sees plain text
- Passkey or recovery phrase — Sign in with passkey (WebAuthn) or 12-word mnemonic
- Encrypted local storage — Messages in IndexedDB encrypted with key derived from your credentials
- User directory — Browse and search registered users to start chats
- Group chat — Create groups, invite users, accept or decline invites; group messages are E2E encrypted
- Shareable links — Share
/u/usernameso others can message you directly - QR code — Profile QR for easy sharing (bundled locally, no internet)
- Mobile-friendly — Responsive layout, notifications
- Multi-account — Multiple accounts per browser; messages scoped per user
- Offline-first — All assets bundled; works in air-gapped or restricted networks
docker compose up -dgo run ./cmd/server- Setup — Sign in with passkey or enter a 12-word recovery phrase (or generate one) and click Continue
- Register — Choose a username and register
- New chat — Click "New chat" to browse users, search, and start a conversation
- Share — Copy your chat link (e.g.
http://localhost:8080/u/alice) or share the QR code from Profile - Chat — Messages are E2E encrypted; only you and the recipient can read them. Use New group to create group chats and invite others.
- Unit tests (Vitest):
npm test - E2E tests (Playwright, group chat): create group, invite user, accept/decline invite, send message in group.
# One-time: install Node deps and Playwright browser
npm install
npm run e2e:install
# Run E2E (starts server automatically, or use existing server)
npm run e2eTo use an already-running server on port 8080: SKIP_WEB_SERVER=1 npm run e2e.
PORT(default: 8080)DATA_DIR(default:./dataor/datain Docker)
# Build and push both platforms (for K8s, Docker Hub, etc.)
./scripts/build-docker.sh YOUR_USERNAME/war-chat:latest
# Local build (amd64 only, load into docker)
./scripts/build-docker.sh war-chat:latest --load# Log in first (one-time)
docker login
# Build and push (replace YOUR_USERNAME with your Docker Hub username)
./scripts/build-docker.sh YOUR_USERNAME/war-chat:latestPull and run:
docker run -d -p 8080:8080 -v war-chat-data:/data YOUR_USERNAME/war-chat:latestKubernetes: The build uses
--provenance=falseso the manifest contains only amd64 and arm64 images. This avoids "exec format error" from K8s pulling attestation manifests by mistake.
The image uses a minimal scratch base (no OS, no packages) for zero vulnerabilities. Run docker scout quickview war-chat:latest to verify.