Documentation Index
Fetch the complete documentation index at: https://mintlify.com/farrugiag/open-chat-widget/llms.txt
Use this file to discover all available pages before exploring further.
Architecture Overview
Open Chat Widget is a full-stack application built with modern technologies. This guide explains how each component works and how they communicate.System Diagram
Components
1. Chat Widget (Frontend)
Location:widget/src/index.ts
Technology: Vanilla TypeScript compiled to a single JavaScript bundle
Purpose: Embeddable UI that website visitors interact with
The widget is framework-agnostic and works on any website - WordPress, React, Vue, plain HTML, etc.
Key Features
- Self-contained: Single
chat-widget.jsfile with no dependencies - Configurable: Read options from
data-*attributes on the script tag - Session management: Generates and stores unique session IDs in localStorage
- Streaming support: Processes NDJSON responses token-by-token
- Responsive design: Adapts to mobile and desktop screens
- State persistence: Remembers open/closed state across page reloads
Configuration
The widget reads configuration from the script tag:widget/src/index.ts
Build Process
The widget is built with esbuild for maximum performance:widget/esbuild.config.mjs
2. Backend API (Server)
Location:backend/src/server.ts
Technology: Node.js with Express framework
Purpose: Process chat requests, manage OpenAI streaming, and enforce security
Core Responsibilities
AuthenticationValidates API keys using timing-safe comparison
Rate LimitingTracks requests by IP address (30/min default)
CORS ProtectionConfigurable origin allowlist
Widget ServingDelivers compiled JavaScript bundle
Request Flow
When a user sends a chat message:API Endpoints
The backend exposes these routes:| Method | Path | Purpose | Auth |
|---|---|---|---|
GET | /health | Health check | None |
GET | /widget/chat-widget.js | Widget bundle | None |
GET | /v1/openapi.json | OpenAPI spec | None |
POST | /chat | Streaming chat (legacy) | Widget API key |
POST | /v1/chat | Non-streaming chat | Widget API key |
POST | /v1/chat/stream | Streaming chat | Widget API key |
GET | /v1/admin/conversations | List conversations | Admin API key |
GET | /v1/admin/conversations/:id | Get conversation thread | Admin API key |
Security Features
Rate Limiting
Rate Limiting
Implemented per IP address in
backend/src/server.ts:105-120:API Key Validation
API Key Validation
Uses timing-safe comparison to prevent timing attacks:
backend/src/server.ts:122-131
CORS Configuration
CORS Configuration
Configurable origin allowlist with production safety:
backend/src/server.ts:67-75
Security Headers
Security Headers
Added to every response:
backend/src/server.ts:350-359
3. Convex Database
Location:convex/schema.ts, convex/conversations.ts
Technology: Convex (serverless real-time database)
Purpose: Store and query conversations and messages
Convex provides reactive queries, automatic scaling, and built-in TypeScript support.
Schema
Two tables with indexes for efficient queries:convex/schema.ts
Key Functions
4. Admin Dashboard
Location:dashboard/
Technology: Next.js 15 with React Server Components
Purpose: View and manage conversations
Features
- Password authentication: Simple login with
DASHBOARD_PASSWORD - Conversation list: Sorted by most recent activity
- Thread viewer: See full message history for each session
- Responsive design: Works on desktop and mobile
Key Pages
- Login Page
- Conversation List
- Thread Viewer
dashboard/app/login/page.tsx
/loginAuthentication Flow
dashboard/lib/auth.ts
Data Flow Example
Let’s trace a complete user interaction:User opens chat widget
- Widget loads from
http://localhost:4000/widget/chat-widget.js - Creates or retrieves
sessionIdfrom localStorage:"a1b2c3d4-..." - Displays welcome message
Backend processes request
- Validates API key: ✓
- Checks rate limit: ✓
- Queries Convex: Find or create conversation for
sessionId - Stores user message in Convex
- Fetches last 20 messages for context
OpenAI generates response
- Backend sends conversation history to OpenAI
- OpenAI streams tokens:
"Our"," support"," hours", … - Backend forwards each token as NDJSON:
Widget displays response
- Receives NDJSON stream
- Shows typing indicator (“Thinking…”)
- Appends each token in real-time
- Displays final message: “Our support hours are 9am-5pm EST.”
Backend stores response
- Saves assistant message to Convex
- Updates conversation’s
updatedAttimestamp - Updates
lastMessagepreview
Tech Stack Summary
Frontend
- Widget: Vanilla TypeScript → esbuild → single bundle
- Dashboard: Next.js 15, React Server Components, Tailwind CSS
Backend
- API Server: Node.js 20+, Express, TypeScript
- Validation: Zod schemas
- HTTP Client: Native
fetchAPI
Database
- Convex: Real-time serverless database
- Tables:
conversations,messages - Indexes: Optimized for session and timestamp queries
AI
- Provider: OpenAI
- Model: GPT-4-turbo-mini (configurable)
- Streaming: Server-sent events (SSE) → NDJSON
DevOps
- Build: npm workspaces, concurrent dev mode
- Deployment: Docker, Docker Compose
- Hosting: Compatible with Railway, Render, Vercel, Fly.io
Performance Considerations
Widget Bundle Size~15KB gzipped. No dependencies. Loads async with
defer.Streaming ResponsesToken-by-token delivery feels instant. First token typically arrives in under 500ms.
Convex QueriesIndexed lookups are ~10-50ms. Reactive subscriptions update in real-time.
Rate LimitingIn-memory buckets prevent abuse. No database queries for rate checks.
Deployment Architecture
Recommended setup for production:Each component scales independently. The widget is served as a static file. The backend is stateless and can run multiple instances behind a load balancer.
Next Steps
Deploy to Production
Learn how to deploy each component to cloud providers
API Reference
Complete endpoint documentation with examples
Customization Guide
Customize widget appearance, colors, and positioning
Security Best Practices
Harden your deployment and protect user data