Skip to content

Chat Architecture

Two separate chat experiences exist: a static site chat (dumb, no auth) and a portal chat (AI-powered, auth required).


1. Static Site Chat (Dumb)

Purpose: SEO-friendly landing page with a simple Q&A widget. No AI, no login.

How it works:

  • Business publishes a static site via POST /api/site/publish (Firebase Function)
  • template.ts renders index.html + sub-pages as pure HTML/CSS/JS
  • QA data is generated at publish time from the business knowledge base and baked into the HTML as <script type="application/json" id="chat-qa-data">
  • Client-side JS does fuzzy pattern matching (bigram similarity) against the baked QA data — zero API calls
  • Fallback answer links users to the portal for full AI chat

Hosting: GCS bucket humanlike-sites{uid}/index.html, {uid}/{slug}.htmlURL: https://storage.googleapis.com/humanlike-sites/{uid}/index.htmlAuth: None Firebase SDK: None AI: None — pattern matching only Runtime cost: Zero (static file serving)

Files:

  • functions/src/site/template.ts — HTML generation (landing page, sub-pages)
  • functions/src/site/generate-qa.ts — QA generation from knowledge base (at publish time)
  • functions/src/site/storage.ts — GCS upload
  • functions/src/site/index.ts — Express routes: preview, publish, unpublish, import

Chat button in navbar: Links to portal (https://app.humanlike.world/portal/{slug}) for full AI chat.


2. Portal Chat (AI-powered)

Purpose: Full conversational AI chat. Requires sign-in. Talks to our API, uses tools (calendar, etc).

How it works:

  • User visits https://app.humanlike.world/portal/{slug}
  • React app resolves slug → business via GET /api/portal/resolve?slug=X (Cloud Run API)
  • User signs in (Google OAuth or email/password via Firebase Auth)
  • On sign-in, portal sets visitor custom claim and writes to visitors/{uid}/businesses/{bizId} in Firestore
  • ChatGPT component fetches system prompt (GET /api/portal/prompt) and tool definitions (GET /api/portal/tools)
  • Messages sent to POST /api/chat (OpenAI Chat Completions with streaming)
  • Tool calls executed via POST /api/portal/tools (server-side, same tool registry as phone)
  • On unmount, interaction logged via POST /api/portal/interaction → Firestore businesses/{bizId}/interactions
  • Chat history persisted in localStorage per business

Hosting: Firebase Hosting (React SPA) Route: /portal/:slugPortal.tsxAuth: Firebase Auth (Google OAuth + email/password) Firebase SDK: Auth only (for sign-in + ID tokens). Firestore used server-side only. AI: OpenAI Chat Completions API (via our Cloud Run proxy) Runtime cost: OpenAI API usage per message

Files:

  • web/src/components/Portal.tsx — Portal page: slug resolution, auth gate, layout shell, interaction logging
  • web/src/components/ChatGPT.tsx — Reusable chat component: streaming, tool calls, message display
  • web/src/components/TexterHome.tsx — "Your Chats" page: lists businesses the visitor has chatted with
  • services/api/serve.js — API endpoints: /api/portal/resolve, /api/portal/prompt, /api/portal/tools, /api/portal/interaction, /api/chat

Comparison

AspectStatic Site ChatPortal Chat
Auth requiredNoYes (Firebase Auth)
AINo (pattern matching)Yes (OpenAI Chat API)
Tools (calendar, etc)NoYes
Firebase SDK in clientNoAuth only
Firestore reads at runtimeNoYes (server-side via API)
SEO crawlableYesNo (SPA, auth-gated)
HostingGCS (static files)Firebase Hosting (React)
Runtime costZeroOpenAI API per message
Chat historyNone (stateless)localStorage + Firestore interaction log
Conversation depthSingle Q&A turnMulti-turn with context

Flow: Static Site → Portal

  1. Visitor lands on static site (SEO, shared link, etc.)
  2. Uses dumb chat for basic questions (hours, location, services)
  3. For deeper questions, clicks "Chat" button in navbar → opens portal in new tab
  4. Signs in → full AI chat with tool access (booking, lookups, etc.)
  5. Interaction logged to business dashboard

Last updated: