# GroupChat2 Client

The client is a Riot.js single-page application that handles authentication, room navigation, chat rendering, invite flows, profile editing, and the live chat experience on top of the server's REST and WebSocket APIs.

## Stack

- Riot.js components
- Vite dev/build pipeline
- Vanilla JavaScript
- `markdown-it` and `highlight.js` for message rendering

## Responsibilities

- Render login and registration flows
- Show the room list, active chat, and profile UI
- Connect to the server over WebSockets for live updates
- Stream AI responses into the message list as they arrive
- Support invite links and message permalink navigation
- Upload avatars and chat images through the API
- Handle token expiry by logging the user out cleanly

## Commands

```bash
npm install
npm run dev
```

```bash
npm run build
```

```bash
npm run preview
```

By default Vite runs on port `3000`.

## Dev Server Behavior

The Vite config proxies these paths to the backend:

- `/api`
- `/ws`
- `/uploads`

Relevant runtime vars:

- `VITE_PORT`: client port, default `3000`
- `VITE_API_PORT`: backend port, default `3001`

This lets the frontend use relative paths in development and production.

## App Structure

```text
src/
|- components/   Riot UI components for auth, rooms, messages, modals, profile
|- services/     API wrapper, WebSocket manager, markdown, avatar, Nostr helpers
|- styles/       Global styles
|- main.js       Component registration and app mount
```

Main UI pieces:

- `app.riot`: top-level auth state, room state, modal state, and message link handling
- `chat-sidebar.riot`: room list and account actions
- `chat-room.riot`: main conversation view and composer
- `message-bubble.riot`: message rendering, hashes, metadata, and markdown output
- `profile-page.riot`: display name and avatar management

## Runtime Notes

- Authentication state is stored in `localStorage`.
- Pending invite tokens and message permalinks are staged through `sessionStorage` when needed.
- The WebSocket layer automatically reconnects and re-joins subscribed rooms.
- AI output is streamed chunk-by-chunk and rendered progressively before the final stored message arrives.
- Message links support both `#roomId/messageHash` and older hash-only navigation.

## Integration Contract

The client expects the backend to provide:

- JWT auth endpoints under `/api/auth/*`
- Room, message, invite, upload, and model endpoints under `/api/*`
- A WebSocket endpoint at `/ws?token=...`
- Uploaded media under `/uploads/*`

For backend setup and env configuration, see the [Server README](../server/README.md).
