A professional, ultra-lightweight (~12KB), API-agnostic chat UI widget built with pure Vanilla JavaScript. Zero framework lock-in (no React/Vue/jQuery), zero external dependencies, and built-in JSONP support for seamless cross-domain integration.
ChatUI provides the interactive power of a modern conversational UI without the performance overhead or technical complexity of framework-bound libraries. It is designed to be "live in 30 seconds" while remaining extensible enough for complex enterprise requirements.
- SMBs: Professional chat with zero dev overhead.
- Enterprise Legacy Systems: Modern interactivity without framework migrations.
- SaaS Platforms: A lean, white-label frontend for proprietary backends.
- Ultra-Lightweight: ~12KB core footprint, minimal impact on host performance.
- Interactive Widget System: Support for 15+ specialized UI components (Rating, Date Picker, File Upload, etc.).
- Zero Dependencies: Pure vanilla JS, works with any stack.
- Cross-Domain Ready: Native JSONP support bypasses CORS headaches.
- Real-Time WebSocket Support: Live typing indicators, read receipts, and streaming responses.
- Protocol-Based Transport: Automatically uses WebSocket (ws/wss) or JSONP (http/https) based on server URL.
- Dual Modes: Supports both
popupandfullpageembedded modes. - Modular Architecture: Built with modern ES6 classes and a dedicated
WidgetFactory. - Accessible & Secure: ARIA-compliant focus management and robust XSS prevention.
Add the script tag to your HTML. The widget will automatically initialize based on the data attributes.
JSONP Mode (HTTP/HTTPS):
<script
id="chat-widget"
src="path/to/chat-widget.js"
data-server-url="http://your-server.com"
data-position="bottom-right"
data-color="#007bff"
data-title="Chat with us">
</script>WebSocket Mode (WS/WSS):
<script
id="chat-widget"
src="path/to/chat-widget.js"
data-server-url="wss://your-server.com/ws"
data-position="bottom-right"
data-color="#007bff"
data-title="Chat with us">
</script>You can initialize and control the widget manually using the global ChatUI object.
// Initialize the widget
const chat = ChatUI.init({
id: 'custom-chat',
title: 'Support Chat',
color: '#28a745',
position: 'bottom-left',
serverUrl: 'http://localhost:3000'
});
// Control the widget
chat.open();
chat.close();
chat.toggle();
chat.sendMessage('Hello from the API!');| Attribute | JS Option | Description | Default |
|---|---|---|---|
data-server-url |
serverUrl |
Base URL of the chat backend API | http://localhost:3000 |
data-display |
displayMode |
Display mode: popup or fullpage |
popup |
data-mode |
themeMode |
Theme mode: light or dark |
light |
data-position |
position |
Corner position: bottom-right, bottom-left, top-right, top-left |
bottom-right |
data-color |
primaryColor |
Primary theme color (Hex code) | #007bff |
data-title |
title |
Title text displayed in the header | Chat with us |
data-target |
targetSelector |
Selector for container element (fullpage mode only) | null |
The widget uses strictly ID-rooted CSS selectors to prevent affecting your site's styles. You can easily theme it by targeting its classes in your own CSS:
/* Override the widget header color */
#chat-widget .header {
background-color: #333;
color: #fff;
}
/* Adjust message bubble styles */
#chat-widget .message {
font-size: 16px;
}The widget supports two transport protocols based on the server URL scheme:
The widget expects a backend that supports the following endpoints (compatible with JSONP):
GET /api/handshake?callback=cb
Response: { status: "success", session_key: "..." }
GET /api/messages?callback=cb&message=...&session_key=...
Response: { text: "Response message", sender: "bot" }
For real-time features, use a WebSocket endpoint. The widget will automatically detect the protocol and establish a WebSocket connection.
The widget sends and receives JSON messages with the following structure:
Client → Server:
{
"type": "handshake|connect|message|typing|read_receipt",
"payload": { ... },
"session_key": "...",
"timestamp": 1234567890
}Server → Client:
{
"type": "handshake|message|message:stream|typing|read_receipt",
"text": "...",
"widget": { ... },
"payload": { ... },
"session_key": "...",
"timestamp": 1234567890
}- Typing Indicators: Send
{ type: "typing", payload: { typing: true } }to show/hide typing indicators - Read Receipts: Send
{ type: "read_receipt", payload: { message_id: "..." } }to confirm message reads - Streaming Responses: Send
{ type: "message:stream", text: "partial..." }for character-by-character AI responses - Custom Events: Listen for
chatwidget:typingandchatwidget:read_receiptevents on the window object
To build the distribution file (dist/chat-widget.js):
npm run buildRun the Playwright end-to-end tests:
npm testTo see the widget in action with a live backend:
- Start the demo API server:
npm run start:demo
- Open
demo/demo.htmlin your browser.
src/modules/: Individual source modules (API, UI, Utils, Class)src/entry.js: Entry point for the bundlersrc/chat-widget.js: Bundle used for local tests/demosdist/chat-widget.js: Final distribution bundledist/chat-widget.min.js: Minified distribution bundletests/: Playwright test suites
- JSONP Security: Callback validation to prevent XSS.
- Scoped Reset: Internal CSS reset prevents host styles from breaking the UI.
- Message Sanitization: Proper handling of user-generated content.