From 6483670dc7f714a094c2f50d3f2bc0df95152fe3 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 10 Feb 2026 10:21:10 -0800 Subject: [PATCH] docs: emphasize API-first design, add curl examples, note web client as reference impl --- README.md | 73 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 67bf231..5660b06 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,11 @@ A modern IRC-inspired chat server written in Go. Decouples session state from transport connections, enabling mobile-friendly persistent sessions over HTTP. +The **HTTP API is the primary interface**. It's designed to be simple enough +that writing a terminal IRC-style client against it is straightforward — just +`curl` and `jq` get you surprisingly far. The server also ships an embedded +web client as a convenience/reference implementation, but the API comes first. + ## Motivation IRC is in decline because session state is tied to the TCP connection. In a @@ -12,7 +17,7 @@ or pay for IRCCloud. This project builds a chat server that: - Holds session state server-side (message queues, presence, channel membership) -- Delivers messages over HTTP (JSON-RPC style) +- Exposes a minimal, clean HTTP+JSON API — easy to build clients against - Supports multiple concurrent connections per user session - Provides IRC-like semantics: channels, nicks, topics, modes - Uses structured JSON messages with arbitrary extensibility @@ -24,12 +29,15 @@ This project builds a chat server that: All client↔server and server↔server communication uses HTTP/1.1+ with JSON request/response bodies. No WebSockets, no raw TCP, no gRPC — just plain HTTP. -- **Client polling**: Clients poll for new messages via `GET` with long-polling - support (server holds the connection open until messages arrive or timeout) -- **Client sending**: Clients send messages/commands via `POST` +- **Client polling**: Clients long-poll `GET /api/v1/messages` — server holds + the connection until messages arrive or timeout. One endpoint for everything. +- **Client sending**: `POST /api/v1/messages` with a `to` field. That's it. - **Server federation**: Servers exchange messages via HTTP to enable multi-server networks (like IRC server linking) +The entire read/write loop for a client is two endpoints. Everything else is +channel management and history. + ### Core Concepts #### Users @@ -90,9 +98,37 @@ Fields: All endpoints accept and return `application/json`. Authenticated endpoints require `Authorization: Bearer ` header. -The API follows an IRC-inspired design: one unified message stream for all -message types (channel messages, DMs, server notices), with a simple `to` field -for addressing. +The API is the primary interface — designed for IRC-style clients. The entire +client loop is: + +1. `POST /api/v1/register` — get a token +2. `GET /api/v1/state` — see who you are and what channels you're in +3. `GET /api/v1/messages?after=0` — long-poll for all messages (channel, DM, system) +4. `POST /api/v1/messages` — send to `"#channel"` or `"nick"` + +That's the core. Everything else (join, part, history, members) is ancillary. + +#### Quick example (curl) + +```bash +# Register +TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/register \ + -d '{"nick":"alice"}' | jq -r .token) + +# Join a channel +curl -s -X POST http://localhost:8080/api/v1/channels/join \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"channel":"#general"}' + +# Send a message +curl -s -X POST http://localhost:8080/api/v1/messages \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"to":"#general","content":"hello world"}' + +# Poll for messages (long-poll) +curl -s http://localhost:8080/api/v1/messages?after=0 \ + -H "Authorization: Bearer $TOKEN" +``` #### Registration @@ -259,18 +295,29 @@ Per gohttpserver conventions: | Metrics | `github.com/prometheus/client_golang` | | DB | `modernc.org/sqlite` + `database/sql` | +### Web Client + +The server embeds a single-page web client (Preact) served at `/`. This is a +**convenience/reference implementation** — not the primary interface. It +demonstrates the API and provides a quick way to test the server in a browser. + +The primary intended clients are IRC-style terminal applications and bots +talking directly to the HTTP API. + ### Design Principles -1. **HTTP is the only transport** — no WebSockets, no raw TCP, no protocol +1. **API-first** — the HTTP API is the product. Clients are thin. If you can't + build a working IRC-style TUI client in an afternoon, the API is too complex. +2. **HTTP is the only transport** — no WebSockets, no raw TCP, no protocol negotiation. HTTP is universal, proxy-friendly, and works everywhere. -2. **Server holds state** — clients are stateless. Reconnect, switch devices, +3. **Server holds state** — clients are stateless. Reconnect, switch devices, lose connectivity — your messages are waiting. -3. **Structured messages** — JSON with extensible metadata. Enables signatures, +4. **Structured messages** — JSON with extensible metadata. Enables signatures, rich content, client extensions without protocol changes. -4. **Simple deployment** — single binary, SQLite default, zero mandatory +5. **Simple deployment** — single binary, SQLite default, zero mandatory external dependencies. -5. **No eternal logs** — history rotates. Chat should be ephemeral by default. -6. **Federation optional** — single server works standalone. Linking is opt-in. +6. **No eternal logs** — history rotates. Chat should be ephemeral by default. +7. **Federation optional** — single server works standalone. Linking is opt-in. ## Status