diff --git a/README.md b/README.md new file mode 100644 index 0000000..74aecc2 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# User to Support Chat + +Real-time support chat in Rust. Users start conversations, supporters reply from a dashboard. Everything lives in RAM, nothing persists, and it all resets every 20 minutes. Like a café where everyone gets kicked out when the clock strikes. Lovely. + +Anonymous by default, ephemeral by design. + +## What It Does + +- Users create sessions anonymously (UUIDs, not usernames) +- Supporters browse active chats and reply in real time +- WebSockets for typing indicators and live message pushes +- Rate limiting: 60 messages per IP per 20-minute window +- Auto-reset: clears all sessions, messages, and rate limits every 20 minutes + +## Tech Stack + +| Thing | Choice | Why | +|---|---|---| +| Language | Rust 1.96 | Single binary. No runtime. Panic = abort. | +| Framework | Axum | WebSocket support, typed routes, tokio-powered. | +| State | DashMap | Concurrent, lock-free, perfect for in-memory sessions. | +| Frontend | HTMX + vanilla JS | Less JavaScript, more HTML swaps. No bundlers. | +| Deployment | Bare metal + systemd | No Docker. No Podman. Just a binary and a `.service` file. | + +## Running It + +The `justfile` handles everything, but you'll need to [install](https://just.systems/man/en/installation.html) it on your machine. + +```bash +just build # clippy + fmt + release +just run # dev mode with hot reload +just deploy # rsync to server + restart systemd +just logs # tail remote journalctl +``` + +Server binds on `0.0.0.0:3111`. Landing page at `/`, user view at `/user`, supporter dashboard at `/supporter`. + +## Key Behaviors + +- Sessions are created via POST to `/api/session/create` — returns JSON with UUID +- Messages sent via HTMX forms to `/send/:session_id` or `/supporter/send/:session_id` +- WebSocket connects to `/ws/user/:session_id` (user) or `/ws/supporter/:supporter_id` +- Reset countdown shown in navbar, auto-refreshes every second +- Typing indicators broadcast via WebSocket using prefixes like `typing:user:start:` + +--- + +**For production use, you'd want a database, auth, TLS, and probably less drama.**