Files
Messenger/README.md
T
vantablackTea c79a3cfe68
CI / Go (build + vet + test) (push) Canceled after 0s
CI / Web (build + lint) (push) Canceled after 0s
backend barebone done, big chunk of work done
2026-09-27 19:42:49 +03:00

106 lines
4.4 KiB
Markdown

# 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.