rushchatbot
v1.7.6
Published
**Version:** 1.7.6
Readme
RushChatbot
Version: 1.7.6
Embeddable hybrid chatbot plugin that combines a click-based FAQ tree with a free-text query engine backed by n8n. Ships as an npm package with a Node.js/Express server and widgets for React, Vue 3, and Vanilla JS.
Features:
- Click-based FAQ question tree with subquestions
- Fuzzy + keyword matching against your config
- n8n webhook fallback for unmatched queries
- Markdown rendering (bold, lists, headings)
- Multi-bubble paragraph responses
- Draggable floating chat button
- Tagalog (TL) language support
- Input validation and profanity guardrails
- Session-based analytics
Table of Contents
- Requirements
- Installation
- Scaffold Config Files
- Configure the Chatbot
- Build the FAQ Tree
- Start the Server
- Embed the Widget
- Floating Button Behavior
- n8n Webhook Setup
- n8n Response Formats
- Environment Variables
- API Reference
- Analytics
- Troubleshooting
1. Requirements
| Requirement | Version | |---|---| | Node.js | >= 18.0.0 | | npm | >= 9.0.0 | | React (for React widget) | >= 18.0.0 | | Vue (for Vue 3 widget) | >= 3.0.0 | | Vue (for Vue 2 widget) | >= 2.5.17 | | n8n instance | Any hosted or self-hosted |
2. Installation
npm install rushchatbot3. Scaffold Config Files
Run the init command to generate the required config and questions files in a directory of your choice:
npx rushchatbot init ./chatbotThis creates three files:
chatbot/
├── chatbot.config.json ← branding, n8n, chat settings
├── questions.json ← English FAQ tree
└── questions.tl.json ← Tagalog FAQ tree (optional)4. Configure the Chatbot
Edit chatbot.config.json with your settings:
{
"branding": {
"title": "My Support Bot",
"subtitle": "How can we help you today?",
"theme": {
"primaryColor": "#4F46E5",
"backgroundColor": "#FFFFFF",
"userBubbleColor": "#4F46E5",
"botBubbleColor": "#F3F4F6",
"textColor": "#111827",
"fontFamily": "Inter, sans-serif"
}
},
"n8n": {
"webhookUrl": "https://your-n8n.com/webhook/your-webhook-id",
"timeoutMs": 55000
},
"chat": {
"welcomeMessage": "Hi! Choose a question below or type your own.",
"fallbackMessage": "Let me look that up for you...",
"matchThreshold": 0.4,
"showPreQuestionsOnStart": true,
"language": "en",
"window": {
"width": 360,
"height": null
}
}
}Config field reference
| Field | Type | Default | Description |
|---|---|---|---|
| branding.title | string | — | Chat header title |
| branding.subtitle | string | — | Chat header subtitle |
| branding.theme.primaryColor | string | #4F46E5 | Header, buttons, user bubble color |
| branding.theme.backgroundColor | string | #FFFFFF | Chat window background |
| branding.theme.userBubbleColor | string | #4F46E5 | User message bubble color |
| branding.theme.botBubbleColor | string | #F3F4F6 | Bot message bubble color |
| branding.theme.textColor | string | #111827 | Main text color |
| branding.theme.fontFamily | string | Inter, sans-serif | Font stack |
| n8n.webhookUrl | string | — | Your n8n POST webhook URL |
| n8n.timeoutMs | number | 55000 | n8n request timeout in milliseconds |
| chat.welcomeMessage | string | — | First message shown when chat opens |
| chat.fallbackMessage | string | — | Shown when an error occurs |
| chat.matchThreshold | number | 0.4 | Fuzzy match sensitivity (0–1). Lower = stricter |
| chat.showPreQuestionsOnStart | boolean | true | Show FAQ buttons when chat opens |
| chat.language | "en" | "tl" | "en" | Language for displaying FAQ questions |
| chat.window.width | number | 360 | Desktop chat window width in pixels. Omit or set null to use responsive default (min(360, vw-48)) |
| chat.window.height | number | null | Desktop chat window height in pixels. Omit or set null to use responsive default (70vh) |
6. Build the FAQ Tree
Edit questions.json to define your FAQ categories and answers. The structure supports two levels: main questions and subquestions.
[
{
"id": "q1",
"question": "About Our Company",
"answer": "We are a company that...",
"subquestions": [
{
"id": "q1a",
"question": "When was the company founded?",
"answer": "We were founded in 2010.",
"subquestions": []
},
{
"id": "q1b",
"question": "What is your mission?",
"answer": "Our mission is to...",
"subquestions": []
}
]
},
{
"id": "q2",
"question": "Contact Information",
"answer": "You can reach us at [email protected].",
"subquestions": []
}
]Rules
- Every question must have a unique
id subquestionsmust be an array (use[]if none)answeris shown when the question is clicked directly or matched via text search- For Tagalog support, mirror the same structure in
questions.tl.jsonwith translated text — keep the sameidvalues
6. Start the Server
Create a server entry file (e.g. server.js or server.ts):
import { createServer } from 'rushchatbot/server'
import path from 'path'
createServer({
configPath: path.resolve('./chatbot/chatbot.config.json'),
questionsPath: path.resolve('./chatbot/questions.json'),
questionsTagalogPath: path.resolve('./chatbot/questions.tl.json'), // optional
port: 3001,
corsOrigin: 'https://your-frontend-domain.com', // or '*' for development
}).listen()Server options
| Option | Type | Default | Description |
|---|---|---|---|
| configPath | string | — | Required. Absolute path to chatbot.config.json |
| questionsPath | string | — | Required. Absolute path to questions.json |
| questionsTagalogPath | string | — | Optional. Absolute path to questions.tl.json |
| port | number | 3001 | Port to listen on |
| corsOrigin | string | string[] | * | Allowed CORS origin(s) |
Start the server:
node server.jsOn successful startup you will see:
[RushChatbot] Server running on http://localhost:30017. Embed the Widget
RushChatbot ships three separate widget builds. Use the one that matches your frontend stack.
React
Install peer dependencies if not already present:
npm install react react-dom markedImport and render the widget:
import { ChatWidget } from 'rushchatbot/client'
export default function App() {
return (
<div>
<ChatWidget apiBase="http://localhost:3001/api/chat" />
</div>
)
}The widget renders as a floating draggable button fixed to the bottom-right of the screen. Clicking it opens the chat box above the button.
React widget props
| Prop | Type | Default | Description |
|---|---|---|---|
| apiBase | string | http://localhost:3001/api/chat | Base URL of the RushChatbot server |
| width | number | from config | Chat box width in pixels (desktop only) |
| height | number | from config | Chat box height in pixels (desktop only) |
Vue 2
Install peer dependency if not already present:
npm install vue@2Register and use the component:
<script>
import ChatWidget from 'rushchatbot/vue2'
export default {
components: { ChatWidget }
}
</script>
<template>
<ChatWidget api-base="http://localhost:3001/api/chat" />
</template>Or register it globally in main.js:
import Vue from 'vue'
import App from './App.vue'
import ChatWidget from 'rushchatbot/vue2'
Vue.component('RushChatbot', ChatWidget)
new Vue({ render: h => h(App) }).$mount('#app')Then use it anywhere:
<template>
<RushChatbot api-base="http://localhost:3001/api/chat" />
</template>Vue 2 widget props
| Prop | Type | Default | Description |
|---|---|---|---|
| api-base | string | http://localhost:3001/api/chat | Base URL of the RushChatbot server |
| width | number | — | Chat box width in pixels (omit for fluid) |
| height | number | — | Chat box height in pixels (omit for fluid) |
| primary-color | string | from config | Override primary/accent color |
| bg-color | string | from config | Override background color |
| border-radius | number | 16 | Container corner radius in pixels |
| show-shadow | boolean | true | Show/hide box shadow |
| placeholder | string | Type a message... | Input placeholder text |
| send-label | string | Send | Send button label |
| hide-input | boolean | false | Hide the text input bar |
| hide-end-chat | boolean | false | Hide the "I'm done" end chat button |
Vue 3
Install peer dependency if not already present:
npm install vueRegister and use the component:
<script setup>
import ChatWidget from 'rushchatbot/vue'
</script>
<template>
<ChatWidget api-base="http://localhost:3001/api/chat" />
</template>Or register it globally in main.ts:
import { createApp } from 'vue'
import App from './App.vue'
import ChatWidget from 'rushchatbot/vue'
const app = createApp(App)
app.component('RushChatbot', ChatWidget)
app.mount('#app')Then use it anywhere:
<template>
<RushChatbot api-base="http://localhost:3001/api/chat" />
</template>Vue widget props
| Prop | Type | Default | Description |
|---|---|---|---|
| api-base | string | http://localhost:3001/api/chat | Base URL of the RushChatbot server |
| width | number | — | Chat box width in pixels (omit for fluid) |
| height | number | — | Chat box height in pixels (omit for fluid) |
| primary-color | string | from config | Override primary/accent color |
| bg-color | string | from config | Override background color |
| border-radius | number | 16 | Container corner radius in pixels |
| show-shadow | boolean | true | Show/hide box shadow |
| placeholder | string | Type a message... | Input placeholder text |
| send-label | string | Send | Send button label |
| hide-input | boolean | false | Hide the text input bar |
| hide-end-chat | boolean | false | Hide the "I'm done" end chat button |
Vanilla JS (Web Component)
No framework required. The Vanilla build registers a <rush-chatbot> custom element using the Web Components API with Shadow DOM.
Via npm
import 'rushchatbot/vanilla'Then add the element anywhere in your HTML:
<rush-chatbot api-base="http://localhost:3001/api/chat"></rush-chatbot>Via CDN / script tag
<script type="module" src="/path/to/rushchatbot/dist/vanilla.es.js"></script>
<!-- or IIFE build for non-module environments -->
<script src="/path/to/rushchatbot/dist/vanilla.iife.js"></script>
<rush-chatbot api-base="http://localhost:3001/api/chat"></rush-chatbot>Web Component attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| api-base | string | http://localhost:3001/api/chat | Base URL of the RushChatbot server |
| width | number | — | Chat box width in pixels (omit for fluid) |
| height | number | — | Chat box height in pixels (omit for fluid) |
| primary-color | string | from config | Override primary/accent color |
| bg-color | string | from config | Override background color |
| border-radius | number | 16 | Container corner radius in pixels |
| show-shadow | boolean | true | Show/hide box shadow |
| placeholder | string | Type a message... | Input placeholder text |
| send-label | string | Send | Send button label |
| hide-input | boolean | false | Hide the text input bar |
| hide-end-chat | boolean | false | Hide the "I'm done" end chat button |
| auto-open | boolean | false | Auto-open chat on load |
| position | bottom-right\|bottom-left | bottom-right | Floating button position |
Attributes can be updated at runtime and the widget will reflect the changes:
document.querySelector('rush-chatbot').setAttribute('api-base', 'https://my-server.com/api/chat')8. Floating Button Behavior
The chat button is draggable across the entire screen:
- Drag — click and hold, then move to reposition the button anywhere on screen
- Click (no drag) — toggles the chat box open or closed
- Chat box position — always appears directly above the button, clamped to the viewport so it never goes off-screen
- Close — click the ✕ button inside the chat header, or click the floating button again
- Works on both desktop (mouse) and mobile (touch)
9. n8n Webhook Setup
When a user types a query that doesn't match any FAQ answer, RushChatbot forwards it to your n8n webhook.
What RushChatbot sends to n8n
{
"query": "the user's message",
"sessionId": "sess_abc123"
}Headers sent:
Content-Type: application/json
x-session-id: sess_abc123Setting up the webhook in n8n
- Create a new workflow in n8n
- Add a Webhook trigger node — set method to
POST - Copy the webhook URL into
chatbot.config.jsonundern8n.webhookUrl - Add your AI/logic nodes after the webhook trigger
- End with a Respond to Webhook node returning one of the supported response formats (see section 11)
- Activate the workflow
Session continuity
The sessionId is generated per browser tab (sess_ + timestamp + random suffix). Pass it through your n8n workflow to maintain conversation context with your AI agent.
10. n8n Response Formats
RushChatbot automatically parses all of the following response shapes from n8n:
Single answer
[{ "output": "Your answer text here" }][{ "answer": "Your answer text here" }][{ "text": "Your answer text here" }]Multiple bubbles (paragraphs)
Return a paragraphs array to render each item as a separate chat bubble with a short delay between them:
[{
"paragraphs": [
"First part of the response.",
"Second part with **bold** and lists.",
"Third bubble with a follow-up question."
]
}]Markdown support
All responses are rendered as Markdown. Supported formatting:
| Syntax | Renders as |
|---|---|
| **bold** | bold |
| # Heading | Large heading |
| - item | Bullet list |
| 1. item | Numbered list |
| [link](url) | Hyperlink |
| \n (newline) | Line break |
11. Environment Variables
| Variable | Required | Description |
|---|---|---|
| PORT | No | Override the server port (default: 3001) |
Setting the port
PORT=4000 node server.js12. API Reference
All endpoints are mounted under /api/chat.
GET /api/chat/config
Returns branding and chat settings. Safe to call from the frontend — never exposes n8n credentials or license key.
Response:
{
"branding": { "title": "...", "subtitle": "...", "theme": { } },
"chat": { "welcomeMessage": "...", "language": "en", "window": { "width": 360, "height": null } }
}GET /api/chat/questions
Returns the FAQ question tree in the configured language.
Response:
[
{
"id": "q1",
"question": "About Our Company",
"answer": "...",
"subquestions": []
}
]GET /api/chat/query?query=your+question&sessionId=sess_abc
Forwards the query directly to n8n, bypassing FAQ matching. Useful for testing your n8n workflow from the browser.
Query params:
| Param | Required | Description |
|---|---|---|
| query | Yes | The user's question |
| sessionId | No | Session identifier |
Response:
{ "answer": "...", "source": "n8n" }or
{ "paragraphs": ["...", "..."], "source": "n8n" }POST /api/chat/query
Main query endpoint. Runs the full pipeline: input validation → guardrails → FAQ matching → n8n fallback.
Request body:
{
"query": "How do I apply for membership?",
"sessionId": "sess_abc123"
}Response (FAQ match):
{
"answer": "You can apply by...",
"source": "config",
"matchedQuestion": "How do I apply for membership?",
"matchedKeywords": ["apply", "membership"],
"score": 87
}Response (n8n fallback):
{ "answer": "...", "source": "n8n" }Response (validation/guardrail blocked):
{ "answer": "Please rephrase your question...", "source": "validation" }POST /api/chat/click
Tracks when a user clicks a pre-built FAQ question.
Request body:
{
"questionId": "q1a",
"sessionId": "sess_abc123"
}Response:
{ "ok": true }GET /api/chat/analytics
Returns the full analytics log.
Response:
[
{
"sessionId": "sess_abc123",
"questionId": "q1a",
"timestamp": "2025-01-01T10:00:00.000Z",
"type": "click"
}
]Analytics types:
| Type | Description |
|---|---|
| click | User clicked a pre-built FAQ question |
| match | User query matched a FAQ answer |
| n8n | Query was forwarded to n8n |
| error | Validation, guardrail, or server error |
13. Analytics
Analytics are written to analytics.json in the same directory as your chatbot.config.json. Each entry records:
sessionId— browser session (resets on new tab)questionId— the matched question ID, orn8n/error/guardrailtimestamp— ISO 8601 UTCtype—click,match,n8n, orerror
You can query the log at any time via GET /api/chat/analytics or read the file directly.
14. Troubleshooting
[RushChatbot] configPath not found
- Use
path.resolve()to ensure the path is absolute - Verify the file exists at the specified location
Chat widget shows nothing / blank
- Check the browser console for CORS errors
- Ensure
corsOriginincreateServer()includes your frontend's origin - Confirm the server is running and reachable at the
apiBaseURL
n8n not responding / timeout
- Increase
n8n.timeoutMsinchatbot.config.json(default is 55000ms) - Test the webhook directly:
GET http://localhost:3001/api/chat/query?query=hello - Check your n8n workflow is activated (not just saved)
Port already in use
kill $(lsof -ti :3001)Queries always fall through to n8n (no FAQ matches)
- Lower
chat.matchThresholdin config (e.g.0.3) - Ensure your
questions.jsonanswers contain keywords that appear in user queries - Check that question
idvalues are unique across the entire tree
