Last updated: 2026-08-20 · Repo: portfolio-chatbot-widget
Self-hosted RAG FAQ chatbot: embeddable widget, Redis vector search, SSE streaming, multi-provider AI fallbacks.
npm install
cp .env.example .env.local # UPSTASH, GEMINI, HF, SEED_SECRET
npm run dev
curl -X POST http://localhost:3000/api/seed -H "Authorization: Bearer $SEED_SECRET"| Route | Method | Auth | Runtime |
|---|---|---|---|
/api/chat |
POST | Session cookie | Edge |
/api/history |
GET, DELETE | Session cookie | Edge |
/api/seed |
POST | SEED_SECRET header |
Node |
/api/feedback |
POST | None | Edge |
- Client →
POST /api/chat(Zod{ message }) - RAG embed + cosine search → Redis FAQ vectors
- LLM SSE stream → client
- Persist
chat:session:{id}in Redis
- Single key:
chatHistoryQueryKey=["chat-history"]inlib/query-keys.ts - Send: optimistic user msg → stream →
setQueryData - Clear: optimistic empty →
DELETE /api/history→ rollback on error - Settings:
widget-settings-context+ localStorage (not server CRUD) - No global densify mesh — only one server data domain (chat history); appropriate for widget scope
lib/auth/seed-auth.ts # timing-safe SEED_SECRET
lib/session-cookie.ts # chatbot_session helpers
lib/api/cors.ts # embed CORS (reflect Origin — allowlist Wave 2)
lib/schemas.ts # Zod chat + feedback
lib/redis.ts # get/save/deleteSession, vectors
hooks/use-chat.ts # chat hook + mutations
public/widget.js # vanilla embed + DELETE clear
| Done | Deferred (Wave 2+) |
|---|---|
| Seed secret auth | HTTP rate limiting |
| HttpOnly session cookie | Production CORS allowlist |
| Sentry + tunnel + quiet build | JWT / user auth |
| Security headers + robots | SHA session encryption |
| Zod chat/feedback | Zod seed/history |
NEXT_TELEMETRY_DISABLED=1in build script- Sentry:
silent: true,telemetry: false,deleteSourcemapsAfterUpload .npmrcfund=false ·allowScriptswhitelist · browserslist postinstall- See
docs/VERCEL_PRODUCTION_GUARDRAILS.md§8, Sentry guide Step 6b
Bot Protection may 429 cold curl. Use browser DevTools fetch('/api/seed', …) or visit site then curl. README § Production re-seed.
- Vercel env:
.env.example+SEED_SECRET - Deploy → reseed (README methods)
NEXT_PUBLIC_CHATBOT_URL- Firewall: Bot Challenge, AI Bots Deny
- Smoke: chat, clear + refresh, Sentry
.agile-v/STATE.md → CLAUDE.md → this file → source code.