Jeremy Chat Widget

Embeddable conversational AI for your website

Try Live Demo Get Started

✨ Want to see Jeremy in action? → Try the live demo

Quick Install

Embed Jeremy with a single line of code. The widget injects itself, loads all styles and assets, and connects to your API endpoint.

HTML

Add this to your page where you want the chat widget to appear (usually before </body>):

<script src="https://jeremy-chat-bot.pages.dev/jeremy.js" data-api="/api/chat" data-orchid-path="orchid/"></script>

Script Attributes

Attribute Required Default Description
data-api No /api/chat API endpoint path for chat requests. Must return {"reply": "..."}
data-orchid-path No ./orchid/ Base path to orchid video directory. Videos: orchid-greeting.webm, orchid-idle.webm, orchid-responding.webm, orchid-bow.webm

Example with Custom Paths

<script 
  src="https://cdn.example.com/v1/jeremy.js" 
  data-api="https://api.example.com/v1/chat"
  data-orchid-path="https://cdn.example.com/assets/orchid/"
></script>

CSS Customization

Jeremy exposes CSS custom properties so you can easily match your brand. Define these in your page's <style> or external CSS before loading jeremy.js.

Color & Branding

:root {
  --jeremy-blue: #0483ca;        /* Primary brand color */
  --jeremy-blue-dark: #036ba5;     /* Hover/active state */
  --jeremy-font: 'Lora', Georgia, serif;  /* Body text */
  --jeremy-heading-font: 'Marcellus SC', serif; /* Headers */
}

Layout & Dimensions

:root {
  --jeremy-panel-width: 380px;      /* Chat panel width */
  --jeremy-panel-height: 580px;    /* Chat panel height */
  --jeremy-orchid-height: 220px;   /* Orchid video area height */
  --jeremy-toggle-size: 60px;      /* Chat toggle button size */
  --jeremy-border-radius: 12px;     /* Border radius */
}

Example: Custom Brand Colors

:root {
  --jeremy-blue: #ff6b35;        /* Your brand orange */
  --jeremy-blue-dark: #e05a2d;    /* Darker shade */
  --jeremy-font: 'Inter', sans-serif; /* Your font */
}

All CSS is scoped with #jeremy- ID and class prefixes to prevent conflicts with your page's styles.

Jeremy & the Orchid

The orchid is Jeremy's animated mascot character. It appears at the top of the chat panel and responds with different animations as you chat.

Orchid States

Customizing the Orchid Area

You can control the orchid display size and background with CSS:

:root {
  --jeremy-orchid-height: 180px; /* Smaller on mobile */
}

The orchid video files must be WebM format. Place them in your orchid/ directory:

Chat Window

The chat panel is fully customizable. Control colors, fonts, sizing, and more with CSS custom properties.

Message Bubbles

Element CSS Class Description
User message .jeremy-msg-user Right-aligned, primary blue background
Assistant message .jeremy-msg-assistant Left-aligned, light gray background
Typing indicator .jeremy-typing Animated three-dot animation

Session Persistence

Chat history is automatically saved to sessionStorage. When a user refreshes the page, their conversation is preserved. Each browser session gets a unique session_id sent to your API for tracking and logging.

CTA Tracking

When a user clicks a link (Calendly booking, phone number, etc.) within a chat message, the widget automatically marks it as cta_clicked: true and sends this flag to your API.

API Configuration

Jeremy communicates with your backend API endpoint. By default, it uses /api/chat, but you can customize this with the data-api attribute.

Hosted Endpoints

Jeremy's API is hosted at:

EndpointMethodDescription
https://jeremy-chat-bot.pages.dev/api/chat POST Main chat endpoint — send messages, receive AI replies
https://jeremy-chat-bot.pages.dev/demo GET Live interactive demo
https://jeremy-chat-bot.pages.dev/jeremy.js GET Embeddable widget script

API Request Format

POST https://jeremy-chat-bot.pages.dev/api/chat

{
  "messages": [
    { "role": "user", "content": "Hello!" },
    { "role": "assistant", "content": "Hi there!" }
  ],
  "session_id": "uuid-here",
  "cta_clicked": false
}

API Response Format

{
  "reply": "Your response text here. Can include HTML <a> tags.",
  "session_id": "uuid-here"
}

Response Notes

Error Handling

If your API returns an error or the request fails, Jeremy displays a fallback message. Make sure your API is accessible from the client's browser (handle CORS appropriately).

Environment Variables

Jeremy's backend requires several environment variables. These are configured in Cloudflare Pages (for the API functions) and in wrangler.toml (for D1 and KV bindings).

Required Secrets (Cloudflare Pages Dashboard)

Set these as environment secrets in your Cloudflare Pages project settings under Settings → Environment → Production/Preview:

OPENAI_API_KEY

Your OpenAI API key for language detection and translation.

sk-proj-xxxxxxxxxxxxx

ANTHROPIC_API_KEY

Your Anthropic API key for Claude AI chat responses.

sk-ant-xxxxxxxxxxxxx

CALENDLY_TOKEN

Your Calendly API token for scheduling appointments (optional but recommended).

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

ALLOWED_ORIGIN

CORS allowed origin (e.g., your website domain). Defaults to * if not set.

https://yourdomain.com

D1 & KV Bindings (wrangler.toml)

Configure these bindings in your wrangler.toml file. The API code references these as env.DB and env.RATE_LIMIT:

# D1 Database binding
[[d1_databases]]
binding = "DB"
database_name = "jeremy-chat"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# KV namespace binding for rate limiting
[[kv_namespaces]]
binding = "RATE_LIMIT"
id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
preview_id = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"

.env.example Template

Reference file for developers:

# OpenAI API (language detection & translation)
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxx

# Anthropic API (Claude AI responses)
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxx

# Calendly API (appointment scheduling, optional)
CALENDLY_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# CORS allowed origin (defaults to * if not set)
ALLOWED_ORIGIN=https://yourdomain.com

# D1 & KV bindings are configured in wrangler.toml, not here
# D1 binding: env.DB
# KV binding: env.RATE_LIMIT

Setup Instructions

  1. Get API keys: Sign up for OpenAI and Anthropic, create API keys.
  2. Cloudflare Pages: In your project settings, add the secrets as environment variables.
  3. D1 Database: Create a D1 database in Cloudflare, update wrangler.toml with the ID.
  4. KV Namespace: Create a KV namespace, update wrangler.toml.
  5. Deploy: Push your code and Cloudflare will automatically load the secrets and bindings.