An embeddable AI chat widget powered by Cloudflare Workers and Llama 3.1. The widget provides a personalized AI assistant experience with intelligent theming, Wikipedia integration, and customizable persona.
- Features
- Installation
- Run Locally
- Theming & Customization
- Language Detection
- API Reference
- Customization
- Development
- Performance Optimization
- Security
- Troubleshooting
- Frequently Asked Questions
- Contributing
- License
- Support
- Personalized AI: Customize the AI's persona, knowledge, and tone by editing the
src/systemInstruction.txtfile. - Wikipedia Integration: Provides accurate, summarized answers to factual questions by dynamically querying Wikipedia when appropriate.
- Response Deduplication: Processes AI responses to remove repetitive phrases and ensure concise output.
- Intelligent Theming: Automatically adapts to website design through multiple detection methods including CSS variables, background colors, and framework detection.
- Modern Interface: Clean, responsive, mobile-friendly design with glassmorphic effects.
- Rate Limiting: Protects the API from abuse with IP and customer-based rate limiting.
- Simple Integration: Add to any website with a single script tag.
- Language Support: Automatic language detection with support for English and Bahasa Indonesia.
- Caching: Intelligent caching system for improved performance and reduced API costs.
To use the widget, you need to deploy it as a Cloudflare Worker. The deployment process requires Wrangler CLI and takes approximately 5-10 minutes to complete.
Before starting, ensure you have the following:
- Node.js: Version 16 or later (check with
node --version) - npm: Included with Node.js (check with
npm --version) - Wrangler CLI: Cloudflare's command-line tool for Workers
- Cloudflare Account: With Workers enabled
- Git: For cloning the repository
- Operating System: Linux, macOS, or Windows (with WSL)
- RAM: Minimum 512MB available
- Storage: 200MB free space
- Network: Stable internet connection for deployment
Install Wrangler globally using npm:
npm install -g wranglerVerify installation:
wrangler --versionClone the project repository and navigate to the directory:
git clone https://github.com/1999AZZAR/live-chat-widget.git
cd live-chat-widgetInstall project dependencies:
npm installThis will install all required packages including Wrangler and development dependencies.
Login to your Cloudflare account:
wrangler auth loginThis will open your browser for authentication. Follow the prompts to complete the login process.
If you need to modify the default configuration, edit wrangler.toml:
name = "live-chat-widget"
main = "src/index.js"
workers_dev = true
compatibility_date = "2025-05-14"Deploy the worker to Cloudflare's edge network:
npm run deployThe deployment process will:
- Bundle your code and dependencies
- Upload to Cloudflare's servers
- Configure the worker with the specified bindings
- Provide a deployment URL
Upon successful deployment, you'll receive a URL like:
https://live-chat-widget.your-account.workers.dev
After deployment, add the widget to your website by including a single script tag in your HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Website</title>
</head>
<body>
<!-- Your website content -->
<!-- Live Chat Widget -->
<script src="https://live-chat-widget.your-account.workers.dev/widget.js"></script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Website</title>
<!-- Define CSS variables for theming -->
<style>
:root {
--primary-color: #007bff;
--background: #ffffff;
--text-color: #333333;
--border-radius: 12px;
}
/* Dark mode variables */
@media (prefers-color-scheme: dark) {
:root {
--primary-color: #4dabf7;
--background: #1a1a1a;
--text-color: #ffffff;
}
}
</style>
</head>
<body>
<!-- Your website content -->
<!-- Live Chat Widget with forced light theme -->
<script src="https://live-chat-widget.your-account.workers.dev/widget.js" data-color="light"></script>
</body>
</html>After embedding, verify the widget is working:
- Visual Check: Look for the chat bubble in the bottom-right corner of your page
- Console Check: Open browser developer tools and check for any JavaScript errors
- Functionality Test: Click the chat bubble and send a test message
If the widget doesn't appear:
- Check Script URL: Ensure the script
srcattribute points to your deployed worker URL - Verify Deployment: Confirm the worker deployed successfully and is accessible
- Browser Cache: Clear browser cache and reload the page
- Console Errors: Check browser developer tools for JavaScript errors
You can run the worker locally with Wrangler and test the widget on a simple HTML page.
-
Start the dev server:
# Using npm scripts (recommended) npm install npm run dev # Or explicitly run fully local (no Cloudflare edge services) npm run dev -- --local
Or use npx directly (no local install required):
npx wrangler dev # remote dev (recommended for AI binding) npx wrangler dev --local # local-only runtime
Notes:
- Remote dev (default without
--local) is recommended because it supports Cloudflare AI and KV bindings defined inwrangler.toml. The chat will work end-to-end. - Local mode (
--local) is great for UI/theming testing, but AI responses may not work if the AI binding isn't available locally.
Wrangler will print a local URL like
http://127.0.0.1:8787. - Remote dev (default without
-
Create a minimal test page (e.g.,
local-test.html) and point the script to your local worker URL:<!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Widget Local Test</title> <!-- Optional Tailwind CDN to try Tailwind/DaisyUI detection --> <script src="https://cdn.tailwindcss.com"></script> </head> <body class="min-h-screen bg-gray-50 p-8"> <h1 class="text-2xl font-bold mb-4">Live Chat Widget - Local Test</h1> <p class="mb-8">This page loads the widget from your local Cloudflare Worker.</p> <!-- Load widget from local worker; add data-color to force theme if needed --> <script src="http://127.0.0.1:8787/widget.js" data-color="auto"></script> </body> </html>
-
Open the file in your browser (double-click or serve it with any static server). The widget should appear in the bottom-right and talk to the local worker. Try toggling Tailwind classes (e.g., add
class="dark"tohtml) to see color/theme detection in action. -
Test the API directly (optional):
curl -X POST http://127.0.0.1:8787/api/chat \ -H 'Content-Type: application/json' \ -d '{"message":"Hello"}'
- Start dev (remote, with bindings):
npm run dev # or npx wrangler dev - Start dev (local runtime):
npm run dev -- --local # or npx wrangler dev --local - Deploy to Cloudflare:
npm run deploy # or npx wrangler deploy
The widget intelligently determines its theme by checking sources in a specific order of priority. This allows for flexible and powerful customization.
-
data-colorAttribute (Highest Priority): You can force a specific theme by adding thedata-colorattribute to the script tag. This is the easiest and most direct way to set a theme.- Force dark mode:
<script src=".../widget.js" data-color="dark"></script>
- Force light mode:
<script src=".../widget.js" data-color="light"></script>
- Force dark mode:
-
Host Page Theme Detection (Automatic): If
data-coloris not set, the widget attempts to detect the theme from your website's existing styles. It looks for:- Background Color of Major Containers: Inspects visible
main,#root,#app,#__next, etc. to determine light/dark based on luminance. - CSS Variables: Reads standard CSS variables like
--primary-color,--background,--text-color, etc., to match your site's branding. - Tailwind/DaisyUI Support:
- Detects Tailwind
darkmode class onhtml/body. - Picks non-neutral Tailwind colors from elements with
bg-*ortext-*classes. - Probes DaisyUI
btn btn-primaryto inferprimary-colorandon-primary.
- Detects Tailwind
- Inferred Styles: If variables aren't present, it infers colors from prominent elements like buttons and links.
- Background Color of Major Containers: Inspects visible
-
OS Preference (Fallback): If no theme can be determined from the methods above, the widget will fall back to the user's operating system preference (
prefers-color-scheme).
For seamless integration, define CSS variables in your site's stylesheet. The widget automatically detects and uses these variables.
| CSS Variable | Description | Default |
|---|---|---|
--primary-color |
Main accent color for buttons and user messages | Auto-detected |
--on-primary |
Text color for elements with primary background | Auto-calculated |
--background |
Chat window background color | Auto-detected |
--text-color |
Primary text color | Auto-detected |
--border-radius |
Border radius for bubbles and inputs | 12px |
--font-family |
Font family for widget text | System font |
Example:
:root {
--primary-color: #007bff;
--on-primary: #ffffff;
--background: #f8f9fa;
--text-color: #212529;
--border-radius: 12px;
--font-family: 'Inter', sans-serif;
}The widget includes special detection for popular frameworks:
Tailwind CSS:
- Detects
bg-*andtext-*classes for color inference - Recognizes
dark:mode classes - Automatically switches between light and dark themes
DaisyUI:
- Probes for
btn btn-primaryelements to detect primary colors - Inherits color scheme from DaisyUI components
For precise control, use the data-color attribute:
<!-- Force light theme -->
<script src="/widget.js" data-color="light"></script>
<!-- Force dark theme -->
<script src="/widget.js" data-color="dark"></script>
<!-- Auto-detect (default) -->
<script src="/widget.js" data-color="auto"></script>The widget automatically detects the language to use for its welcome message by checking in this order:
window.AZZAR_CHAT_CONFIG.lang: A globally defined JavaScript variable.<script data-azzar-lang="...">: An attribute on the script tag.<html lang="...">: Thelangattribute of your HTML tag.navigator.language: The browser's default language setting.
You can also change the language dynamically at any time by calling window.azzarChatSetLang('your-lang-code').
The widget provides several endpoints for integration and monitoring.
GET /widget.js: Serves the main widget script for embeddingGET /widget-iframe: Serves the iframe content for the chat interfacePOST /api/chat: Main chat endpoint for sending messagesGET /api/welcome-message: Generates and returns an AI welcome messageGET /api/cache-stats: Returns statistics about the LRU cache performance
Send a POST request to /api/chat with the following JSON payload:
{
"message": "User message here",
"history": [
{"role": "user", "content": "Previous user message"},
{"role": "assistant", "content": "Previous AI response"}
]
}Response:
{
"response": "AI response text"
}Set language through multiple methods:
-
Global Variable:
window.AZZAR_CHAT_CONFIG = { lang: 'id' };
-
Script Attribute:
<script src="/widget.js" data-azzar-lang="id"></script>
-
HTML Lang Attribute:
<html lang="id">
-
Runtime Change:
window.azzarChatSetLang('id');
The API implements dual-layer rate limiting:
- IP-based: 100 requests per minute per IP
- Customer-based: 30 requests per minute per API key
Rate limit headers are included in responses:
X-RateLimit-Remaining: Remaining requestsRetry-After: Seconds until reset (when exceeded)
The widget uses a multi-level caching system:
- Memory Cache: Fast LRU cache for recent conversations
- KV Cache: Persistent cache for frequently accessed data
- Response Deduplication: Prevents repetitive AI responses
Cache statistics available at /api/cache-stats.
To customize the AI's personality, knowledge, and behavior:
- Edit the
src/systemInstruction.txtfile with your desired persona details - Deploy changes:
npm run deploy
The AI will use the new persona for all conversations. The persona file includes:
- Personality traits and communication style
- Technical expertise and knowledge areas
- Response guidelines and limitations
The AI includes built-in knowledge of Azzar's rate calculation methodology:
- Hourly rates from $20-$35 based on project size
- Consultation fees ($70-$120) every 30 hours
- Payment plans with 2-3 installment options
- Multi-currency support with real-time conversion
The project follows a modular architecture designed for Cloudflare Workers:
live-chat-widget/
├── src/
│ ├── index.js # Main Cloudflare Worker entry point
│ ├── systemInstruction.txt # AI persona configuration and knowledge base
│ ├── widget-generator.js # Client-side widget JavaScript generation
│ ├── iframe-generator.js # Chat interface HTML generation
│ ├── lru-handler.js # LRU cache implementation with KV storage
│ └── crawl.txt # Additional resources and configuration
├── wrangler.toml # Cloudflare Workers configuration
├── package.json # Node.js dependencies and scripts
├── API.md # API documentation
└── README.md # Project documentation
src/index.js: Main worker logic handling routing, rate limiting, and API endpointssrc/systemInstruction.txt: Defines the AI assistant's personality, knowledge, and behaviorwrangler.toml: Configuration for Cloudflare Workers bindings and deployment settings
src/widget-generator.js: Generates the embeddable JavaScript for websitessrc/iframe-generator.js: Creates the chat interface HTML and styling
src/lru-handler.js: Implements caching with memory and KV storage layerssrc/crawl.txt: Contains additional resources and configuration data
The worker uses the following environment variables and bindings:
| Binding | Type | Purpose |
|---|---|---|
AI |
AI | Llama 3.1 model for chat responses |
SYSTEM_PROMPT |
KV | Persistent storage for system prompts |
RATE_LIMITER_KV |
KV | Rate limiting data storage |
| Variable | Default | Description |
|---|---|---|
DEBUG |
false |
Enable debug logging and additional error information |
The project supports two development modes:
Remote Mode (Recommended):
npm run dev- Full Cloudflare integration with AI and KV bindings
- End-to-end functionality testing
- Requires active internet connection
Local Mode:
npm run dev -- --local- Runs without Cloudflare services
- Useful for UI testing and development
- AI responses will not work
-
Start Development Server:
npm run dev
-
Access Local Worker:
- Worker URL:
http://127.0.0.1:8787 - Widget script:
http://127.0.0.1:8787/widget.js
- Worker URL:
-
Test with Sample Page:
<!DOCTYPE html> <html> <head> <title>Widget Test</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <h1>Live Chat Widget Test</h1> <script src="http://127.0.0.1:8787/widget.js"></script> </body> </html>
Test the chat endpoint directly:
# Simple message test
curl -X POST http://127.0.0.1:8787/api/chat \
-H "Content-Type: application/json" \
-d '{"message":"Hello, how are you?"}'
# Test with conversation history
curl -X POST http://127.0.0.1:8787/api/chat \
-H "Content-Type: application/json" \
-d '{
"message":"What is your name?",
"history":[
{"role":"user","content":"Hello"},
{"role":"assistant","content":"Hello! How can I help you today?"}
]
}'- Visual Testing: Verify widget appears and functions correctly
- Theme Testing: Test light/dark mode switching
- Language Testing: Verify language detection and switching
- Mobile Testing: Test responsiveness on different screen sizes
Monitor cache statistics:
curl http://127.0.0.1:8787/api/cache-statsCheck rate limiting status:
curl -I http://127.0.0.1:8787/api/chat \
-H "Content-Type: application/json" \
-d '{"message":"test"}'Run linting checks:
# Check for syntax errors and style issues
npm run lintThe project uses JSDoc for type documentation. All functions include parameter and return type information.
# Deploy to Cloudflare Workers
npm run deploy
# Check deployment status
wrangler tail live-chat-widgetFor production deployments, ensure:
- KV Namespaces: Created and properly configured
- AI Binding: Enabled in Cloudflare dashboard
- Custom Domain: Optional, for branded URLs
- Rate Limits: Configured according to usage requirements
The widget uses multiple caching layers:
- LRU Memory Cache: Recent conversations (1 hour TTL)
- KV Cache: Persistent storage for API responses
- Response Deduplication: Prevents repetitive AI output
Dual-layer protection:
- IP-based: 100 requests/minute
- Customer-based: 30 requests/minute per API key
The widget is optimized for fast loading:
- Gzipped widget.js: ~35KB
- Minimal external dependencies
- Lazy-loaded components
- Origin validation for API endpoints
- Rate limiting prevents abuse
- CORS headers for cross-origin requests
- Input sanitization and validation
- No persistent storage of chat history
- Anonymous usage analytics only
- Compliant with privacy regulations
- No third-party tracking
- Check browser console for errors
- Verify script URL is correct
- Ensure HTTPS in production
- Check CORS headers if using custom domain
- Verify Cloudflare AI binding is configured
- Check rate limits haven't been exceeded
- Review systemInstruction.txt for persona issues
- Check KV namespace configuration
- Verify CSS variables are defined in
:root - Check for conflicting styles
- Use
data-colorattribute for manual control - Test with different browsers
- Set HTML
langattribute - Use
data-azzar-langscript attribute - Check
navigator.languagefallback - Use
window.azzarChatSetLang()for runtime changes
Q: What is the Live Chat Widget? A: The Live Chat Widget is an embeddable AI-powered chat interface that can be added to any website with a single script tag. It uses Cloudflare Workers and Llama 3.1 to provide intelligent responses.
Q: How much does it cost to use? A: The widget uses Cloudflare's free tier for Workers and KV storage. AI usage may incur costs based on Cloudflare's AI pricing. The widget itself is free to deploy and use.
Q: Can I customize the AI's personality?
A: Yes, you can modify the src/systemInstruction.txt file to customize the AI's personality, knowledge, and response style.
Q: What browsers are supported? A: The widget supports all modern browsers including Chrome, Firefox, Safari, and Edge. It requires JavaScript to be enabled.
Q: Can I use this on a static website? A: Yes, the widget works on any website that can load external JavaScript, including static sites hosted on Netlify, Vercel, GitHub Pages, etc.
Q: How does the widget handle user data? A: The widget does not store chat history or personal data. All conversations are processed in real-time and not retained after the session ends.
Q: Can I integrate this with my existing chat system? A: The widget can be extended via the API to integrate with existing systems. See the API documentation for details.
Q: How do I change the widget's appearance?
A: Use CSS variables in your website's stylesheet or the data-color attribute on the script tag. See the Theming section for detailed instructions.
Q: Can I change the widget's position on the page? A: Currently, the widget appears in the bottom-right corner. Custom positioning would require modifying the widget code.
Q: How do I change the language?
A: The widget automatically detects language from HTML attributes. You can also use the data-azzar-lang attribute or call window.azzarChatSetLang().
Q: The widget doesn't appear on my website A: Check that the script URL is correct and accessible. Clear browser cache and verify there are no JavaScript errors in the console.
Q: The AI responses are slow A: Response times depend on Cloudflare's AI service. Check your internet connection and ensure you're not hitting rate limits.
Q: The theme doesn't match my website
A: Verify your CSS variables are properly defined and the widget has access to them. Try using the data-color attribute for manual theme control.
We welcome contributions to improve the Live Chat Widget. Please follow these guidelines:
-
Fork the Repository
- Click the "Fork" button on GitHub
- Clone your fork:
git clone https://github.com/your-username/live-chat-widget.git
-
Set Up Development Environment
cd live-chat-widget npm install npm run dev -
Create a Feature Branch
git checkout -b feature/your-feature-name
- Use consistent indentation (2 spaces)
- Add JSDoc comments for functions
- Follow existing naming conventions
- Keep functions focused and single-purpose
- Test your changes locally before submitting
- Verify widget functionality in different browsers
- Test with both light and dark themes
- Check mobile responsiveness
- Use clear, descriptive commit messages
- Start with a verb (Add, Fix, Update, Remove)
- Keep first line under 50 characters
- Add detailed description if needed
-
Ensure Code Quality
# Run linting (if available) npm run lint # Test locally npm run dev
-
Update Documentation
- Update README.md if adding new features
- Update API.md for API changes
- Add code comments for complex logic
-
Create Pull Request
- Push your branch to GitHub
- Create a pull request with a clear description
- Reference any related issues
Bug Fixes:
- Fix reported issues
- Improve error handling
- Enhance stability
Features:
- New functionality
- UI/UX improvements
- Performance enhancements
Documentation:
- Improve existing docs
- Add examples and tutorials
- Translate documentation
- Automated checks will run on your PR
- Maintainers will review your code
- Address any feedback or requested changes
- Once approved, your changes will be merged
When reporting bugs or requesting features:
- Use the GitHub issue templates
- Provide clear steps to reproduce
- Include browser and OS information
- Attach screenshots if relevant
Thank you for contributing to the Live Chat Widget!
This project is licensed under the MIT License. See the LICENSE file for full terms and conditions.
For support and questions:
- Documentation: Check this README and API.md
- Issues: Use GitHub Issues for bugs and feature requests
- Discussions: Use GitHub Discussions for questions and general discussion
Built with Cloudflare Workers and Llama 3.1