Bolnee-Chat: Chatbot-integratie voor zakelijke websites

Waarom Bolnee-Chat?

Self-Hosted & Voor Altijd Gratis

Geen vendor lock-in en geen facturatie per bericht. Draai het op je eigen server, Vercel of Cloudflare Pages. Er is geen externe database nodig, aangezien SQLite wordt gebruikt.

RAG-gebaseerde Antwoorden

Het systeem scant je website en importeert PDF-, TXT-, MD- en DOCX-bestanden. Deze worden opgesplitst in SQLite FTS (Full Text Search) om gefundeerde prompts te bouwen. Bronnen worden geciteerd en de fallback-opties zijn configureerbaar.

2-regelige Embed, voor elke Stack

Kopieer window.BotConfig en chatbot-widget.js en plak deze vóór de </body> tag. Het werkt op elke website; accentkleuren, thema's en begroetingen zijn live aanpasbaar via het dashboard.

Alle Functies

Bot Overzicht — Statistieken & Snippet

Per bot beschikbaar: live status, aantal berichten/gebruikers, creatiedatum, aantal bronnen en de embed-snippet (inclusief botName, avatar, chatUrl, accent, greeting en theme).

Uiterlijk — Live Preview

Bewerk de botnaam, avatar (upload/preview), accent- en achtergrondkleuren, thema (licht/donker/automatisch) en de begroeting. Wijzigingen zijn direct zichtbaar in de live preview en worden opgeslagen via PATCH /api/chatbots/:id.

Chats — Gegroepeerd per Bezoeker

Chats zijn chronologisch gegroepeerd per visitorId (op basis van IP) en datum. Functies om te verversen en te downloaden als CSV (Excel), JSON of PDF (print). Actieve sessies worden gedefinieerd als unieke bezoekers in de laatste 5 minuten.

Instellingen — Provider, Prompts en Danger Zone

Configuratie van provider, model, baseUrl en apiKey. Daarnaast instellingen voor het standaardbericht (vóór de eerste interactie) en het fallback-bericht (wanneer geen bronnen overeenkomen). Bevat tevens de mogelijkheid om de bot, chats, bronnen en chunks te verwijderen.

Widget — Zwevend, Thema-bewust en Persistent

Een bubble rechtsonder die opent in een schuifvenster (360×520, 75vh op mobiel). De header bevat het accent en de avatar. De widget beschikt over:

  • Typing-indicatoren.
  • SSE (Server-Sent Events) streaming.
  • Vermelding van bronnen.
  • VISITOR_ID en geschiedenis in localStorage, zodat de begroeting slechts één keer verschijnt en chats behouden blijven na het sluiten en openen.
  • Thema's: licht/donker/automatisch (#0f172a / #fff).

Aanvullende functionaliteiten

  • Kennisbeheer: Overzichten van locator, type, status, fouten en datum, inclusief de mogelijkheid om bronnen te verwijderen of nieuwe toe te voegen.
  • Avatar-opslag: Data-URL's worden geconverteerd naar /api/public/avatar/:id (limiet 2MB, opgeslagen in data/avatars/).
  • Versleutelde provider-sleutels: API-sleutels, baseUrl en model per bot worden versleuteld via AES-256-GCM en worden nooit blootgesteld in de snippet.
  • Dark-mode console: Interface met #020617 achtergrond, #1e293b kaarten en slate-800 inputs.

Workflow

  1. Chatbot maken: Voer naam en avatar in (PNG/JPG/WEBP ≤2MB). De avatar wordt opgeslagen als /api/public/avatar/:id en getoond in de widget-header.
  2. Kennis toevoegen: Voeg URL's toe, bestanden uploaden of beide. De same-origin crawler (crawler/crawler.py) respecteert robots.txt, extraheert h1/h2/p/li, verwijdert duplicaten en slaat data op in data/{chatbotId}_website.json. Statusverloop: queuedcrawlingparsingindexingindexed.
  3. Provider configureren: Kies een provider → Base URL wordt automatisch ingevuld → plak de API-sleutel. De lijst met modellen kan live worden opgehaald (prioriteit voor :free bij OpenRouter). Sleutels worden versleuteld opgeslagen (AES-256-GCM).
  4. Embedden: Kopieer de code vanuit het Overzicht of de Kennis-sectie. De origin wordt automatisch geconfigureerd via window.location.origin; de widget wordt geladen via chatbot-widget.js met SSE streaming.

Vereisten

VereisteDetails
BesturingssysteemmacOS, Linux, Windows (WSL)
RuntimeNode.js 18+
Package Managernpm
Python3.10+ (voor crawler, optioneel maar aanbevolen)
Python Dependenciesaiohttp, beautifulsoup4, lxml, requests, brotli (+ playwright voor JS-zware sites)

Installatie

# Clone
git clone https://github.com/AniketWathore/bolnee-chat.git
cd bolnee-chat

# Env
cp .env.example .env
# Bewerk .env — voor eenvoudige self-hosted setup:
# DISABLE_AUTH=true
# JWT_SECRET=vervang-mij-door-32-tekens
# LLM_BASE_URL=https://openrouter.ai/api/v1   # optionele globale fallback
# LLM_API_KEY=sk-or-v1-...                     # optionele globale fallback
# LLM_MODEL=inclusionai/ling-3.0-flash-fin:free

# Install
npm install

# Python crawler deps (optioneel)
pip install aiohttp beautifulsoup4 lxml requests brotli

# Verify
npm run lint    # tsc --noEmit
npm run build   # vite + esbuild → dist/
npm run dev     # http://localhost:3000 (auto-fallback naar 3001 als bezet)

SQLite wordt aangemaakt op data/bolnee.db. Gescande websites worden opgeslagen in data/{chatbotId}_website.json en chunks in SQLite.

Gebruik — Dashboard Flow

  1. Maak chatbot: + New chatbot → naam + avatar (preview ≤2MB).
  2. Voeg kennis toe: Voer https://jouw-site.com in en/of upload PDF/TXT/MD/DOCX/FAQ → status queuedindexed.
  3. Configureer provider: Kies provider → Fetch models → kies model → Save. Sleutels zijn versleuteld.
  4. Embed: Kopieer de snippet uit het Overzicht:
<script>
window.BotConfig = {
  botName: "Customer Bot",
  avatar: "https://jouw-domein/api/public/avatar/BOT_ID",
  chatUrl: "https://jouw-domein/api/public/chat/BOT_ID",
  accentColor: "#111111",
  greeting: "Hoi! Hoe kan ik helpen?",
  theme: "dark"
};
</script>
<script src="https://jouw-domein/chatbot-widget.js" async></script>

Plak dit vóór </body>. De widget slaat VISITOR_ID en chatgeschiedenis op in localStorage.

Referentie Bot-console

TabFunctionaliteit
OverviewLive status, berichten/gebruikers/bronnen, kopieer embed code
AppearanceNaam/avatar/accent/thema/begroeting + live preview
ChatsGegroepeerd per bezoeker → datum, CSV/JSON/PDF export, Refresh
KnowledgeBronnen + wizard voor het toevoegen van kennis
SettingsProvider/model/baseUrl/apiKey, defaultMessage/fallbackMessage, Danger zone verwijderen

API Referentie

MethodePadBeschrijving
POST/api/chatbotsBot aanmaken
GET/api/chatbotsLijst met bots ophalen
PATCH/api/chatbots/:idUiterlijk + provider aanpassen
GET/api/chatbots/:id/appearanceUiterlijk ophalen
GET/api/chatbots/:id/messages?limit=200Gegroepeerde berichten
GET/api/chatbots/:id/statsTotaal / gebruikers
GET`/api/chatbots/:id/messages/export?format=csv\json`Exporteren
GET/api/knowledge/sources?chatbotId=IDLijst met bronnen
POST/api/knowledge/sources/:chatbotIdURL ({url}) of bestand (multipart) toevoegen → queued
DELETE/api/knowledge/sources/:sourceId?chatbotId=IDBron + chunks verwijderen
POST/api/public/chat/:chatbotIdSSE chat {message, visitorId} → data: {token\error\sources} + data: [DONE]
GET/api/public/knowledge/:chatbotIdPublieke kennis (gecached)
GET/api/public/avatar/:chatbotIdAvatar bestand of redirect
POST/api/providers/modelsLijst met modellen voor provider/baseUrl/apiKey
GET/api/statsGlobale totalMessages/activeSessions

Streaming: public/chatbot-widget.js:311 leest SSE via getReader(), met fallback naar text() + SW bypass voor vergrendelde streams. Bezoekersgroepering gebeurt via X-Visitor-Id (VISITOR_ID in localStorage).

Bestandsreferentie

PadRol
server.tsExpress + Vite dev, auth (DISABLE_AUTH), ingestie, RAG, SSE chat
server/db.tsSQLite (better-sqlite3) — chatbots/sources/chunks/messages, getChatbotAppearance
server/ingestion.ts + crawler/runcrawlerfor_bolnee.pyCrawl → /data/{id}_website.json → chunks
crawler/crawler.pySame-origin crawl, robots.txt, h1/h2/p/li extractie, sitemap + homepage
public/chatbot-widget.jsEmbedbare widget — BotConfig.chatUrl, accent, greeting, theme, VISITOR_ID, history
src/components/ChatbotDashboard.tsxTabs: overview/appearance/chats/knowledge/settings, embedCode met thema
src/components/KnowledgeSection.tsx4-staps wizard: Knowledge → Provider → Processing (polls status) → Embed
src/components/Overview.tsxStatistieken + grid van 4 bots + View all
src/components/BotCreationWizard.tsxNaam + avatar upload (2MB limiet)
src/index.cssDark-mode tokens (--color-bg #020617, --color-card #1e293b)
vercel.json / wrangler.tomlHosting rewrites, bucket = "./dist", DISABLE_AUTH

Hosting

Het dashboard is volledig API-driven (/api/* relatief) en configureert automatisch window.location.origin voor embed-URL's.

Vercel

  1. Omgevingsvariabelen instellen: DISABLEAUTH=true (JWTSECRET niet vereist in simple mode).
  2. vercel.json is reeds geconfigureerd voor rewrites (/api/:path/api, /(.)/index.html, outputDirectory: dist).
  3. Uitvoeren: npm run build && vercel --prod.

Cloudflare Pages / Workers

  1. wrangler.toml: bucket = "./dist", DISABLE_AUTH=true.
  2. Uitvoeren: npm run build en wrangler pages deploy dist (of npx wrangler deploy).

Het chat-eindpunt streamt SSE; gebruik voor externe sites de publieke https:// chatUrl (niet localhost).

Configuratie

EnvBeschrijvingStandaard
DISABLEAUTH / VITEDISABLE_AUTHGeen login nodig voor console (single-tenant)false
JWT_SECRETSleutel voor auth signing (16+ tekens, vereist voor productie)development-secret-change-me
LLMBASEURL / OPENROUTERAPIKEY / NVIDIAAPIKEYGlobale provider fallback (instellingen per bot hebben voorrang)
LLMAPIKEYGlobale API-sleutel fallback
LLM_MODELGlobaal model fallback (bijv. openai/gpt-4o-mini)gpt-4o-mini
PORTServer poort (automatische fallback +1 als bezet)3000

Probleemoplossing

SymptoomOplossing
Poort 3000 in gebruik → 3001 en embed faalt op externe siteEmbed gebruikt window.location.origin; regenereer na restart of deploy naar publieke URL.
getReader locked / ReadableStream lockedUpdate public/sw.js naar v3 om POST /api/public/chat over te slaan; hard-refresh voor update.
Model 404 / 402Gebruik Fetch models → kies :free (bijv. inclusionai/ling-3.0-flash-fin:free) of voeg credits toe.
404 knowledge/avatarControleer of data/bolnee.db bestaat en of bot-id overeenkomt met data/{id}_website.json.
Avatar te grootPNG/JPG/WEBP $\le$2MB; data-URL's worden automatisch geconverteerd naar /api/public/avatar/:id.
Begroeting herhaalt zich bij openen/sluitenOpgelost in public/chatbot-widget.js:115 via saveHistory/loadHistory in localStorage; wis bolneemsgs* om te resetten.

Controlelijst voor Verificatie

  • [ ] npm run lint (geen TypeScript-fouten).
  • [ ] npm run build (genereert dist/).
  • [ ] npm run dev (beschikbaar op http://localhost:3000).
  • [ ] Handmatige check:
  • Bot maken → avatar preview → Uiterlijk opslaan → preview update.
  • Kennis toevoegen: URL + PDF → status queuedindexed.
  • Provider → Fetch models → kies :free → Opslaan.
  • Overzicht → Kopieer embed → plakken in HTML → widget laadt, begroeting verschijnt één keer, geschiedenis blijft behouden, thema's functioneren correct.
  • Chats → gegroepeerd per bezoeker → CSV/JSON/PDF export.
  • Instellingen → default/fallback berichten → Chat zonder bronnen geeft fallback-antwoord.

Licentie

Gedistribueerd onder de MIT-licentie. Zie LICENSE voor meer informatie.