Open-source AI chatbot platform — train on your business knowledge, embed anywhere.
Current main: PRD Phases 0-4 are implemented as an open platform foundation: verified publishing, service operations and handoff, enterprise governance, versioned APIs/SCIM, multilingual and channel contracts, templates, reviewed plugins, and stable-session experiments. Self-hostable, bring-your-own-key, and MIT licensed. Live deployment: open-chat1.vercel.app.
OpenBusinessChat lets a business create a custom AI chatbot grounded in its own knowledge and embed it on a website with a single line of code. Retrieval thresholds and refusal controls reduce unsupported answers without pretending that any LLM can guarantee zero hallucinations.
- Upload knowledge — PDFs, Word docs, TXT, CSV, Markdown, website URLs, YouTube transcripts, manual text
- Take action with tools — call your APIs, look up orders, create tickets, send emails — your bot decides when to use them
- RAG-grounded answers — pgvector retrieval, configurable strictness, source citations
- Embed anywhere —
<iframe>or one-line<script>widget - Capture leads from chat — optional visitor follow-up form plus a dashboard lead inbox
- Bring your own AI — OpenAI, Anthropic, Google Gemini, Groq, or local Ollama (with primary + fallback chain)
- Multi-tenant — each business workspace has its own bots, knowledge, and API keys
- Production-oriented foundation — TypeScript end-to-end, Prisma + PostgreSQL, tenant isolation, secure auth, and abuse-protection hooks
| Feature | Status |
|---|---|
| Email/password auth (JWT + bcrypt, httpOnly cookies) | ✅ |
| Google OAuth (verified email, CSRF state, account linking) | ✅ |
| Multi-tenant data model (User → Workspace → Bot → KnowledgeSource → Document → DocumentChunk) | ✅ |
| PostgreSQL + pgvector with prepared migrations | ✅ |
| Admin dashboard (workspace selector, bot CRUD, settings) | ✅ |
| Per-workspace AI provider config (OpenAI / Anthropic / Gemini / Groq / Ollama) | ✅ |
| AES-256-GCM encrypted workspace provider keys and tool headers | ✅ |
| Primary + fallback provider chain with auto-failover | ✅ |
| Curated model catalog with "Auto (recommended)" defaults | ✅ |
| File upload (PDF with local scanned-page OCR, DOCX, TXT, MD, CSV — up to 10 MB) | ✅ |
| Website crawler (same-origin depth/page/path limits, noise stripping, scheduled refresh) | ✅ |
| YouTube transcript extraction | ✅ |
| Manual text knowledge entry | ✅ |
| Sliding-window chunking + batched embeddings | ✅ |
| RAG retrieval over pgvector cosine similarity | ✅ |
| Three answer modes: Strict / Balanced / Flexible | ✅ |
| Configurable fallback behavior + contact info | ✅ |
| Auto-generated starter questions from your knowledge | ✅ |
| Animated suggestion bubbles in the chat widget | ✅ |
| Lead capture form + dashboard lead inbox | ✅ |
| Admin chat preview with grounding badges + source citations | ✅ |
Public iframe embed (/embed/{publicKey}) |
✅ |
Drop-in <script> widget (widget.js) — floating chat bubble |
✅ |
| Conversation logs viewer | ✅ |
| Analytics: totals, unknown-answer rate, top user questions | ✅ |
Platform-owner /admin dashboard: signups, activation, installs, usage, ingestion, tool, and security metrics |
✅ |
| Animated end-to-end flow demo on the landing page | ✅ |
| Agentic tools — bot calls HTTP APIs via function-calling (OpenAI + Anthropic) | ✅ |
| Tool execution log with input/output, latency, status per invocation | ✅ |
| Approval-required tool actions — review, reject, approve, and execute from the existing tool log | ✅ |
| Persistent ingestion job records with retry/error lifecycle | ✅ |
| Guided launch readiness with required and recommended checks | ✅ |
| Draft settings, immutable publish versions, and rollback | ✅ |
| Per-bot evaluation datasets with publish quality gates | ✅ |
| Extraction preview, source ownership, tags, freshness, conflicts, and citation controls | ✅ |
| Verified starter questions, public citations, answer feedback, and knowledge-gap inbox | ✅ |
| Widget AI disclosure, privacy notice, origin restrictions, and offline states | ✅ |
| Quality analytics: evidence coverage, feedback, latency, refusals, and gaps | ✅ |
| Shared service workflow: escalation, packets, assignment, notes, priority, business hours, and SLA | ✅ |
| Signed/idempotent webhook delivery with logs, retries, and helpdesk/CRM contract | ✅ |
| Risk-tiered tool test console with immutable test executions | ✅ |
| Outcome, containment, action, provider/model, token, and estimated-cost analytics | ✅ |
Workspace roles/invitations, scoped service accounts, stable /api/v1, and SCIM |
✅ |
| Environments, policy, domains, retention/privacy jobs, and audit export | ✅ |
| Locale-aware chat/evaluations, channels, templates, plugin manifest, and experiments | ✅ |
| MIT licensed, fully self-hostable | ✅ |
- Node.js 20.9+
- Docker Desktop (for local Postgres with pgvector)
- An OpenAI API key for cloud embeddings, or a local Ollama model that supports embeddings. Anthropic, Gemini, and Groq chat currently use OpenAI for embeddings.
# 1. Clone
git clone https://github.com/Hemang-ai/OpenChat.git
cd OpenChat
# 2. Install dependencies
npm install
# 3. Configure environment
cp .env.example .env
# Open .env and set:
# DATABASE_URL (the docker-compose default already matches)
# JWT_SECRET (any random 32+ char string)
# APP_URL (http://localhost:3000)
# OPENAI_API_KEY (your sk-... key, unless using Ollama)
# 4. Start Postgres + pgvector
docker compose up -d postgres
# 5. Run migrations
npx prisma generate
npm run db:deploy
# 6. Start the dev server
npm run devOpen http://localhost:3000.
- Register with Google or email/password → an account + workspace are created
- AI Settings → paste your OpenAI API key, click Save
- Dashboard → + New bot → choose a workflow template and create an unpublished draft
- Bot → Knowledge → add business content, inspect extraction, and approve any conflict or freshness warnings
- Bot → Evaluations → add at least three launch questions with expected facts or expected refusals, then run the suite
- Bot → Preview → test the same draft answer path with full evidence traces
- Bot → Settings / Embed → add human fallback, privacy notice, and approved website origins
- Bot → Launch → resolve required checks and publish an immutable version
- Bot → Embed → copy the
<iframe>or<script>snippet into an approved website
Published visitors stay on the last known-good version while settings or knowledge changes remain in draft. Rollback creates a new immutable version from an earlier snapshot, preserving the audit trail.
The platform-owner dashboard is separate from customer workspaces at /admin. It shows signups, activation, bots, verified embeds, conversations, leads, ingestion health, tool activity, and recorded security events.
After running the latest migrations, create the one-time local administrator. The username defaults to admin; do not place a real password in Git or .env.example.
# Generate a durable workspace encryption key first.
openssl rand -base64 32
# Put the resulting value in WORKSPACE_SECRETS_KEY in your uncommitted .env.
# Set a unique 15+ character PLATFORM_ADMIN_INITIAL_PASSWORD in .env, then:
npm run admin:bootstrapSign in using the configured email or admin, open http://localhost:3000/admin, and replace the bootstrap password when prompted. Bootstrap can only create the first platform administrator.
To protect existing workspace keys after setting WORKSPACE_SECRETS_KEY, run:
npm run secrets:migrateKnowledge submissions run immediately for a responsive dashboard experience and are also recorded as durable jobs. For a production worker, set a strong INGESTION_WORKER_SECRET and invoke the protected endpoint from a queue consumer or scheduler:
curl -X POST "$APP_URL/api/internal/ingestion-jobs" \
-H "Authorization: Bearer $INGESTION_WORKER_SECRET"The worker processes every source type, including uploaded files. Development stores uploads under ignored .data/uploads; production uses the configured private S3-compatible bucket, so retries survive deployments and request timeouts.
Run webhook and governance maintenance workers on the same schedule (five minutes recommended):
curl -X POST "$APP_URL/api/internal/webhooks" -H "Authorization: Bearer $WEBHOOK_WORKER_SECRET"
curl -X POST "$APP_URL/api/internal/maintenance" -H "Authorization: Bearer $MAINTENANCE_WORKER_SECRET"See Production Operations for SLOs, backup/restore, migration, worker, and rollback procedures.
OpenBusinessChat now includes a built-in lead capture workflow so the bot can turn anonymous website conversations into follow-up opportunities.
Many business chatbots answer questions but lose the visitor when the conversation ends. Lead capture closes that gap: after a visitor engages with the embedded chat, the widget can invite them to leave contact details for a human follow-up. This makes the product more valuable for agencies, service businesses, sales teams, clinics, local businesses, and any company that wants support conversations to become pipeline.
When lead capture is enabled for a bot:
- The visitor asks a question in the public iframe or script widget.
- The chat shows a compact Human follow-up card after the first real user message.
- The visitor can submit name, email, phone, company, and a short request.
- The widget confirms that the details were sent.
The form is intentionally optional and appears after engagement, so the bot still feels helpful before it asks for contact information.
Inside Dashboard → Bot → Settings, turn on Lead capture and customize the prompt shown in the widget.
Inside Dashboard → Bot → Leads, owners can:
- View captured leads with email, phone, company, request, and the latest related chat question.
- Filter by status: New, Contacted, Qualified, or Dismissed.
- Update status from the lead inbox.
- Track lead totals, new leads, and qualified leads.
Lead counts also appear in bot cards and analytics, including lead conversion rate from conversations to captured leads.
Lead capture adds:
Leadmodel withNEW,CONTACTED,QUALIFIED, andDISMISSEDstatuses.- Bot settings:
leadCaptureEnabledandleadCapturePrompt. - Public endpoint:
POST /api/public/leads. - Admin endpoint:
GET/PATCH /api/admin/bots/{botId}/leads. - Migration:
prisma/migrations/20260528120000_add_lead_capture.
After pulling the latest main, run:
npx prisma generate
npm run db:deploy- Frontend: Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Lucide icons
- Backend: Next.js Route Handlers, Node.js runtime
- Database: PostgreSQL 16 with pgvector extension (cosine similarity)
- ORM: Prisma 5
- AI: OpenAI / Anthropic / Google Gemini / Groq / Ollama via a unified provider abstraction
- Auth: Google OAuth or email/password, with JWT sessions in httpOnly cookies
- Validation: Zod
- PDF parsing: pdf-parse v2; DOCX: mammoth; HTML: cheerio; YouTube: youtube-transcript
┌──────────────────────────┐
Customer (browser) │ Public widget / iframe │
│ /embed/{publicKey} │
└────────────┬─────────────┘
│ POST /api/public/chat
│ POST /api/public/leads
▼
┌────────────────────────────────────────────────────────────┐
│ Next.js (App Router) │
│ │
│ /api/public/chat ──► RAG ──► retrieve chunks (pgvector) │
│ │ ──► LLM + optional tool loop │
│ ▼ │
│ grounding check, source citations │
│ │
│ /api/public/leads ──► validated lead capture │
│ │
│ /api/auth/google ──► Google OAuth + local JWT session │
│ /api/admin/* ──► auth-guarded admin endpoints │
│ /dashboard/* ──► admin UI, analytics, lead inbox │
└────────────────────────────────────────────────────────────┘
│
┌─────────────────┴─────────────────┐
▼ ▼
PostgreSQL + pgvector Workspace AI provider
(User, OAuthAccount, (OpenAI / Anthropic /
Workspace, Bot, Tool,
KnowledgeSource, Document, Gemini / Groq / Ollama)
DocumentChunk[vector],
Conversation, Message,
Lead)
app/
(marketing)/ Landing page + animated demo
(dashboard)/ Admin UI (workspace, bots, AI settings)
api/auth/ Email/password + Google OAuth, logout
api/admin/ Workspace + bot CRUD, knowledge, evaluations, launch/versioning,
analytics, gaps, leads, logs, and tools
api/public/ Chat, citations, feedback, leads, and verified embed events
embed/[publicKey]/ Iframe-embeddable chat widget
login/, register/ Auth pages
components/
ui/ shadcn/ui design system
chat/ Public-facing chat widget, lead form, suggestion bubbles
dashboard/ Tabs: launch, knowledge, evaluations, preview, embed,
analytics, gaps, leads, logs, tools, and settings
marketing/ Landing animations (FlowAnimation, DashboardMockup)
lib/
agents/ Tool-calling loop, HTTP execution, execution records
ai/ Provider abstraction + curated model catalog
auth/ JWT, bcrypt, and Google OAuth helpers
db/ Prisma client singleton
bots/ Draft config, readiness, publish/version, rollback, origin policy
evaluations/ Deterministic launch evaluation runner
ingestion/ Chunker, quality checks, jobs, and pipeline orchestrator
loaders/ PDF/OCR, DOCX, crawler, YouTube, and incremental Google Drive contract
rag/ Chat, retrieval, verified suggestions, and knowledge gaps
security/ Rate limiting, audit events, safe fetch, encrypted secrets
utils/ Zod helpers, classnames, toast
prisma/
schema.prisma All models
migrations/ Prepared migrations covering full schema
public/
widget.js Drop-in script widget
scripts/seed.ts Optional seed script
types/index.ts Shared TypeScript types
# Core application
DATABASE_URL="postgresql://postgres:password@localhost:5432/openbusinesschat?schema=public"
JWT_SECRET="your-32-char-random-secret"
APP_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000"
WORKSPACE_SECRETS_KEY="" # 32-byte base64 or 64-character hex; required for encrypted workspace secrets
AUDIT_HASH_SALT="" # optional, separate privacy salt for audit/event identifiers
# Google sign-in (optional)
GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="your-client-secret"
# AI defaults (workspace settings override these)
LLM_PROVIDER="openai" # openai | anthropic | gemini | groq | ollama
LLM_FALLBACK_PROVIDER=""
OPENAI_API_KEY="sk-..." # embeddings for OpenAI/Anthropic/Gemini/Groq
OPENAI_MODEL="gpt-4o-mini"
OPENAI_EMBEDDING_MODEL="text-embedding-3-small"
ANTHROPIC_API_KEY=""
ANTHROPIC_MODEL=""
GEMINI_API_KEY=""
GEMINI_MODEL=""
GROQ_API_KEY=""
GROQ_MODEL=""
OLLAMA_BASE_URL="http://localhost:11434"
OLLAMA_MODEL=""
# Uploads and public API protection
MAX_FILE_SIZE_MB="10"
OBJECT_STORAGE_BUCKET="" # required in production; S3, R2, MinIO, or compatible
OBJECT_STORAGE_REGION="auto"
OBJECT_STORAGE_ENDPOINT="" # required for R2/MinIO; omit for AWS S3
OBJECT_STORAGE_ACCESS_KEY_ID=""
OBJECT_STORAGE_SECRET_ACCESS_KEY=""
OBJECT_STORAGE_FORCE_PATH_STYLE="false"
UPSTASH_REDIS_REST_URL=""
UPSTASH_REDIS_REST_TOKEN=""
PUBLIC_CHAT_RATE_LIMIT_REQUESTS="30"
PUBLIC_CHAT_RATE_LIMIT_WINDOW_SECONDS="60"
RATE_LIMIT_FAIL_OPEN="false"
# One-time platform admin bootstrap. Keep the real password only in a secret manager or local .env.
PLATFORM_ADMIN_USERNAME="admin"
PLATFORM_ADMIN_EMAIL="admin@localhost"
PLATFORM_ADMIN_INITIAL_PASSWORD=""
INGESTION_WORKER_SECRET=""
WEBHOOK_WORKER_SECRET=""
MAINTENANCE_WORKER_SECRET=""Workspace-level settings (entered via the dashboard) always override these defaults.
Create a Web application OAuth client in Google Cloud.
Authorized JavaScript origins:
http://localhost:3000
https://YOUR_DOMAIN
Authorized redirect URIs:
http://localhost:3000/api/auth/google/callback
https://YOUR_DOMAIN/api/auth/google/callback
Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env locally and in your deployment environment. Never commit the downloaded Google credential JSON file.
The callback must match exactly, including scheme, hostname, port, path, and trailing slash. Adding only a JavaScript origin causes Google error 400: redirect_uri_mismatch. After saving changes in Google Cloud, allow a few minutes for propagation.
- Database: Provision Neon from the Vercel Marketplace or use another PostgreSQL host with pgvector. The initial migration enables the
vectorextension. - Core secrets: Set
JWT_SECRET,APP_URL,NEXT_PUBLIC_APP_URL,WORKSPACE_SECRETS_KEY, and preferablyAUDIT_HASH_SALTin Vercel. A Neon Marketplace connection suppliesDATABASE_URLautomatically. - Private uploads: Attach an S3-compatible private bucket and set the
OBJECT_STORAGE_*variables. Uploaded documents are encrypted at rest, tenant-scoped, and read by retryable ingestion workers. - Google login: Set
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRET, then add the exact production callback in Google Cloud. - Public chat rate limiting: Upstash Redis is recommended for distributed enforcement. Without it, the app uses a bounded per-instance limiter so public chat remains available. Set
RATE_LIMIT_REQUIRE_DISTRIBUTED=trueif your deployment must fail closed when Redis is absent.RATE_LIMIT_FAIL_OPEN=trueapplies only when a configured Redis service becomes unavailable. - Apply migrations: From a trusted CI job or a machine with the production
DATABASE_URL, runnpm run db:deploy. Apply this before the Vercel deployment so the running application always sees the expected schema. - Deploy: Vercel runs
npm run build, which generates Prisma and builds Next.js without coupling the build to a live database connection. - Configure authenticated five-minute jobs for
/api/internal/ingestion-jobs,/api/internal/webhooks, and/api/internal/maintenance. - Visit
/api/health, then test registration, bot creation, ingestion, preview, publish/promotion, public embed, handoff, webhook delivery,/adminauthorization, service API, and a tool approval separately.
The reference deployment uses Vercel at open-chat1.vercel.app with a Vercel Marketplace Neon database.
Serverless ingestion: uploads are written to private S3-compatible storage before a durable ingestion job is executed. The same persisted job can be retried by
/api/internal/ingestion-jobsafter a timeout or deployment. Development uses the ignored local object store; production deliberately fails upload setup when no private bucket is configured.
docker compose up -d # brings up Postgres
npm run build && npm start # serves on :3000A production Dockerfile is included for one-shot containerization if you prefer that.
- The Next.js
proxy.tsperforms an early session redirect, while every admin route handler and server page independently revalidates authorization and tenant ownership. - Google OAuth uses a short-lived state cookie, verifies Google ID tokens and verified email addresses, and links provider identities through
OAuthAccountrather than storing OAuth users with fake passwords. - Public chat endpoints (
/api/public/*and/embed/*) only accept a bot'spublicKey— internal IDs are never exposed. - Public lead submissions are validated, rate-limited, and only accepted when lead capture is enabled for an active bot.
- Published widgets enforce configured website origins for chat, lead, and telemetry requests. Empty origin lists remain available for local setup and must be tightened before production launch.
- Published bot versions pin both settings and approved source IDs. Draft knowledge changes do not affect visitor retrieval until publish; rollback restores the selected settings and source snapshot.
- Per-workspace provider keys and new tool headers are AES-256-GCM encrypted with
WORKSPACE_SECRETS_KEY, never returned to the client, and masked in UI. After deploying the migration, runnpm run secrets:migrateto encrypt legacy workspace keys and clear their plaintext fields. - File uploads are extension/MIME/signature checked, size-capped (default 10 MB), stored in tenant-scoped private object storage, and removed with their source lifecycle.
- Website ingestion validates every redirect target, blocks local/private network addresses, and caps pages at 5 MB to reduce SSRF and memory-abuse risk.
- Public chat and lead endpoints support distributed Upstash rate limiting and use a bounded per-instance fallback when Redis is not configured.
/adminis separate from/dashboardand requires a platform role checked in route handlers and server components. The bootstrap administrator must change its password before accessing platform metrics.- The platform dashboard uses aggregate records and privacy-minimized embed events. It never exposes provider keys or raw customer content by default.
- Google client secrets and downloaded
client_secret_*.jsonfiles must never be committed. Rotate any credential exposed in chat, screenshots, logs, or public history. - Tenant isolation: workspace ownership and membership are server-scoped; governance changes require Admin/Owner access, service identities require explicit scopes, and platform roles remain separate.
- Organization policy can restrict providers/models, external tools, production promotion, retention, region, and customer-managed key references.
- See Trust Center, Plugin Manifest, and Production Operations.
Run npm run verify before opening a pull request. GitHub Actions repeats Prisma validation, type-checking, lint, authorization/upload safety tests, production build, high-severity dependency blocking, and CycloneDX SBOM generation.
The core contracts for the original four phases are present. Next releases focus on production adapters and certification evidence rather than duplicate product flows:
- Durable object storage, malware scanning, isolated OCR worker, and queue adapters for large/high-volume files (local inline OCR covers the first 10 scanned PDF pages)
- Google Drive incremental sync and reviewed Slack/Teams/WhatsApp channel packages
- Certified OIDC/SAML profiles, passkeys/MFA, managed KMS adapters, and regional deployment evidence
- Community security review and signed distribution for plugin/template catalog entries
- Statistical experiment reporting, locale benchmark packs, and human-agent response assist
- Managed cloud billing, white-label domains, advanced moderation, legal hold, and sector profiles
We welcome contributions! See CONTRIBUTING.md for the workflow. Quick version:
- Fork the repo
- Branch off
main - Make your change with a clear commit message
- Open a pull request
MIT — see LICENSE. Free to use, modify, and ship commercially.
Built with Next.js, Prisma, pgvector, and shadcn/ui. Inspired by the broader RAG community (LangChain, LlamaIndex, ChatGPT-style assistants) but designed to be a self-contained, focused product for non-technical business owners.