https://github.com/merteraslan/chat-widget
A modern, lightweight React chat widget that connects seamlessly to your AI backend via webhooks with support for rich interactive messages, forms, articles, and canned responses.
https://github.com/merteraslan/chat-widget
ai automation chat chatbot chatwoot customer-support javascript low-code n8n npm react typescript webhook widget zapier
Last synced: about 2 months ago
JSON representation
A modern, lightweight React chat widget that connects seamlessly to your AI backend via webhooks with support for rich interactive messages, forms, articles, and canned responses.
- Host: GitHub
- URL: https://github.com/merteraslan/chat-widget
- Owner: merteraslan
- License: mit
- Created: 2025-07-23T00:18:11.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2025-08-08T03:22:30.000Z (about 2 months ago)
- Last Synced: 2025-08-08T05:26:53.034Z (about 2 months ago)
- Topics: ai, automation, chat, chatbot, chatwoot, customer-support, javascript, low-code, n8n, npm, react, typescript, webhook, widget, zapier
- Language: TypeScript
- Homepage:
- Size: 215 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# @merteraslan/chat-widget
## Why this widget
Build customer conversations without getting trapped by third-party chat platforms. This React component connects directly to your own backend, giving you complete control over data, styling, and functionality. You keep ownership of every conversation while getting a production-ready chat interface in minutes.
## Install
```bash
npm i @merteraslan/chat-widget
# or
yarn add @merteraslan/chat-widget
```## How requests are shaped
When users send messages, the widget transmits a JSON payload to your configured endpoint:
```json
{
"prompt": "What are your business hours?",
"session_id": "visitor-456"
}
```Your server responds with either plain text wrapped in an `output` field, or structured content for interactive features. CSRF protection headers are automatically included when you provide a token.
## Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `color` | `string` | ❌ | Accent color applied throughout the interface using hex notation. |
| `agentName` | `string` | ❌ | Display name that appears alongside bot responses. |
| `webhookUrl` | `string` | ✅ | The HTTP endpoint your backend exposes. The widget POSTs a JSON payload with the user's text and the sessionId. You own the endpoint; return a plain string in the field you configure (default: output). |
| `openByDefault` | `boolean` | ❌ | Controls initial widget visibility when the page loads. Default: `false`. |
| `placeholder` | `string` | ❌ | Hint text displayed inside the message input field. Default: `"Share your thoughts..."`. |
| `csrfToken` | `string` | ❌ | Security token transmitted via `X-CSRF-Token` header with each request. |
| `title` | `React.ReactNode` | ❌ | Content rendered in the chat window header area. Default: `"Assistant"`. |
| `sessionId` | `string` | ❌ | Unique identifier forwarded to your backend for conversation tracking. |
| `initialMessage` | `string` | ❌ | Opening message from the bot when chat first appears. Default: `"Hi there! What can I do for you?"`. |
| `className` | `string` | ❌ | Custom CSS class applied to the root widget element. |## Quick Start
```tsx
import { ChatWidget } from '@merteraslan/chat-widget';
import '@merteraslan/chat-widget/dist/style.css';export default function App() {
return (
);
}
```## Response Formats
### Simple Text Response
```json
{
"output": "Our store opens at 9 AM Monday through Friday!"
}
```### Interactive Content Response
```json
{
"content": "Pick a category:",
"content_type": "canned_response",
"content_attributes": {
"responses": {
"responses": [
{ "id": "orders", "text": "Order status" },
{ "id": "returns", "text": "Returns & refunds" }
]
}
}
}
```## Interactive Messages
Beyond basic text exchanges, the widget renders rich interactive elements that enhance user engagement. Your backend can send structured responses that become clickable buttons, forms, article links, and product showcases.
### Canned Responses / Quick Replies
```json
{
"content": "Which department can help you?",
"content_type": "canned_response",
"content_attributes": {
"responses": {
"responses": [
{ "id": "tech", "text": "Technical Issues" },
{ "id": "sales", "text": "Sales Inquiry" }
]
}
}
}
```### Article Links
```json
{
"content": "Browse these helpful guides:",
"content_type": "article",
"content_attributes": {
"items": [
{
"title": "Getting Started Guide",
"description": "Step-by-step setup instructions",
"link": "https://help.example.com/setup"
}
]
}
}
```### Interactive Forms
```json
{
"content": "Complete this information request:",
"content_type": "form",
"content_attributes": {
"form": {
"title": "Support Ticket",
"fields": [
{
"id": "issue",
"type": "text",
"label": "Describe the problem",
"required": true
},
{
"id": "priority",
"type": "select",
"label": "Urgency level",
"required": false
}
]
}
}
}
```### Product/Service Cards
```json
{
"content": "Explore these solutions:",
"content_type": "card",
"content_attributes": {
"cards": {
"cards": [
{
"title": "Enterprise Package",
"description": "Full-featured solution for large teams",
"image": "https://cdn.example.com/enterprise.png",
"price": "$99/month",
"badge": "RECOMMENDED",
"link": "https://example.com/enterprise",
"linkText": "Learn More"
}
]
}
}
}
```## Styling
The component includes self-contained CSS with scoped class names to avoid conflicts. Customize the appearance by targeting specific selectors with higher specificity or by wrapping the widget in a container with custom CSS.
For complete design control, the source code is intentionally compact and readable — perfect for forking and modifying to match your exact requirements.
## Development
```bash
npm install
npm run dev
```### CDN usage (no build tools)
Option A: Native ESM with an import map
```html
{
"imports": {
"react": "https://esm.sh/react@18",
"react-dom": "https://esm.sh/react-dom@18",
"react-dom/client": "https://esm.sh/react-dom@18/client",
"react/jsx-runtime": "https://esm.sh/react@18/jsx-runtime"
}
}import * as ReactDOMClient from 'react-dom/client';
// Provide ReactDOM global for the widget's mount helper
window.ReactDOM = ReactDOMClient;import { mountChatWidget } from 'https://unpkg.com/@merteraslan/chat-widget@latest/dist/chat-widget.es.js';
mountChatWidget(document.body, { webhookUrl: '/api/chat' });```
Option B: UMD + globals
```html
const { mountChatWidget } = window.ChatWidget;
mountChatWidget(document.body, { webhookUrl: '/api/chat' });```
More examples in `examples/`.
## License
MIT - see [LICENSE](LICENSE) file for details.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.