A production-ready RAG (Retrieval Augmented Generation) chatbot platform that enables businesses to create intelligent, context-aware chatbots for their websites.
| Feature | Description | |
|---|---|---|
| 🔒 | Privacy First | Run entirely on your infrastructure. Use local LLMs (Ollama) for complete data isolation—your conversations never touch external servers. |
| ♾️ | Unlimited Everything | One deployment = unlimited sites, unlimited chatbots, unlimited conversations. No per-site fees, no usage caps. |
| 🏠 | Self-Hosted | Your data stays on your servers. Full privacy and control over your customer interactions. |
| 🔄 | No Vendor Lock-in | Swap between Ollama, OpenAI, Anthropic, or Azure with a single env var. |
| 🚀 | Production Ready | Security headers, rate limiting, JWT auth, and 440+ tests included. |
| 🎨 | White-Label | Fully customizable branding for the platform and chat widget. |
| 📦 | Easy Integration | Single <script> tag to add chat to any website. |
Dashboard & Widget Customization
Manage your sites, customize widget appearance, and see a live preview of your chatbot.
Embed Code
Get a ready-to-use embed code to add the chatbot to any website with a single script tag.
Many businesses rely on cloud-based chatbot services that charge recurring subscription fees and store customer data on third-party servers. SiteChat offers a fundamentally different approach:
| Aspect | Commercial SaaS Platforms | SiteChat |
|---|---|---|
| Pricing | Monthly subscriptions ($49-$500+/mo), usage-based fees | One-time deployment, no recurring fees ever |
| Sites & Chatbots | Pay per site, limited chatbots per plan | Unlimited sites, unlimited chatbots from single install |
| Conversations | Metered usage, overage charges | Unlimited conversations, no caps |
| Data Privacy | Your data on their servers, shared infrastructure | 100% self-hosted, data never leaves your control |
| AI Model Privacy | All queries sent to cloud APIs | Run local LLMs (Ollama) for complete data isolation |
| Page/Content Limits | Tiered limits (50-5000 pages), overages charged | Unlimited pages and documents |
| LLM Flexibility | Locked to their chosen model (usually one provider) | Swap between Ollama, OpenAI, Anthropic, or Azure freely |
| Customization | Limited branding options, "Powered by" badges | Full white-labeling, complete UI control |
| Compliance | Limited compliance options | GDPR/HIPAA-ready, air-gapped deployments possible |
| Vendor Lock-in | Proprietary formats, no data export | Open source, standard formats, full portability |
| API Access | Limited or premium-tier only | Full API access included |
- Agencies & Multi-Site Businesses: Manage chatbots for all your client sites or properties from one installation—no per-site fees
- Privacy-Critical Industries: Healthcare, legal, finance, or government where data sovereignty is non-negotiable
- Complete Data Isolation: Run local LLMs with Ollama—customer conversations never leave your servers
- High-Volume Operations: Unlimited conversations without metered billing or overage charges
- Custom Integrations: Need deep integration with internal systems via full API access
- Long-Term Cost Control: One deployment, zero recurring fees—scale without scaling costs
- Full Branding: Complete white-labeling with no third-party badges or attributions
SiteChat requires self-hosting infrastructure and technical expertise to deploy and maintain. Commercial platforms offer managed hosting and support, which may be preferable for teams without DevOps resources.
| Getting Started | Reference | Operations |
|---|---|---|
| 🚀 Quick Start | 📚 API Reference | 🧪 Testing |
| ⚙️ Configuration | 🔌 Widget Integration | 🔒 Production Security |
| 🏗️ Architecture | 🎯 Features | 🤝 Contributing |
| 📸 Screenshots | 🔄 Comparison | 🆕 Recent updates |
Highlights from the latest platform and dashboard work:
- Mandatory admin password change — New auto-created admin accounts are flagged with
must_change_password. Legacy admin users without that field are migrated on startup so they must pick a new password on first login. - API lock until password is set — While
must_change_passwordis true, admins may only callGET/PATCH/api/auth/me. Other dashboard APIs return403with codemust_change_password. - Profile password flow —
PATCH /api/auth/meallows setting a new password without the current password whenmust_change_passwordis true; otherwise the current password is still required. - Admin management of site owners —
PATCH /api/auth/users/{user_id}lets admins update a site owner’s (role=user) display name and/or password. - User API — Responses include
must_change_passwordwhere applicable.
- JWT on conversation routes — Listing, search, detail, notes, tags, status, export, delete, and related operations require a valid Bearer token.
- Role-scoped data — Admins see all sites (optional
site_idfilter). Support agents see only conversations for sites inassigned_site_ids(multi-site queries use asite_id$infilter). Site owners see only their own sites’ conversations. - Agent restrictions — Agents cannot export conversations or delete (single or bulk).
POST /api/conversations/auto-closeis admin-only. Exports for non-admins require explicitsite_idand/orsession_idsscoped to sites they can access.
- Visitor abandon —
POST /api/handoff/{handoff_id}/abandon(public, rate-limited) marks a handoff abandoned when the visitor leaves; body includessession_idfor verification. The embeddable widget calls this on unload/navigation where possible (includingsendBeacon). - Re-request signal — If a visitor requests a human again while the request is still pending, the server bumps
visitor_queue_signalsand updates the row so the agent queue and SSE stream can highlight “still waiting / nudge” behavior. - Agent queue visibility — Support agents see unassigned items (open pool) plus handoffs assigned to them. Admins and site owners still see the full queue for the site(s). SSE uses the same rules and includes queue row identity (including signals) so updates propagate reliably.
- Abandoned handoffs — Messaging, assignment, and status changes are rejected appropriately once a session is abandoned.
- Site-scoped access — List, export, count, and delete check that the caller may view that site (
can_view_site). Agents cannot delete leads.
- First-login gate — After login, admins with
must_change_passwordget a blocking “Set your password” modal until they save a new password (dashboard is inert until then). - Agents — Default view is Handoffs; white-label settings are not loaded for the agent role. Sidebar navigation uses delegated clicks and keeps menu + utility links in sync for the active view.
- Handoffs UI — Copy explains the shared pending queue; assign to agent sits with the conversation chrome for clearer workflow.
- Landing — The chat widget is loaded with a normal
<script>tag (same-origin in dev). For a separate API host, setdata-api-urlon the script. - Cache busting — Dashboard CSS may use a query string on
styles.cssafter UI changes so browsers pick up new styles.
- Default CORS — Includes
http://localhost:8015andhttp://127.0.0.1:8015for common alternate dev ports. - Widget build — If
npm run buildfails with “source missing”, restorefrontend/src/widget/chatbot.jsfrom the repo;frontend/widget/is build output only.
| Category | Features |
|---|---|
| Core | Site management, document upload, RAG chatbot, multi-LLM support |
| Widget | Embeddable chat, customizable appearance, proactive triggers, lead capture |
| Operations | Conversation history, analytics dashboard, human handoff, Q&A training |
| Admin | JWT auth, role-based access, mandatory admin password setup, security hardening, white-labeling |
Site & Document Management
- Website Crawling - Automatically crawl and index website content with status tracking
- Multi-site Support - Manage multiple websites from a single dashboard
- Scheduled Re-crawling - Daily/weekly/monthly auto-crawl with URL filtering
- Document Upload - PDF, DOCX, TXT, MD with automatic chunking and vector embeddings
AI Chatbot with RAG
- Intelligent Responses - Context-aware answers using retrieved content
- Source Citations - Responses include references to source documents
- Confidence Scores - Each response includes a confidence rating
- Follow-up Suggestions - AI suggests relevant follow-up questions
- Streaming Responses - Real-time streaming for better UX
- Multi-LLM Support - Ollama, OpenAI, Anthropic, Azure OpenAI
Embeddable Chat Widget
- Single Script Tag - Easy integration on any website
- Customizable - Colors, title, welcome message, position
- Responsive - Works on desktop and mobile
- Live Preview - See changes in real-time while customizing
- Embed Code Generator - Copy-paste ready integration code
- Behavior Config - System prompt, temperature, max tokens
Proactive Triggers
- Conditions - Time on page, scroll depth, exit intent, URL patterns, visit count
- Actions - Nudge notification or auto-open chat
- Settings - Custom messages, cooldown periods
- Analytics - Track impressions, clicks, and conversions
Lead Generation
- Widget Capture - Collect visitor email and name during chat sessions
- Duplicate Prevention - Automatically skip re-prompting for existing leads
- Source Tracking - Track where leads originated (chat, form, etc.)
- CSV Export - Export all leads with timestamps for CRM import
- Search & Pagination - Easily browse and search captured leads
- Access Control - Dashboard lead APIs enforce per-site access; agents cannot delete leads
Conversation Management
- Authenticated API - List, search, detail, tags, notes, and exports require JWT; access is limited by role (admin / site owner / agent)
- Full History - Admins see all sites; agents only assigned sites; owners only their sites
- Search & Filter - By content, date, or site (scoped like list)
- Export - Download conversations for analysis (not available to agents; site owners need explicit site/session scope)
- Bulk Operations - Delete or manage multiple conversations (agents cannot delete)
- Auto-close - Inactive conversation cleanup is admin-only
- Session Tracking - Track user sessions and engagement
Analytics Dashboard
- Metrics - Conversations, messages, confidence scores, response times
- Time Periods - Day, week, month views
- Visualizations - Interactive charts with Chart.js
- Per-site Filtering - Drill down by specific sites
Human Handoff
- Triggers - User-initiated, AI-suggested (low confidence), phrase detection
- Visitor Abandon - Visitors can abandon a handoff when leaving the page; widget calls the public abandon endpoint with session verification
- Re-request While Pending - Repeated “connect to human” while still pending bumps a queue signal for agent visibility and SSE updates
- Agent Dashboard - Real-time queue, pending/active/resolved filters; agents see the open pool plus tickets assigned to them; admins/owners see the full site queue
- Business Hours - Configurable schedule, timezone support, offline messages
- Live Chat - Real-time messaging between agent and visitor (blocked for resolved/abandoned sessions)
Q&A Training
- Custom Q&A Pairs - Create question-answer pairs to improve chatbot responses
- From Conversations - Convert existing chat exchanges into training data
- Edit & Refine - Modify answers before saving as training data
- Enable/Disable - Toggle Q&A pairs on/off without deleting
- RAG Integration - Q&A pairs are automatically used in response generation
- Statistics - Track total, enabled, and recently added Q&A pairs
Authentication & Authorization
- JWT Authentication - Secure token-based auth
- Role-based Access - Admin, site owner (
user), and support agent roles with scoped data access - Mandatory Admin Password - New and migrated admin accounts can be required to set a new password before using the rest of the API; until then, only profile (
/api/auth/me) is allowed - Admin Updates Site Owners - Admins can patch site-owner accounts (
name/password) via/api/auth/users/{user_id} - Password Policy - Configurable complexity requirements
- Session Management - Secure login/logout;
must_change_passwordexposed in user responses
Security Features
- Headers - X-Frame-Options, CSP, HSTS, X-XSS-Protection
- CORS - Configurable origins, no wildcards in production
- Validation - Content limits, input sanitization, user agent blocking
- Rate Limiting - Per-IP limits on login, chat, lead capture, and handoff endpoints
- Spam Protection - Honeypot fields on lead capture and handoff to silently block bots
- Environment Modes - Development, staging, production with auto-warnings
White-labeling
- Platform - Custom name, logo, favicon, colors, footer
- Widget - Hide "Powered by" branding, custom branding text/link
| Layer | Technology |
|---|---|
| Backend | FastAPI, Python 3.10+, Pydantic |
| Database | MongoDB (Motor async driver) |
| Vector Store | FAISS (swappable: Chroma, Pinecone, Qdrant) |
| LLM | LangChain + Ollama/OpenAI/Anthropic/Azure |
| Embeddings | HuggingFace Sentence Transformers |
| Auth | JWT (python-jose), passlib, SlowAPI (rate limiting) |
| Frontend | Vanilla JS, CSS Variables, Chart.js |
| Widget | Standalone JS (obfuscated via javascript-obfuscator) |
| Doc Processing | PyPDF, docx2txt, BeautifulSoup4 |
SiteChat uses a Provider Pattern for all infrastructure components, making it easy to swap providers without changing business logic.
| Component | Options | Default |
|---|---|---|
| LLM | Ollama, OpenAI, Anthropic, Azure | Ollama |
| Embeddings | HuggingFace, OpenAI, Ollama | HuggingFace |
| Vector Store | FAISS, Chroma, Pinecone, Qdrant | FAISS |
| Database | MongoDB, PostgreSQL (planned) | MongoDB |
| Storage | Local, S3 (planned), GCS (planned) | Local |
| Cache | Memory, Redis (planned) | Memory |
Change environment variables in .env:
# Example: Switch to OpenAI
LLM_PROVIDER=openai
LLM_MODEL=gpt-4-turbo
OPENAI_API_KEY=sk-xxx
# Example: Switch to Pinecone
VECTOR_STORE_PROVIDER=pinecone
PINECONE_API_KEY=xxx
PINECONE_INDEX=sitechatsitechat/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI entry point
│ │ ├── config.py # Configuration & settings
│ │ ├── core/ # Dependencies & security middleware
│ │ ├── providers/ # Swappable infrastructure
│ │ │ ├── factory.py # LangChain component factories
│ │ │ ├── database/ # Database providers (MongoDB)
│ │ │ ├── storage/ # Storage providers (Local/S3)
│ │ │ └── cache/ # Cache providers (Memory/Redis)
│ │ ├── database/ # Vector store & DB operations
│ │ ├── models/ # Pydantic schemas
│ │ ├── routes/ # API endpoints
│ │ │ ├── auth.py, chat.py, sites.py, documents.py
│ │ │ ├── conversations.py, analytics.py, crawl.py
│ │ │ ├── triggers.py, handoff.py, platform.py, embed.py
│ │ │ ├── leads.py, qa.py # Lead capture & Q&A training
│ │ └── services/ # Business logic
│ │ ├── rag_engine.py # RAG implementation
│ │ ├── crawler.py # Web crawler
│ │ ├── document_processor.py, indexer.py
│ ├── tests/ # Pytest test suite
│ │ ├── unit/ # Unit tests
│ │ ├── integration/ # API tests
│ │ ├── security/ # Security tests
│ │ └── providers/ # Provider tests
│ ├── requirements.txt
│ └── .env.example
├── frontend/
│ ├── landing.html # Marketing landing (served at /)
│ ├── index.html # Dashboard SPA (served at /app)
│ ├── login.html # Login page
│ ├── demo.html # Widget demo
│ ├── js/app.js # Dashboard logic
│ ├── css/styles.css
│ ├── css/landing.css # Landing page styles
│ ├── package.json # Widget build config
│ ├── build.js # Obfuscation script
│ ├── src/widget/chatbot.js # Widget source (edit here; commit to git)
│ └── widget/ # Obfuscated widget (served)
│ ├── chatbot.js # Production build
│ └── chatbot.min.js # Minified build
├── e2e/ # Playwright E2E tests
└── README.md
| Requirement | Version | Purpose |
|---|---|---|
| Python | 3.10+ | Backend server |
| MongoDB | 6.0+ | Database |
| Ollama | Latest | Local LLM |
| Node.js | 18+ | Widget build (optional) |
# 1. Clone and setup backend
git clone <repository-url>
cd sitechat/backend
python -m venv venv && source venv/bin/activate && pip install -r requirements.txt
# Windows: python -m venv venv && venv\Scripts\activate && pip install -r requirements.txt
# 2. Configure environment
cp .env.example .env
# Edit .env with your settings (see Configuration section below)
# 3. Start MongoDB
mongod --dbpath /path/to/data
# 4. Pull Ollama model and start server
ollama pull llama3.2
ollama serve
# 5. Run the application (in a new terminal)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000| URL | Description |
|---|---|
| http://localhost:8000 | Marketing landing |
| http://localhost:8000/app | Dashboard (after login) |
| http://localhost:8000/dashboard | Same as /app |
| http://localhost:8000/login | Sign in |
| http://localhost:8000/api/docs | API Documentation |
| http://localhost:8000/demo | Widget Demo |
Seeing “It works!”? That is Apache on port 80, not SiteChat. Use http://localhost:8000 above, or run
./scripts/run-sitechat.shfrom the repo root (opens the browser). To serve SiteChat on plainhttp://localhost, see deploy/APACHE_PROXY.md.
- Email: admin@sitechat.in
- Password: Admin123!
⚠️ Change these credentials in production!
cd frontend
npm install
npm run buildSee backend/.env.example for a complete list of all configuration options.
# ===========================================
# App Settings
# ===========================================
APP_NAME=SiteChat
DEBUG=true
# ===========================================
# LLM Provider (ollama, openai, anthropic, azure)
# ===========================================
LLM_PROVIDER=ollama
LLM_MODEL=llama3.1:8b
OLLAMA_BASE_URL=http://localhost:11434
# OPENAI_API_KEY=sk-xxx # If using OpenAI
# ANTHROPIC_API_KEY=sk-ant-xxx # If using Anthropic
# ===========================================
# Embeddings Provider (huggingface, openai, ollama)
# ===========================================
EMBEDDINGS_PROVIDER=huggingface
EMBEDDINGS_MODEL=all-MiniLM-L6-v2
# ===========================================
# Vector Store (faiss, chroma, pinecone, qdrant)
# ===========================================
VECTOR_STORE_PROVIDER=faiss
FAISS_INDEX_PATH=./data/faiss_index
# ===========================================
# Database (mongodb)
# ===========================================
DATABASE_PROVIDER=mongodb
MONGODB_URL=mongodb://localhost:27017
MONGODB_DB=sitechat
# ===========================================
# Storage (local)
# ===========================================
STORAGE_PROVIDER=local
LOCAL_STORAGE_PATH=./data/uploads
# ===========================================
# Cache (memory)
# ===========================================
CACHE_PROVIDER=memory
CACHE_TTL=300
# ===========================================
# Security Settings
# ===========================================
ENVIRONMENT=production # development, staging, production
CORS_ORIGINS=https://yourdomain.com,https://api.yourdomain.com
TRUSTED_HOSTS=yourdomain.com,api.yourdomain.com
ENABLE_SECURITY_HEADERS=true
# ===========================================
# Authentication
# ===========================================
# Generate a strong secret: python -c "import secrets; print(secrets.token_hex(32))"
JWT_SECRET=your-64-character-secret-key-here
JWT_ALGORITHM=HS256
JWT_EXPIRE_HOURS=24
# Admin (created on first run if ADMIN_PASSWORD is set)
# Set to empty string to disable auto-creation
ADMIN_EMAIL=admin@yourdomain.com
ADMIN_PASSWORD=YourStr0ng!Passw0rd
# Password policy
MIN_PASSWORD_LENGTH=8
REQUIRE_PASSWORD_COMPLEXITY=trueFull documentation available at /api/docs (Swagger UI) when running the server.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/login |
User login |
| POST | /api/auth/register |
User registration |
| GET | /api/auth/me |
Get current user (includes must_change_password when applicable) |
| PATCH | /api/auth/me |
Update profile; set new_password without current password when must_change_password is true |
| PATCH | /api/auth/users/{user_id} |
Admin: update site owner name/password (role=user) |
| GET | /api/sites |
List all sites |
| POST | /api/sites |
Create new site |
| GET | /api/sites/{site_id} |
Get site details |
| DELETE | /api/sites/{site_id} |
Delete site |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/chat |
Send message (JSON) |
| POST | /api/chat/stream |
Send message (SSE streaming) |
| POST | /api/chat/feedback |
Submit feedback |
| POST | /api/documents/upload |
Upload document |
| GET | /api/documents/{site_id} |
List documents |
| DELETE | /api/documents/{doc_id} |
Delete document |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/crawl |
Start website crawl |
| GET | /api/crawl/status/{site_id} |
Check crawl status |
| GET | /api/sites/{site_id}/crawl-schedule |
Get schedule config |
| PUT | /api/sites/{site_id}/crawl-schedule |
Update schedule |
| POST | /api/sites/{site_id}/crawl-now |
Trigger immediate crawl |
| GET | /api/sites/{site_id}/crawl-history |
Get crawl history |
| GET | /api/sites/{site_id}/crawl-status |
Get current crawl status |
All /api/conversations/* routes require authentication; list/search/detail respect admin vs site-owner vs agent site scope. Agents cannot export or delete.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/conversations |
List conversations (scoped by role) |
| GET | /api/conversations/search |
Search by message content (scoped) |
| GET | /api/conversations/{session_id} |
Get conversation |
| DELETE | /api/conversations/{session_id} |
Delete conversation (not agents) |
| POST | /api/conversations/bulk-delete |
Delete multiple conversations (not agents) |
| POST | /api/conversations/export |
Export conversations (not agents; scoped for non-admins) |
| POST | /api/conversations/auto-close |
Close inactive conversations (admin only) |
| GET | /api/analytics/overview |
Dashboard overview |
| GET | /api/analytics/sites/{site_id} |
Site-specific analytics |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/sites/{site_id}/triggers |
List triggers |
| POST | /api/sites/{site_id}/triggers |
Create trigger |
| PUT | /api/sites/{site_id}/triggers/{id} |
Update trigger |
| DELETE | /api/sites/{site_id}/triggers/{id} |
Delete trigger |
| GET | /api/sites/{site_id}/triggers/analytics |
Trigger analytics |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/handoff |
Create handoff request (re-post while pending bumps visitor queue signal) |
| POST | /api/handoff/{handoff_id}/abandon |
Visitor abandons handoff (session_id in body); public, rate-limited |
| GET | /api/handoff/{id} |
Get handoff status |
| GET | /api/handoff/{id}/messages |
Get messages |
| POST | /api/handoff/{id}/messages |
Send visitor message |
| POST | /api/handoff/{id}/agent-message |
Send agent message |
| PUT | /api/handoff/{id}/status |
Update status (claim/resolve) |
| GET | /api/sites/{site_id}/handoff/queue |
Get agent queue (agents: unassigned + assigned to them) |
| GET | /api/sites/{site_id}/handoff/config |
Get handoff config |
| PUT | /api/sites/{site_id}/handoff/config |
Update handoff config |
Dashboard lead routes require auth and per-site access; agents cannot delete.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/leads |
Capture a new lead (widget) |
| GET | /api/leads/check/{site_id}/{session_id} |
Check if lead exists |
| GET | /api/sites/{site_id}/leads |
List leads (paginated) |
| GET | /api/sites/{site_id}/leads/export |
Export leads as CSV |
| GET | /api/sites/{site_id}/leads/count |
Get total leads count |
| DELETE | /api/leads/{lead_id} |
Delete a lead (not agents) |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/sites/{site_id}/qa |
Create Q&A pair |
| GET | /api/sites/{site_id}/qa |
List Q&A pairs (paginated) |
| GET | /api/sites/{site_id}/qa/stats |
Get Q&A statistics |
| GET | /api/sites/{site_id}/qa/{qa_id} |
Get single Q&A pair |
| PUT | /api/sites/{site_id}/qa/{qa_id} |
Update Q&A pair |
| DELETE | /api/sites/{site_id}/qa/{qa_id} |
Delete Q&A pair |
| POST | /api/sites/{site_id}/qa/from-conversation |
Create from conversation |
| POST | /api/sites/{site_id}/qa/{qa_id}/toggle |
Toggle enabled status |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/platform/whitelabel |
Get white-label config |
| PUT | /api/platform/whitelabel |
Update config (admin) |
| POST | /api/platform/whitelabel/reset |
Reset to defaults (admin) |
Add the chatbot to any website with a single script tag:
<script
src="https://your-domain.com/widget/chatbot.js"
data-site-id="YOUR_SITE_ID"
data-api-url="https://your-domain.com/api"
data-color="#0D9488"
data-title="Chat with us"
data-position="bottom-right">
</script>| Attribute | Description | Default |
|---|---|---|
data-site-id |
Site ID (required) | - |
data-api-url |
Backend API base URL (omit when the page is same-origin with the API; set when the marketing site and API use different hosts) | - |
data-color |
Primary theme color | #0D9488 |
data-title |
Chat header title | Chat with us |
data-welcome |
Welcome message | Hi! How can I help you? |
data-position |
Widget position | bottom-right |
The authoritative widget code lives at frontend/src/widget/chatbot.js. It is part of this repository—commit it like any other source file.
The embeddable script your sites load is generated under frontend/widget/ (chatbot.js is obfuscated for production; chatbot.min.js is a lighter build). Only those built files need to be URL-served to end users; they are produced from src/widget/, not hand-edited.
cd frontend
npm install # First time only
npm run build # Regenerates frontend/widget/chatbot.js and chatbot.min.jsIf npm run build fails with “Source file not found”, frontend/src/widget/chatbot.js is missing from your tree—restore it from git; do not rely on widget/*.js alone as the source of truth.
Before deploying to production, ensure you've completed the following security steps:
# Set to production mode
ENVIRONMENT=production
DEBUG=false# Generate a secure secret
python -c "import secrets; print(secrets.token_hex(32))"
# Set in .env
JWT_SECRET=<generated-64-character-secret># Only allow your specific domains
CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
TRUSTED_HOSTS=yourdomain.com,app.yourdomain.com# Use a strong password (8+ chars, uppercase, lowercase, number)
ADMIN_EMAIL=admin@yourdomain.com
ADMIN_PASSWORD=YourStr0ng!Passw0rd
# Or disable auto-creation and create via API
ADMIN_PASSWORD=Security headers are automatically added in production:
X-Frame-Options: DENY- Prevents clickjackingX-Content-Type-Options: nosniff- Prevents MIME sniffingX-XSS-Protection: 1; mode=block- Enables XSS filteringStrict-Transport-Security- Enforces HTTPS (production only)Content-Security-Policy- Controls resource loadingReferrer-Policy- Controls referrer information
Secure your embeddable chat widget:
Use SRI hashes to ensure the widget script hasn't been tampered with:
<script>
(function() {
var s = document.createElement('script');
s.src = 'https://yourdomain.com/widget/chatbot.js';
s.async = true;
s.integrity = 'sha384-YOUR_SRI_HASH'; // Get from /api/embed/security/{site_id}
s.crossOrigin = 'anonymous';
s.dataset.siteId = 'YOUR_SITE_ID';
s.dataset.apiUrl = 'https://yourdomain.com';
document.head.appendChild(s);
})();
</script>To get your SRI hash:
curl https://yourdomain.com/api/embed/security/YOUR_SITE_IDConfigure widget security in the dashboard under Site Settings → Security:
| Setting | Description |
|---|---|
| Enforce Domain Validation | Only allow widget to load on whitelisted domains |
| Allowed Domains | List of permitted domains (supports wildcards like *.example.com) |
| Require Referrer Header | Reject API requests without a valid Referer header |
| Rate Limit (per session) | Maximum API requests per session per minute (10-200) |
| Secure Embed Code | Copy-ready embed code with SRI hash included |
Restrict where your widget can be embedded:
- Go to your site settings in the dashboard
- Navigate to the "Security" tab
- Add allowed domains (supports wildcards like
*.example.com) - Enable "Enforce domain validation" to reject unauthorized domains
| Endpoint | Description |
|---|---|
GET /api/embed/script/{site_id} |
Get embed code with optional SRI |
GET /api/embed/security/{site_id} |
Get security info (SRI hash, allowed domains) |
- HTTPS: Always use HTTPS in production (configure via reverse proxy)
- Database: Use authentication for MongoDB (
MONGODB_URL=mongodb://user:pass@host:27017) - Secrets: Never commit
.envfiles to version control - Monitoring: Enable logging and set up alerts for security events
- Updates: Keep dependencies updated (
pip install --upgrade)
The project includes 440+ tests across backend, frontend, and end-to-end test suites.
# Backend (pytest)
cd backend && pytest
# Frontend (jest)
cd frontend && npm test
# E2E (playwright)
cd e2e && npm testcd backend
# Run all tests
pytest
# Run by category
pytest tests/unit/ # Unit tests (RAG, crawler, document processing)
pytest tests/integration/ # API endpoint tests
pytest tests/security/ # Security & auth tests
pytest tests/providers/ # Provider & database tests
# Other options
pytest tests/test_auth.py # Specific file
pytest tests/test_auth.py::TestLogin # Specific class
pytest -v # Verbose output
pytest --cov=app --cov-report=html # With coverage reportcd frontend
npm test # Run tests
npm run test:coverage # With coverage
npm run test:watch # Watch modecd e2e
npm install # First time only (also installs browser binaries)
npm test # Run tests
npm run test:ui # Interactive UI mode
npm run test:report # View HTML report| Category | Location | Tests | Description |
|---|---|---|---|
| Unit | backend/tests/unit/ |
120 | RAG engine, crawler, document processor |
| Integration | backend/tests/integration/ |
176 | REST API endpoints |
| Security | backend/tests/security/ |
55 | Auth, JWT, input sanitization, SRI |
| Providers | backend/tests/providers/ |
91 | LLM, embeddings, vector store, database |
| Frontend | frontend/tests/ |
60+ | Widget and dashboard JS functions |
| E2E | e2e/tests/ |
~25 | Full user flows (login, sites, chat) |
| Type | Location | Pattern | Notes |
|---|---|---|---|
| Backend | backend/tests/<category>/ |
test_*.py |
Use fixtures from conftest.py, @pytest.mark.asyncio for async |
| Frontend | frontend/tests/ |
*.test.js |
Use mocks from setup.js |
| E2E | e2e/tests/ |
*.spec.js |
Follow Playwright patterns |
Mock external dependencies (MongoDB, vector store, LLM APIs) in all test types.
MIT License - feel free to use this project for your own purposes.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Built with ❤️ using FastAPI, LangChain, and MongoDB



