# rony-chat-widget
A drop-in vanilla-JS chat widget that talks to the Rony Chat Bot backend over Server-Sent Events. No build step, no runtime dependencies, no global CSS pollution.
## Files
| File | Purpose |
|---|---|
| `chat-widget.js` | The widget. Self-contained ~12 KB. |
| `chat-widget.css` | Scoped styles, themable via CSS custom properties. |
| `example.html` | Standalone demo page (use with `python3 -m http.server`). |
## Quick start (any site)
```html
```
The bubble appears bottom-right (or bottom-left), opens a 380×560 panel, and talks to `data-api-url/api/chat` over SSE.
## Configuration (all via `data-*` attributes on the `
```
## Theming (override without forking)
All visual tokens are CSS custom properties on the root element. Set them in your site's stylesheet:
```css
.rony-chat-widget-root {
--rony-accent: #ff6b35; /* bubble + send button + links */
--rony-radius: 4px; /* tighter corners */
--rony-font: "Inter", sans-serif;
}
```
See the full list in `chat-widget.css` (search for `--rony-`).
## Astro integration
The simplest path is the drop-in. Add this to your `Layout.astro` (or any shared layout):
```astro
---
// src/layouts/ChatLayout.astro
import "../path/to/chat-widget.css";
const apiUrl = import.meta.env.PUBLIC_CHAT_API_URL || "http://localhost:7331";
---
```
Notes:
- `is:inline` keeps Astro from hashing/transforming the script tag, so the `data-*` attributes survive.
- `PUBLIC_CHAT_API_URL` is an Astro env var; set it in `.env` per environment.
- The bot's `cors_origins` in YAML must include your Astro dev origin (`http://localhost:4321`).
## React/Next.js
Mount the same script tag in your root layout:
```tsx
// app/layout.tsx
import Script from "next/script";
export default function RootLayout({ children }) {
return (
{children}
);
}
```
## Backend requirements
The widget expects the bot to:
1. Expose `POST /api/chat` accepting `{ messages, stream }` (see `docs/architecture.md` §3.1).
2. Stream SSE events: `start`, `chunk`, `sources`, `done`, `error` (see `docs/architecture.md` §3.2).
3. Allow the page's origin via `cors_origins` in the bot's config.
## Running the example locally
```bash
# 1. Start the bot
./bin/chat-bot serve
# 2. Serve the widget (in another terminal)
cd web
python3 -m http.server 8000
# 3. Open http://localhost:8000/example.html in a browser
```
> Note: `localhost:8000` must be in the bot's `cors_origins` for the demo to work. The default config already includes it.
## Browser support
Modern browsers (Chrome/Edge 90+, Firefox 90+, Safari 15+). Uses:
- `fetch` + `ReadableStream` (for SSE)
- `AbortController`
- CSS custom properties + `prefers-color-scheme`
No polyfills, no transpilation.
## What's not in the widget (yet)
- **Conversation persistence** — each visit is a fresh conversation. The bot is stateless; add a `conversation_id` cookie + server-side history if you want continuity.
- **Markdown images / tables** — the renderer handles paragraphs, lists, code, links, bold/italic. Tables and images render as raw text. For richer output, swap `renderMarkdown` for `marked` or `markdown-it`.
- **Typing indicators beyond the streaming caret** — the caret at the end of the streaming response is the only indicator. Good enough for short answers.
- **Mobile sheet drag-to-dismiss** — the panel goes full-screen on phones, but can't be swiped away. Add a swipe handler if it matters.