Appearance
Build Your Own OpenClaw AI Chat
Fresh OpenClawA custom chat interface for your dashboard: floating bubble, full chat page, WebSocket streaming, and shared sessions.
Three files, about 1,100 lines, React + TypeScript. A floating bubble plus a full chat page plus a WebSocket proxy with shared sessions across interfaces.
Architecture: three layers, one conversation
Browser components talk to a WebSocket proxy, which talks to your AI gateway. Each layer handles its own concerns.
- Browser layer (React + TypeScript) -
ChatBubble.tsx(~280 lines) plusOpsChat.tsx(~450 lines). The components the user interacts with: floating popup and full-page layouts. - WebSocket proxy (Node.js + WebSocket) -
gateway-ws-proxy.ts(~400 lines). Sits between the browser and the OpenClaw gateway. Handles streaming, reconnection, message queueing, and multi-tab session sharing. - OpenClaw gateway (agent runtime) - your agent. Receives messages, processes them through the configured model, sends responses back token-by-token.
What you get out of the box
Six capabilities built into the three files, with no external dependencies beyond react-markdown:
- Floating chat bubble - persistent bubble on every page, resizable popup, unread badge with count.
- Full chat page - dedicated page with full history, auto-growing textarea, and message queueing.
- Markdown rendering - code blocks, headers, and lists render properly via
react-markdown. - File attachments - drag-drop, clipboard paste (Cmd+V), file picker. Images as base64.
- Auto-reconnect - exponential backoff (1s to 15s) with a message queue during reconnect.
- Shared session - the same conversation across browser, Telegram, and WhatsApp. One agent, many interfaces.
File breakdown
Each file has a single responsibility: the bubble handles UI, the proxy handles transport, the chat page handles layout.
ChatBubble.tsx (~280 lines) - floating chat bubble:
text
Key Features:
├── Persistent bottom-right position
├── Resizable popup (min 340x350, max 800x900)
├── Size persists in localStorage
├── Unread message badge with count
├── WebSocket connection to /ws/chat
├── Last 15 messages displayed
├── File attachments (paste, drag, picker)
└── "Open full" link to dedicated chat page
Message Flow:
connect() → ws.send({ type: "history", limit: 200 })
send() → ws.send({ type: "send", message, attachments })
receive → "sent" → "delta" (streaming) → "final"gateway-ws-proxy.ts (~400 lines) - browser to OpenClaw gateway:
text
GatewayConnection:
├── Reads config from ~/.openclaw/openclaw.json
├── Nonce-based authentication handshake
├── Persistent connection to gateway WS
├── Auto-reconnect with exponential backoff
├── Request/response tracking with timeouts
└── Event broadcasting to all browser clients
ChatProxy (per browser tab):
├── Accepts WS connection at /ws/chat
├── Forwards "send" → gateway.request("chat.send")
├── Streams "delta" events back to browser
├── Handles "history" → gateway.request("chat.history")
├── Multiple tabs share same gateway session
└── Connection drop = auto-reconnect, no data lossOpsChat.tsx (~450 lines) - full chat page:
text
Core Features:
├── Auto-growing textarea (max 200px)
├── Message queue (send while streaming)
├── Queue counter badge on send button
├── Stop button to abort current response
├── Smart auto-scroll (only if near bottom)
├── Drag-drop file upload with overlay
└── Welcome screen when no messagesThe master prompt
Paste this into your AI agent and it will build the entire chat interface. Customize the details to match your stack.
text
Build me a custom AI chat interface for my dashboard
with three components:
1. FLOATING CHAT BUBBLE (ChatBubble.tsx):
- Persistent floating bubble in bottom-right corner
- Follows user across all dashboard pages
- Resizable popup window on click
- Unread message badge with count
- Connects to shared WebSocket connection
2. FULL CHAT PAGE (OpsChat.tsx):
- Full-width chat with complete message history
- Markdown rendering via react-markdown
- File attachments via drag-drop AND clipboard paste
- Message queue: send while AI is streaming
- Smart auto-scroll (only scrolls if near bottom)
3. WEBSOCKET PROXY (gateway-ws-proxy.ts):
- Proxy between browser and AI gateway
- Token-by-token streaming
- Auto-reconnect with exponential backoff
- Message queue during reconnect
- Shared session across all interfaces
Tech: React, TypeScript, Vite, react-markdownWebSocket message protocol
The full protocol between browser and proxy. Ten message types cover the entire lifecycle.
Client to server (browser sends to proxy):
text
1. { type: "history", limit: 200 }
Load recent messages on connect
2. { type: "send", message: "...", attachments: [...] }
Send a new message (with optional files)
3. { type: "abort" }
Stop the current streaming responseServer to client (proxy sends to browser):
text
1. { type: "connected", gatewayConnected: true } Connection established
2. { type: "history", messages: [...] } Conversation history loaded
3. { type: "sent" } Streaming begins
4. { type: "delta", text: "..." } Partial token
5. { type: "final", message: {...} } Done
6. { type: "error", error: "..." } Error