SiteChat: AI support for your website
SiteChat is a SaaS product I built for website owners who want AI chat that actually knows their content, and a real inbox when a human needs to step in. Drop in one script tag and it works on WordPress, WooCommerce, Shopify, Next.js, or plain HTML. The main focus is online stores: product questions, policies, and (soon) live order lookup without sending shoppers elsewhere.
- Live: sitechat.live
- Intro video: Loom walkthrough
Problem
Most chatbot widgets sound generic and leave the merchant stuck when a customer needs a person. Store owners want answers grounded in their own docs and catalog, plus the usual live-chat habits: email when a new chat starts, stop the bot, take over, reply as staff. Doing that with five separate tools is painful.
Solution
Everything sits in one monorepo. Visitors use a small embeddable widget. Merchants use a React dashboard. Both talk to the main TypeScript API (apps/api on Bun + Hono) for auth, chat, billing, inbox, and webhooks.
Auth is Better Auth with Drizzle. The web dashboard uses HttpOnly session cookies. JWT Bearer tokens are there for the planned mobile app so the same API works without cookies.
Retrieval lives in a separate FastAPI service: crawl, chunk, embed, and search with pgvector. The Bun API never talks to the vector index itself. Celery and Redis handle background ingestion. Postgres stores workspaces, messages, and embeddings.
A visitor message goes widget → Bun API chat → FastAPI search → LLM stream (SSE), then the thread is saved. When a new session starts, the merchant gets an email with a deep link into the inbox, where they can stop the AI, take over, or reply as staff. For stores, an intent classifier (Phase 2) will send FAQ and policy questions to RAG, and order or stock questions to live WooCommerce.
Impact
- A full product surface: widget, knowledge sources, streaming chat, operator inbox, and usage-based billing.
- TypeScript owns the main product API; Python owns the ML pipeline. They share one database schema and a hard API-key boundary.
- Runs on Docker / Dokploy. LLM providers are swappable. Billing uses an internal ledger with Stripe or offline PH payments.
Lessons learned
- Keep one main API boundary. Otherwise the SPA and FastAPI each grow into their own mini CRM.
- Human takeover has to be designed in from day one: alerts, handling modes, and an inbox API that future channels can reuse.
- Writing the architecture first, then implementing against it, kept a multi-runtime monorepo shippable instead of stuck in endless scaffolding.
Tech stack
- Dashboard: Vite, React, TanStack Query, Zustand, shadcn/ui, Tailwind
- API: Bun, Hono, Better Auth (session cookies for web; JWT for planned mobile), Drizzle ORM, Zod
- RAG: FastAPI, Celery, Redis, Postgres + pgvector, Gemini embeddings
- LLMs: Gemini / OpenAI / Anthropic (env-configured)
- Billing & storage: Internal ledger + Stripe (optional), Cloudflare R2
- Deploy: Docker Compose, Dokploy
Screenshots
Marketing / product
