# Messenger Self-hosted messenger for family and friends. Built from scratch: Go backend, React PWA frontend, PostgreSQL, WebRTC calls. Deployed on a home-lab mini PC. > **Status:** Phase 1 — auth (JWT + refresh in httpOnly cookies, argon2id), > contacts, direct-message chats, real-time delivery over WebSocket > (messages, typing, presence, read receipts). Backend is complete and tested; > the frontend still shows the Phase 0 status screen. ## Repository layout ``` server/ Go API cmd/api/ entrypoint (wiring, migrations, graceful shutdown) internal/api/ HTTP handlers: auth, users, contacts, conversations, messages internal/auth/ argon2id hashing, JWT access tokens, refresh tokens internal/realtime/ WebSocket hub: events, presence, typing, read receipts internal/store/ PostgreSQL access (pgx), embedded migrations internal/platform/ config, structured logging web/ React + TypeScript + Vite frontend (PWA-ready) deploy/ docker-compose and operational config docs/ architecture, ADR, OpenAPI .github/ CI workflows ``` ## API (Phase 1) All endpoints under `/api/v1`. Auth via httpOnly cookies (`messenger_access` = JWT 15 min, `messenger_refresh` = opaque token 30 days, rotated on refresh). | Method | Path | Description | |--------|-----------------------------------|---------------------------------| | POST | `/api/v1/auth/register` | Create account (sets cookies) | | POST | `/api/v1/auth/login` | Sign in (sets cookies) | | POST | `/api/v1/auth/refresh` | Rotate refresh token | | POST | `/api/v1/auth/logout` | Revoke session, clear cookies | | GET | `/api/v1/users/me` | Current user | | GET | `/api/v1/users?q=` | Search users by username/name | | GET | `/api/v1/contacts` | Contact list | | POST | `/api/v1/contacts` | `{user_id}` — add contact | | DELETE | `/api/v1/contacts/{user_id}` | Remove contact | | GET | `/api/v1/conversations` | List chats + unread counts | | POST | `/api/v1/conversations` | `{user_id}` — create/find DM | | GET | `/api/v1/conversations/{id}/messages` | History, keyset `?before=` | | POST | `/api/v1/conversations/{id}/messages` | `{body, temp_id}` — send | | GET | `/ws` | WebSocket (auth via cookie) | WebSocket event types: `message.created`, `typing`, `presence`, `read`. ## Prerequisites - Go 1.27+ - Node.js 22+ - Docker + Docker Compose (for deployment) ## Local development Requires a local PostgreSQL (e.g. `sudo -u postgres psql -c "CREATE ROLE messenger LOGIN PASSWORD 'messenger';"` and `sudo -u postgres psql -c "CREATE DATABASE messenger OWNER messenger;"`). ```bash # Backend (migrations run automatically on start) cd server go run ./cmd/api # listen on :8080 # Frontend (separate terminal) cd web npm install npm run dev # Vite on :5173, proxies /api -> :8080 ``` The frontend calls `/api/v1/ping` on load and renders the server response. ## Useful endpoints | Endpoint | Purpose | |--------------|----------------------------------| | `/healthz` | Liveness probe | | `/readyz` | Readiness probe | | `/api/v1/ping` | Round-trip check (JSON) | ## Deployment (Docker Compose) ```bash cp deploy/.env.example deploy/.env # adjust secrets cd deploy docker compose up -d --build ``` The API container is a single static binary that also serves the built frontend (`/app/web`). PostgreSQL runs alongside with a healthcheck. ## Roadmap - **Phase 0** — skeleton, CI, Docker ✅ - **Phase 1** — auth (JWT + refresh in httpOnly cookie, argon2id), contacts, DMs, WebSocket delivery, receipts, typing ✅ (backend) - Phase 1.5 — frontend: auth screens, chat UI, realtime client (PWA) - Phase 2 — groups, reactions, media upload + thumbnails (S3-like storage interface) - Phase 3 — search (pg_trgm), Web Push (VAPID), PWA offline - Phase 4 — P2P WebRTC calls via our WebSocket signalling + coturn TURN fallback - Phase 5 — metrics (Prometheus + VictoriaMetrics + Grafana), docs, hardening ## License Proprietary for now; open-sourcing at v1.0.