chatnest 3.4.0 → 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/readme.md
CHANGED
|
@@ -1,306 +1,462 @@
|
|
|
1
1
|
# ChatNest
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://i.ibb.co.com/ts1T0q7/chatnest.jpg" alt="ChatNest" width="400">
|
|
5
|
+
</p>
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Table of Contents
|
|
8
|
-
- [Key Features](#key-features)
|
|
9
|
-
- [Installation](#installation)
|
|
10
|
-
- [Usage](#usage)
|
|
11
|
-
- [Configuration Options](#configuration-options)
|
|
12
|
-
- [Example Initialization with Full Configuration](#example-initialization-with-full-configuration)
|
|
13
|
-
- [Dependencies](#dependencies)
|
|
14
|
-
|
|
15
|
-
## Key Features
|
|
16
|
-
|
|
17
|
-
1. **Seamless Integration with LLMs using LangChain or RAG (Retrieval-Augmented Generation)**
|
|
18
|
-
- **LangChain Integration**: ChatNest is fully compatible with LangChain, allowing developers to harness the power of large language models (LLMs) directly within their chat interface. This enables dynamic and context-aware responses by structuring conversation history, improving response generation, and enabling multi-turn conversations.
|
|
19
|
-
- **RAG-Based Conversational AI**: With RAG, ChatNest offers access to real-time knowledge bases, document databases, and custom data sources, allowing users to retrieve and interact with up-to-date and accurate information. This setup is ideal for applications that require responses grounded in specific knowledge domains, like customer support, product information, or knowledge retrieval.
|
|
20
|
-
|
|
21
|
-
2. **Flexible Configuration System**
|
|
22
|
-
- Developers can control chatbot settings, such as default endpoints (e.g., `deleteEndpoint` for clearing history or `apiEndpoint` for main interactions), response types, themes, and interaction prompts.
|
|
23
|
-
- ChatNest supports custom API routes, allowing developers to set up and route requests to specific RAG or LangChain endpoints for highly optimized and tailored performance.
|
|
24
|
-
|
|
25
|
-
3. **Customizable UI**
|
|
26
|
-
- ChatNest is designed to blend seamlessly with your app’s visual style. You can adjust colors, fonts, and layout, enabling a fully branded chatbot experience.
|
|
27
|
-
- The widget is also mobile-responsive, ensuring optimal user experience across all devices.
|
|
28
|
-
|
|
29
|
-
## Use Cases
|
|
30
|
-
|
|
31
|
-
- **Customer Support**: ChatNest, combined with LangChain or RAG, can serve as a smart assistant capable of answering questions based on real-time data from your knowledge base.
|
|
32
|
-
- **Product Recommendations**: For e-commerce, ChatNest can pull from product databases, providing users with personalized recommendations and detailed product descriptions.
|
|
33
|
-
- **Knowledge Retrieval**: ChatNest can act as a virtual assistant in educational platforms, retrieving information from research papers, textbooks, or articles, enhancing learning experiences.
|
|
34
|
-
- **Internal Tools**: Enhance productivity by allowing team members to interact with internal databases or corporate knowledge resources through the chat interface.
|
|
7
|
+
A lightweight, customizable AI chat widget. Drop it into any website in minutes.
|
|
35
8
|
|
|
9
|
+
---
|
|
36
10
|
|
|
37
11
|
## Installation
|
|
38
12
|
|
|
39
|
-
|
|
40
|
-
|
|
13
|
+
**CDN**
|
|
41
14
|
```html
|
|
42
|
-
<script src="https://cdn.jsdelivr.net/npm/chatnest@3.4.
|
|
15
|
+
<script src="https://cdn.jsdelivr.net/npm/chatnest@3.4.2/dist/chatnest.min.js"></script>
|
|
43
16
|
```
|
|
44
17
|
|
|
45
|
-
|
|
46
|
-
|
|
18
|
+
**npm**
|
|
47
19
|
```bash
|
|
48
20
|
npm install chatnest
|
|
49
21
|
```
|
|
22
|
+
```js
|
|
23
|
+
import Chatnest from 'chatnest';
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
50
29
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
greeting: 'Hi there! How can I assist you today?',
|
|
60
|
-
apiEndpoint: 'https://your-api-endpoint.com/chat',
|
|
61
|
-
primaryColor: '#1a73e8',
|
|
62
|
-
width: '400px',
|
|
63
|
-
height: '600px'
|
|
30
|
+
```html
|
|
31
|
+
<script src="https://cdn.jsdelivr.net/npm/chatnest@3.4.2/dist/chatnest.min.js"></script>
|
|
32
|
+
<script>
|
|
33
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
34
|
+
new Chatnest({
|
|
35
|
+
botName: 'Support Bot',
|
|
36
|
+
apiEndpoint: 'https://your-api.com/chat',
|
|
37
|
+
primaryColor: '#0084ff'
|
|
64
38
|
});
|
|
65
|
-
});
|
|
39
|
+
});
|
|
40
|
+
</script>
|
|
66
41
|
```
|
|
67
42
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
|
92
|
-
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
|
109
|
-
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
118
|
-
| `showTypingText`
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
| `
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
|
126
|
-
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
|
135
|
-
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Configuration
|
|
46
|
+
|
|
47
|
+
### Core
|
|
48
|
+
|
|
49
|
+
| Option | Type | Default | Description |
|
|
50
|
+
|--------|------|---------|-------------|
|
|
51
|
+
| `botName` | `string` | `'Chat Assistant'` | Name shown in the header |
|
|
52
|
+
| `botImage` | `string` | default avatar | Bot avatar URL |
|
|
53
|
+
| `botSubname` | `string` | `null` | Sub-label below the bot name |
|
|
54
|
+
| `showBotSubname` | `boolean` | `true` | Show/hide `botSubname` |
|
|
55
|
+
| `greeting` | `string` | `'Hello! How can I help you today?'` | Opening message |
|
|
56
|
+
| `placeholder` | `string` | `'Type your message here...'` | Input placeholder text |
|
|
57
|
+
| `primaryColor` | `string` | `'#0084ff'` | Accent color — hex or CSS gradient |
|
|
58
|
+
| `fontSize` | `number\|string` | `14` | Message font size in px (14–25) |
|
|
59
|
+
| `width` | `string` | `'400px'` | Widget width (300–600px) |
|
|
60
|
+
| `height` | `string` | `'600px'` | Widget height (400–800px) |
|
|
61
|
+
| `position` | `string` | `'bottom-right'` | `bottom-right` `bottom-left` `bottom-center` `top-right` `top-left` |
|
|
62
|
+
| `theme` | `string` | `'light'` | `'light'` `'dark'` `'system'` |
|
|
63
|
+
|
|
64
|
+
### API
|
|
65
|
+
|
|
66
|
+
| Option | Type | Default | Description |
|
|
67
|
+
|--------|------|---------|-------------|
|
|
68
|
+
| `apiEndpoint` | `string` | `'http://localhost:7000/chat'` | Chat endpoint URL |
|
|
69
|
+
| `apiKey` | `string` | `''` | Bearer token added to `Authorization` header |
|
|
70
|
+
| `apiHeaders` | `object` | `{ 'Content-Type': 'application/json' }` | Extra request headers |
|
|
71
|
+
| `apiMethod` | `string` | `'POST'` | HTTP method |
|
|
72
|
+
| `apiTimeout` | `number` | `30000` | Request timeout in ms |
|
|
73
|
+
| `apiRequestFormat` | `object` | `{ query, userId, domain }` | Map request field names to what your API expects |
|
|
74
|
+
| `apiResponseFormat` | `object` | `{ response, products, productItem }` | Map response field names from your API |
|
|
75
|
+
| `apiDataFormat` | `string` | `'json'` | `'json'` or `'form-data'` |
|
|
76
|
+
| `useMultipartFormData` | `boolean` | `true` | Use multipart encoding for file uploads |
|
|
77
|
+
| `userId` | `string\|function\|null` | `null` | Override the `user_id` sent on every API call. Pass a static string, a function `(userManager) => string`, or `null` to use the auto-generated ID. If `nativeForm.useEmailAsUserId` is `true` the submitted email takes over automatically after form submission. |
|
|
78
|
+
| `transformResponse` | `function` | `null` | Transform the raw API response before display |
|
|
79
|
+
| `productInjectionMarker` | `string\|array` | see below | Text marker(s) after which the product carousel is inserted |
|
|
80
|
+
|
|
81
|
+
### Chat Behavior
|
|
82
|
+
|
|
83
|
+
| Option | Type | Default | Description |
|
|
84
|
+
|--------|------|---------|-------------|
|
|
85
|
+
| `enableHistory` | `boolean` | `true` | Persist chat in localStorage |
|
|
86
|
+
| `maxHistoryLength` | `number` | `100` | Max messages stored locally |
|
|
87
|
+
| `separateSubpageHistory` | `boolean` | `false` | Separate history per URL path |
|
|
88
|
+
| `enableMarkdown` | `boolean` | `true` | Render Markdown in bot replies |
|
|
89
|
+
| `enableTypewriter` | `boolean` | `true` | Typewriter animation for bot replies |
|
|
90
|
+
| `typewriterSpeed` | `object` | `{ min: 30, max: 70 }` | Typewriter speed range in ms per character |
|
|
91
|
+
| `typewritewithscroll` | `boolean` | `false` | Auto-scroll while typewriter is animating |
|
|
92
|
+
| `enableTypingIndicator` | `boolean` | `true` | Show "Thinking…" while waiting |
|
|
93
|
+
| `showTypingText` | `boolean` | `true` | Show text label next to typing dots |
|
|
94
|
+
| `typingIndicatorColor` | `string` | `'#666'` | Color of the typing dots |
|
|
95
|
+
| `showTimestamp` | `boolean` | `false` | Show time on each message |
|
|
96
|
+
| `chips` | `array` | `[]` | Suggestion chip buttons, e.g. `['Help', 'Pricing']` |
|
|
97
|
+
|
|
98
|
+
### File Upload
|
|
99
|
+
|
|
100
|
+
| Option | Type | Default | Description |
|
|
101
|
+
|--------|------|---------|-------------|
|
|
102
|
+
| `enableFileUpload` | `boolean` | `true` | Enable file / image attachments |
|
|
103
|
+
| `fileAccept` | `string` | `'image/*,.pdf,.doc,.docx,.txt'` | Accepted MIME types or extensions |
|
|
104
|
+
| `maxFiles` | `number` | `null` | Max files per message (`null` = unlimited) |
|
|
105
|
+
| `enableEnhancedMobileInput` | `boolean` | `true` | Optimised input handling on mobile |
|
|
106
|
+
|
|
107
|
+
### Backend History
|
|
108
|
+
|
|
109
|
+
| Option | Type | Default | Description |
|
|
110
|
+
|--------|------|---------|-------------|
|
|
111
|
+
| `enableBackendHistory` | `boolean` | `true` | Send conversation history to the API |
|
|
112
|
+
| `backendHistoryEndpoint` | `string` | `''` | Separate endpoint to fetch server-side history |
|
|
113
|
+
| `deleteEndpoint` | `string` | `{apiEndpoint}/delete-history` | Endpoint called when the user clears chat |
|
|
114
|
+
| `feedbackEndpoint` | `string` | `{apiEndpoint}/feedback` | Endpoint for like/dislike feedback |
|
|
115
|
+
| `enableServerHistoryDelete` | `boolean` | `false` | Call `deleteEndpoint` when erasing chat |
|
|
116
|
+
|
|
117
|
+
### UI & Branding
|
|
118
|
+
|
|
119
|
+
| Option | Type | Default | Description |
|
|
120
|
+
|--------|------|---------|-------------|
|
|
121
|
+
| `showBranding` | `boolean` | `true` | "Powered by" footer link |
|
|
122
|
+
| `brandingText` | `string` | `'Powered by NeuroBrain'` | Footer brand label |
|
|
123
|
+
| `brandingUrl` | `string` | `'https://neurobrains.co/'` | Footer brand URL |
|
|
124
|
+
| `showMessageActions` | `boolean` | `true` | Like / dislike / copy / regenerate buttons |
|
|
125
|
+
| `enableDeleteButton` | `boolean` | `true` | Show clear-chat button in header |
|
|
126
|
+
| `aiAvatar` | `string` | `null` | URL, emoji, or inline SVG for the AI avatar |
|
|
127
|
+
| `showAiAvatar` | `boolean` | `true` | Show/hide the AI avatar next to messages |
|
|
128
|
+
| `chatBackgroundColor` | `string` | `'#ffffff'` | Chat panel background color |
|
|
129
|
+
| `chatBackgroundImage` | `string` | `null` | CSS background-image for the chat panel |
|
|
130
|
+
| `sendButtonIconSize` | `number` | `24` | Send button icon size in px |
|
|
131
|
+
| `showPrivacyNotice` | `boolean` | `true` | Show a small privacy notice below the input |
|
|
132
|
+
| `privacyNoticeText` | `string` | `'Messages may be stored to improve responses.'` | Privacy notice copy |
|
|
133
|
+
|
|
134
|
+
### Toggle Button
|
|
135
|
+
|
|
136
|
+
| Option | Type | Default | Description |
|
|
137
|
+
|--------|------|---------|-------------|
|
|
138
|
+
| `toggleButtonIcon` | `string` | default chat icon | URL, emoji, or SVG for the toggle button |
|
|
139
|
+
| `toggleButtonSize` | `number` | `60` | Toggle button diameter in px (40–80) |
|
|
140
|
+
| `toggleButtonAnimation` | `number` | `4` | Animation style 0–5 (`0` = none) |
|
|
141
|
+
| `toggleButtonBottomMargin` | `number` | `50` | Distance from the bottom of the viewport in px |
|
|
142
|
+
| `toggleButtonRightMargin` | `number` | `30` | Distance from the right edge of the viewport in px |
|
|
143
|
+
| `websiteBottomSpacing` | `number` | `0` | Extra bottom spacing to avoid overlapping site elements |
|
|
144
|
+
|
|
145
|
+
### Text Box Pop-up
|
|
146
|
+
|
|
147
|
+
The small speech-bubble pop-up that appears above the toggle button before the chat is opened.
|
|
148
|
+
|
|
149
|
+
| Option | Type | Default | Description |
|
|
150
|
+
|--------|------|---------|-------------|
|
|
151
|
+
| `showTextBox` | `boolean` | `true` | Show the pop-up text box |
|
|
152
|
+
| `textBoxMessage` | `string` | `'Hi there! If you need any assistance, I am always here.'` | Main message |
|
|
153
|
+
| `textBoxSubMessage` | `string` | `'24/7 Live Chat Support'` | Sub-message |
|
|
154
|
+
| `showTextBoxCloseButton` | `boolean` | `true` | Allow user to dismiss the pop-up |
|
|
155
|
+
| `textBoxTextColor` | `string` | `'primary'` | `'primary'` (uses `primaryColor`), `'default'`, or any hex |
|
|
156
|
+
| `textBoxSpacingFromToggle` | `number` | `0` | Gap between the pop-up and toggle button in px |
|
|
157
|
+
|
|
158
|
+
### Native Lead Form
|
|
159
|
+
|
|
160
|
+
A fully built-in, no-dependency lead-capture form. Fields, labels, and validation are all customisable. Data is saved to `localStorage` and, optionally, the submitted email is used as the API `user_id` from that point on.
|
|
161
|
+
|
|
162
|
+
| Option | Type | Default | Description |
|
|
163
|
+
|--------|------|---------|-------------|
|
|
164
|
+
| `nativeForm.enabled` | `boolean` | `false` | Enable the native form |
|
|
165
|
+
| `nativeForm.trigger` | `string` | `'onOpen'` | When to show — `'onOpen'` (chat opens) or `'onFirstMessage'` (first send attempt) |
|
|
166
|
+
| `nativeForm.title` | `string` | `'Before we start'` | Modal heading |
|
|
167
|
+
| `nativeForm.subtitle` | `string` | `'Tell us a little about yourself.'` | Modal sub-heading |
|
|
168
|
+
| `nativeForm.submitLabel` | `string` | `'Start chatting'` | Submit button label |
|
|
169
|
+
| `nativeForm.useEmailAsUserId` | `boolean` | `true` | After submission, set the email field value as the persistent API `user_id` |
|
|
170
|
+
| `nativeForm.storageKey` | `string\|null` | `null` | localStorage key prefix. `null` → auto (`cnf_<hostname>`) |
|
|
171
|
+
| `nativeForm.fields` | `array` | name + email + phone | Array of field descriptors — see table below |
|
|
172
|
+
| `nativeForm.onSubmit` | `async function\|null` | `null` | Optional async callback `(formData) => void\|false`. Return `false` to block submission. |
|
|
173
|
+
|
|
174
|
+
**Field descriptor shape**
|
|
175
|
+
|
|
176
|
+
| Key | Type | Required | Description |
|
|
177
|
+
|-----|------|----------|-------------|
|
|
178
|
+
| `name` | `string` | yes | Field key, also used as the `localStorage` data property |
|
|
179
|
+
| `label` | `string` | yes | Label shown above the input |
|
|
180
|
+
| `type` | `string` | no | HTML input type — `'text'` `'email'` `'tel'` `'number'` etc. Default `'text'` |
|
|
181
|
+
| `required` | `boolean` | no | Mark field as required. Default `false` |
|
|
182
|
+
| `placeholder` | `string` | no | Input placeholder text |
|
|
183
|
+
| `validate` | `function` | no | Custom validator `(value: string) => errorMessage \| ''`. Overrides built-in type checks. |
|
|
184
|
+
|
|
185
|
+
**localStorage keys written on submit**
|
|
186
|
+
|
|
187
|
+
| Key | Value |
|
|
188
|
+
|-----|-------|
|
|
189
|
+
| `cnf_<hostname>_submitted` | `"true"` |
|
|
190
|
+
| `cnf_<hostname>_data` | JSON — all field values + `submittedAt` ISO timestamp |
|
|
191
|
+
|
|
192
|
+
### HubSpot Lead Form
|
|
193
|
+
|
|
194
|
+
Displays a lead-capture form before or during chat. Requires HubSpot portal credentials.
|
|
195
|
+
|
|
196
|
+
| Option | Type | Default | Description |
|
|
197
|
+
|--------|------|---------|-------------|
|
|
198
|
+
| `hubspot.enabled` | `boolean` | `false` | Enable HubSpot form integration |
|
|
199
|
+
| `hubspot.portalId` | `string` | `''` | HubSpot portal ID |
|
|
200
|
+
| `hubspot.formGuid` | `string` | `''` | HubSpot form GUID |
|
|
201
|
+
| `hubspot.triggerKeywords` | `array` | `['pricing','demo','contact','quote','help','support']` | Keywords that trigger the form |
|
|
202
|
+
| `showFormOnStart` | `boolean` | `true` | Show form when chat opens for new users |
|
|
203
|
+
| `useEmailAsUserId` | `boolean` | `true` | Use submitted email as the persistent user ID (HubSpot form only) |
|
|
204
|
+
| `formTitle` | `string` | `'Give Your Details'` | Form modal title |
|
|
205
|
+
| `formSubtitle` | `string` | `'Please provide your information to start chatting.'` | Form modal subtitle |
|
|
206
|
+
|
|
207
|
+
### Supabase Chat History
|
|
208
|
+
|
|
209
|
+
Persist chat history in Supabase so sessions survive across devices and browsers.
|
|
210
|
+
|
|
211
|
+
| Option | Type | Default | Description |
|
|
212
|
+
|--------|------|---------|-------------|
|
|
213
|
+
| `supabase.enabled` | `boolean` | `false` | Enable Supabase persistence |
|
|
214
|
+
| `supabase.url` | `string` | `''` | Supabase project URL |
|
|
215
|
+
| `supabase.anonKey` | `string` | `''` | Supabase anon/public API key |
|
|
216
|
+
| `supabase.tableName` | `string` | `'chat_history'` | Table to store messages |
|
|
217
|
+
| `supabase.historyLimit` | `number` | `50` | Max rows to load on widget open |
|
|
218
|
+
| `supabase.pollIntervalMs` | `number` | `5000` | Background refresh interval (ms); Realtime gives instant delivery |
|
|
219
|
+
|
|
220
|
+
### Parlant Integration
|
|
221
|
+
|
|
222
|
+
| Option | Type | Default | Description |
|
|
223
|
+
|--------|------|---------|-------------|
|
|
224
|
+
| `parlant.enabled` | `boolean` | `false` | Enable Parlant agent integration |
|
|
225
|
+
| `parlant.apiBaseUrl` | `string` | `''` | Parlant API base URL |
|
|
226
|
+
|
|
227
|
+
### Callbacks
|
|
228
|
+
|
|
229
|
+
| Option | Type | Description |
|
|
230
|
+
|--------|------|-------------|
|
|
231
|
+
| `onInit` | `function` | Called when the widget is ready |
|
|
232
|
+
| `onMessage` | `function` | Called on every message send / receive |
|
|
233
|
+
| `onError` | `function` | Called on API errors |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Native Lead Form
|
|
238
|
+
|
|
239
|
+
Capture user details before or during chat — no HubSpot account needed. All data stays in the user's browser.
|
|
240
|
+
|
|
241
|
+
### Minimal setup
|
|
242
|
+
|
|
243
|
+
```js
|
|
244
|
+
new Chatnest({
|
|
245
|
+
apiEndpoint: 'https://your-api.com/chat',
|
|
246
|
+
nativeForm: {
|
|
247
|
+
enabled: true
|
|
248
|
+
}
|
|
197
249
|
});
|
|
250
|
+
```
|
|
198
251
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
252
|
+
Shows a name + email + phone form when the chat opens. After submission the email becomes the persistent `user_id` on every API request.
|
|
253
|
+
|
|
254
|
+
### Custom fields
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
new Chatnest({
|
|
258
|
+
apiEndpoint: 'https://your-api.com/chat',
|
|
259
|
+
nativeForm: {
|
|
260
|
+
enabled: true,
|
|
261
|
+
trigger: 'onFirstMessage', // intercept first send attempt
|
|
262
|
+
title: 'Quick intro',
|
|
263
|
+
subtitle: 'We use this to personalise your experience.',
|
|
264
|
+
submitLabel: 'Let\'s go',
|
|
265
|
+
fields: [
|
|
266
|
+
{ name: 'fullname', label: 'Your name', type: 'text', required: true },
|
|
267
|
+
{ name: 'email', label: 'Work email', type: 'email', required: true },
|
|
268
|
+
{ name: 'company', label: 'Company', type: 'text', required: false,
|
|
269
|
+
validate: (v) => v.length >= 2 ? '' : 'Enter your company name.' }
|
|
270
|
+
]
|
|
271
|
+
}
|
|
206
272
|
});
|
|
273
|
+
```
|
|
207
274
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
275
|
+
### Custom submit hook
|
|
276
|
+
|
|
277
|
+
```js
|
|
278
|
+
new Chatnest({
|
|
279
|
+
nativeForm: {
|
|
280
|
+
enabled: true,
|
|
281
|
+
onSubmit: async (formData) => {
|
|
282
|
+
// formData = { fullname, email, company, submittedAt }
|
|
283
|
+
const res = await fetch('/api/leads', {
|
|
284
|
+
method: 'POST',
|
|
285
|
+
headers: { 'Content-Type': 'application/json' },
|
|
286
|
+
body: JSON.stringify(formData)
|
|
287
|
+
});
|
|
288
|
+
if (!res.ok) return false; // returning false shows an error and keeps the form open
|
|
289
|
+
}
|
|
290
|
+
}
|
|
216
291
|
});
|
|
217
292
|
```
|
|
218
293
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
294
|
+
### Reading stored data in your own code
|
|
295
|
+
|
|
296
|
+
```js
|
|
297
|
+
// Check if the user already submitted
|
|
298
|
+
const submitted = localStorage.getItem('cnf_yourdomain.com_submitted') === 'true';
|
|
299
|
+
|
|
300
|
+
// Read field values
|
|
301
|
+
const data = JSON.parse(localStorage.getItem('cnf_yourdomain.com_data') || 'null');
|
|
302
|
+
// { fullname: 'Jane Doe', email: 'jane@co.com', submittedAt: '2025-04-03T...' }
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## User ID Control
|
|
308
|
+
|
|
309
|
+
By default ChatNest auto-generates a random `user_id` per browser and persists it in `localStorage`. You can override this at any level of precision:
|
|
310
|
+
|
|
311
|
+
```js
|
|
312
|
+
// 1. Static — same ID for every visitor (useful for authenticated apps)
|
|
313
|
+
new Chatnest({ userId: 'user_42' });
|
|
314
|
+
|
|
315
|
+
// 2. Dynamic — evaluated on every API request
|
|
316
|
+
new Chatnest({
|
|
317
|
+
userId: (userManager) => {
|
|
318
|
+
// userManager.currentUser is the auto-generated or email-derived ID
|
|
319
|
+
return window.__myApp?.loggedInUserId || userManager.currentUser;
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// 3. Email from nativeForm — no extra config needed
|
|
324
|
+
// When nativeForm.useEmailAsUserId is true (the default),
|
|
325
|
+
// the email the user submits automatically becomes userManager.currentUser
|
|
326
|
+
// and is used on all subsequent requests.
|
|
327
|
+
new Chatnest({
|
|
328
|
+
nativeForm: { enabled: true, useEmailAsUserId: true }
|
|
248
329
|
});
|
|
249
330
|
```
|
|
250
331
|
|
|
251
|
-
|
|
332
|
+
**Resolution order on each API call:**
|
|
333
|
+
1. `config.userId` (string or function), if set
|
|
334
|
+
2. `userManager.currentUser` — which is the submitted email after `nativeForm` or `hubspot` form submission (when `useEmailAsUserId: true`)
|
|
335
|
+
3. Auto-generated `user_<domain><timestamp>_<random>` persisted in `localStorage`
|
|
252
336
|
|
|
253
|
-
|
|
337
|
+
---
|
|
254
338
|
|
|
255
|
-
##
|
|
339
|
+
## Supabase Setup
|
|
256
340
|
|
|
257
|
-
|
|
341
|
+
### 1. Create the table
|
|
258
342
|
|
|
259
|
-
|
|
343
|
+
```sql
|
|
344
|
+
CREATE TABLE IF NOT EXISTS chat_history (
|
|
345
|
+
id BIGSERIAL PRIMARY KEY,
|
|
346
|
+
user_id TEXT NOT NULL,
|
|
347
|
+
domain TEXT NOT NULL,
|
|
348
|
+
query TEXT NOT NULL,
|
|
349
|
+
response TEXT NOT NULL,
|
|
350
|
+
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
351
|
+
);
|
|
260
352
|
|
|
261
|
-
|
|
262
|
-
|
|
353
|
+
CREATE INDEX IF NOT EXISTS idx_chat_history_user_domain ON chat_history (user_id, domain);
|
|
354
|
+
CREATE INDEX IF NOT EXISTS idx_chat_history_timestamp ON chat_history (timestamp DESC);
|
|
263
355
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
3. Check your `apiRequestFormat` mapping matches your API expectations
|
|
356
|
+
ALTER TABLE chat_history ENABLE ROW LEVEL SECURITY;
|
|
357
|
+
CREATE POLICY "chat_history_open" ON chat_history FOR ALL USING (true) WITH CHECK (true);
|
|
267
358
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
3. Set `apiDataFormat: 'form-data'`
|
|
272
|
-
4. Check file size limits on your server
|
|
359
|
+
-- Enable Realtime for instant Messenger-like delivery (optional but recommended)
|
|
360
|
+
ALTER PUBLICATION supabase_realtime ADD TABLE chat_history;
|
|
361
|
+
```
|
|
273
362
|
|
|
274
|
-
###
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
363
|
+
### 2. Configure
|
|
364
|
+
|
|
365
|
+
```js
|
|
366
|
+
new Chatnest({
|
|
367
|
+
apiEndpoint: 'https://your-api.com/chat',
|
|
368
|
+
supabase: {
|
|
369
|
+
enabled: true,
|
|
370
|
+
url: 'https://xxxxxxxxxxxx.supabase.co',
|
|
371
|
+
anonKey: 'your-anon-key',
|
|
372
|
+
tableName: 'chat_history', // optional
|
|
373
|
+
historyLimit: 50 // optional
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
```
|
|
279
377
|
|
|
280
|
-
|
|
378
|
+
> Find `url` and `anonKey` in **Supabase → Project Settings → API**.
|
|
281
379
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
380
|
+
**Real-time sync** — The widget polls for new rows every 3 seconds. When a human agent or backend adds a reply to `chat_history`, it appears live, like Messenger. Tune with `supabase.pollIntervalMs`.
|
|
381
|
+
|
|
382
|
+
**Multi-part responses (`,,,`)** — If your API returns multiple replies concatenated with three commas, ChatNest splits them into separate messages:
|
|
383
|
+
`"Hello!,,,How can I help?"` → two bot messages.
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Product Carousel
|
|
388
|
+
|
|
389
|
+
When your API returns a `products` array, ChatNest renders product cards with image, name, price, highlights, and a CTA button.
|
|
390
|
+
|
|
391
|
+
```js
|
|
392
|
+
new Chatnest({
|
|
393
|
+
apiEndpoint: 'https://your-api.com/chat',
|
|
394
|
+
productInjectionMarker: 'Here are some recommendations:',
|
|
395
|
+
apiResponseFormat: {
|
|
396
|
+
response: 'response',
|
|
397
|
+
products: 'products',
|
|
398
|
+
productItem: {
|
|
399
|
+
name: 'name',
|
|
400
|
+
price: 'price',
|
|
401
|
+
image: 'image_url',
|
|
402
|
+
link: 'buy_link',
|
|
403
|
+
highlights: 'highlights',
|
|
404
|
+
ctaText: 'Buy now'
|
|
291
405
|
}
|
|
292
|
-
}
|
|
406
|
+
}
|
|
407
|
+
});
|
|
293
408
|
```
|
|
294
409
|
|
|
295
|
-
|
|
296
|
-
```
|
|
410
|
+
Expected API response shape:
|
|
411
|
+
```json
|
|
297
412
|
{
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
userId: 'user_id',
|
|
303
|
-
domain: 'domain'
|
|
304
|
-
}
|
|
413
|
+
"response": "Here are some recommendations:\n\n",
|
|
414
|
+
"products": [
|
|
415
|
+
{ "name": "Product A", "price": "$29", "image_url": "...", "buy_link": "...", "highlights": "Lightweight" }
|
|
416
|
+
]
|
|
305
417
|
}
|
|
306
418
|
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## File Upload
|
|
423
|
+
|
|
424
|
+
```js
|
|
425
|
+
new Chatnest({
|
|
426
|
+
apiEndpoint: 'https://your-api.com/chat',
|
|
427
|
+
enableFileUpload: true,
|
|
428
|
+
useMultipartFormData: true,
|
|
429
|
+
apiDataFormat: 'form-data',
|
|
430
|
+
fileAccept: 'image/*',
|
|
431
|
+
maxFiles: 1
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
Single file → sent as `image` field. Multiple files → `file_0`, `file_1`, etc.
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Troubleshooting
|
|
440
|
+
|
|
441
|
+
**Widget not loading**
|
|
442
|
+
Wrap init in `DOMContentLoaded`. Load the script before your init code.
|
|
443
|
+
|
|
444
|
+
**422 error from API**
|
|
445
|
+
Your API expects different field names:
|
|
446
|
+
```js
|
|
447
|
+
apiRequestFormat: { query: 'message', userId: 'user_id', domain: 'domain' }
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**Products not showing**
|
|
451
|
+
Ensure your API returns a `products` array and `productInjectionMarker` matches text in the `response` field.
|
|
452
|
+
|
|
453
|
+
**Supabase history not loading**
|
|
454
|
+
- Confirm `supabase.enabled: true` and credentials are correct
|
|
455
|
+
- Check RLS policies allow reads with the anon key
|
|
456
|
+
- Check browser console for `[Supabase]` error messages
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## License
|
|
461
|
+
|
|
462
|
+
MIT © [Sifat Hasan](https://github.com/Pro-Sifat-Hasan)
|