Project ·
Gorgi - Site Widget Assistant
Multi-tenant AI chat platform on Cloudflare's edge — grounded retrieval, quota gates before AI spend, and a tiny style-isolated widget.
Gorgi is an embeddable AI support widget for websites. A business can create a site, add its own knowledge sources, customize the chat experience, test answers in a dashboard, and install the assistant with one script tag. The interesting part is not just the chat UI — it is the full product loop behind it: tenant isolation, grounded retrieval, usage limits, dashboard operations, and a widget small enough to drop into an existing site without taking over the page.
At a glance
- Role: Sole engineer across product scope, architecture, API, dashboard, widget, data model, and test strategy.
- Scope: Multi-tenant chat platform with public widget config, public chat, dashboard management, knowledge sources, appearance settings, usage tracking, and test chat.
- Stack: Cloudflare Workers, Hono, D1, Drizzle, Cloudflare AI Search, Workers AI, React, Vite, Tailwind, TypeScript, Vitest.
- Status: Working MVP before launch operations hardening.
- Proof: One-line Shadow DOM widget around 4.6 kB gzipped, tenant-scoped retrieval, quota checks before billable AI calls, and backend tests against real Workers/D1 bindings.
The problem
Small businesses want the benefit of an AI assistant without building a support platform or trusting a generic chatbot to invent answers. The assistant needs to answer from the company’s real content, stay easy to install, and avoid surprise AI costs.
- Integration friction: The customer should not need a framework plugin, custom frontend work, or a long implementation project just to add chat.
- Trust and tenant boundaries: Answers must be grounded in the current site’s sources, not another customer’s content or model guesswork.
- Cost and abuse risk: Public chat endpoints can be spammed, so usage limits need to run before retrieval or generation spend.
The goal: build the smallest complete SaaS loop where a client can configure a site, add knowledge, embed one script, and get controlled, grounded answers from Cloudflare’s edge.
The solution
Gorgi combines a tiny embeddable widget with a dashboard and a single Worker API. The product is designed around the operational path a real customer would need, not just a demo chat box.
- Embeddable chat widget — a dependency-free script renders inside Shadow DOM so host-page CSS cannot break the assistant. It loads public site settings, sends visitor questions, and renders escaped text responses safely.
- Client dashboard — a React/Vite admin app lets a client manage sites, knowledge sources, appearance, embed code, usage, and test conversations before installing the widget publicly.
- Grounded chat API — a Hono Worker validates origin, checks quota, retrieves tenant-scoped context from Cloudflare AI Search, and asks Workers AI for a short answer grounded in those chunks.
- Operational guardrails — daily, monthly, and per-IP limits live in D1 so public requests are gated before expensive AI calls.
Technical overview
Frontend — The dashboard is a React SPA built with Vite and Tailwind. It covers authentication, site settings, source management, appearance controls, usage visibility, embed-code copy, and test chat. The public widget is separate: vanilla TypeScript compiled to a small IIFE, style-isolated with Shadow DOM.
Backend/API — A single Cloudflare Worker hosts the Hono app. It serves the dashboard API, public widget configuration, public chat, source management, usage, and auth routes. Dashboard sessions use password hashing and signed session tokens without pulling in a separate auth service.
Data layer — D1 stores clients, sites, settings, sessions, sources, usage
counters, chat messages, and fallback/insight data. Drizzle keeps SQL access
structured. Cloudflare AI Search owns ingestion and retrieval, with metadata
filters keyed by site_instance_id so queries only see the active tenant’s
content.
Infrastructure — The system is split into deployable workspace apps:
apps/api for the Worker API, apps/dashboard for the admin SPA,
apps/widget for the embeddable script, and packages/shared for constants and
shared TypeScript contracts.
Reliability/security — The public chat route is ordered deliberately: validate site and origin, apply quota limits, retrieve context, generate an answer, then store the transcript. If no relevant context exists, the API can return a configured fallback instead of spending on generation. The widget renders plain escaped text rather than raw HTML.
How it works
- A client creates a site in the dashboard and adds knowledge sources.
- The dashboard/API stores metadata in D1 and sends source content to Cloudflare AI Search with the site’s tenant identifier.
- The client copies a script tag containing a public site key onto their website.
- The widget loads public settings, opens a style-isolated chat UI, and sends visitor questions to the public chat endpoint.
- The Worker verifies the request origin, checks daily/monthly/IP quota, fetches relevant chunks with a tenant filter, generates a grounded answer with Workers AI, records the transcript, and returns a safe text response.
Key decisions
Gate cost before intelligence
The chat pipeline checks origin and quota before retrieval or generation. That means abusive traffic is rejected while the request is still cheap. The trade-off is a little more state management in D1, but it makes spend predictable enough for an MVP that exposes a public endpoint.
Keep the widget boring on purpose
The widget is vanilla TypeScript instead of React. That choice avoids shipping a framework into someone else’s website, keeps the bundle small, and reduces CSS conflicts. Shadow DOM gives the widget its own styling boundary while still allowing theme settings from the dashboard.
Use managed retrieval, own the product logic
Instead of building a vector database and ingestion system, Gorgi uses Cloudflare AI Search for indexing and retrieval. The app owns the important product rules — tenants, sites, quotas, prompts, source metadata, transcripts, and dashboard workflows — while the platform handles the search substrate.
One Worker for the MVP
The dashboard API, public config, and public chat endpoints live in one Hono app. Separate services would give more isolation later, but one Worker made the MVP easier to deploy, test, and reason about while route boundaries kept the code organized.
Challenges
- Making AI answers trustworthy: The API has to prefer grounded answers over confident guesses. Retrieval is tenant-filtered, prompts constrain the model to supplied context, and fallback paths handle weak or missing context.
- Designing for hostile public traffic: The widget endpoint is public by design, so origin checks, quota counters, IP-hour limits, and escaped rendering are part of the core flow rather than afterthoughts.
- Balancing MVP speed with SaaS shape: Gorgi needed real product surfaces — auth, settings, source management, usage, test chat, embed code — without turning into an enterprise support platform before the core loop was proven.
Outcome
Gorgi demonstrates a complete Cloudflare-native AI product loop: a customer can configure a site, add knowledge, test the assistant, copy one script tag, and let visitors ask questions grounded in that site’s content.
- A multi-tenant Worker API coordinates dashboard routes, public config, public chat, auth, quotas, retrieval, generation, and transcripts.
- The widget stays genuinely embeddable: tiny, dependency-free, style-isolated, and safe to render on arbitrary customer pages.
- Cost and abuse controls are built into the request order instead of bolted on after launch.
- The codebase is organized as a monorepo with shared contracts and verification coverage for API, dashboard, and widget behavior.
What I would improve next
- Add stronger response trust features: citations in the widget, answer feedback, and clearer source diagnostics for customers.
- Expand ingestion beyond the MVP paths with better website crawling, retries, and source health states.
- Add production billing/provisioning flows and AI Gateway spend routing.
- Improve onboarding with a guided install checklist and a live preview of widget appearance before copying the script.
Have a similar system to build?
Send the product goal, timeline, and current blockers. I’ll help you turn it into a practical build plan.
Start a conversation