# GroupChat2 Server The server is a Rust/Axum application that provides authentication, room and message APIs, WebSocket chat delivery, AI response orchestration, file uploads, and SQLite-backed persistence for GroupChat2. ## Stack - Rust 2021 - Axum and Tokio - SQLx with SQLite - JWT auth and Argon2 password hashing - OpenRouter for AI completions - Tavily or Brave for web search tools ## Responsibilities - Register and authenticate users - Support Nostr challenge/verify login - Manage rooms, members, invites, and profile updates - Persist messages, hashes, room settings, and AI metadata - Broadcast real-time events over WebSockets - Stream AI responses and tool usage events to connected clients - Store uploaded avatars and chat images - Serve built frontend assets in production ## Requirements - Rust toolchain with `cargo` - A valid `OPENROUTER_API_KEY` - A search provider configured through either Tavily or Brave ## Environment Copy `.env.example` to `.env` and fill in the values you need. ```bash cp .env.example .env ``` Important variables: - `BIND_ADDR`: server bind address, default `0.0.0.0:3001` - `RUST_LOG`: log level, default `info` - `DATABASE_URL`: SQLite connection string, default `sqlite:chat.db?mode=rwc` - `JWT_SECRET`: JWT signing secret - `OPENROUTER_API_KEY`: required - `SEARCH_PROVIDER`: `tavily` or `brave` - `TAVILY_API_KEY`: required when `SEARCH_PROVIDER=tavily` - `BRAVE_API_KEY`: required when `SEARCH_PROVIDER=brave` - `STATIC_DIR`: optional path to built client assets for production serving ## Commands Run the backend directly: ```bash cargo run ``` Build a release binary: ```bash cargo build --release ``` From the repo root, production build/run is also available through: ```bash ./prod.sh ``` ## Startup Behavior On startup the server: - loads environment variables from `.env` - validates required AI/search configuration - creates a timestamped backup of the SQLite database if it already exists - keeps the 10 most recent backups - opens the SQLite database - applies SQL migrations embedded in the binary ## API Surface Main routes exposed by the server: - `/api/auth/register` - `/api/auth/login` - `/api/auth/me` - `/api/auth/profile` - `/api/auth/avatar` - `/api/auth/nostr/challenge` - `/api/auth/nostr/verify` - `/api/rooms` - `/api/rooms/:room_id` - `/api/rooms/:room_id/messages` - `/api/rooms/:room_id/join` - `/api/rooms/:room_id/clear` - `/api/messages/hash/:hash` - `/api/models` - `/api/invites` - `/api/invites/:token/accept` - `/api/invites/nostr` - `/api/upload` - `/ws` - `/uploads/*` ## Real-Time Flow WebSocket clients connect to `/ws` with a JWT token in the query string. Client messages include: - `join_room` - `typing` - `send_message` Server events include: - new messages - AI typing notifications - AI stream chunks and stream end markers - AI tool usage updates - user typing notifications - room deleted and room cleared events ## Storage Layout ```text server/ |- migrations/ SQL schema and incremental changes |- src/ handlers, middleware, models, services |- uploads/ avatars and chat images |- backups/ automatic database backups |- chat.db SQLite database ``` Uploaded file behavior: - avatars are stored under `uploads/avatars/` - chat images are stored under `uploads/chat-images/` - avatar uploads are limited to 2 MB - chat image uploads are limited to 5 MB ## AI Behavior When a user mentions the assistant or the room is configured to always respond, the server: - loads recent room history - includes image context for human-uploaded images when available - calls OpenRouter in streaming mode - executes tool calls for search or page fetches - broadcasts streaming output to the room - stores the final AI response with usage metadata For frontend behavior and local browser setup, see the [Client README](../client/README.md).