Skip to main content

Quickstart Guide

This guide will get you from zero to a working chat widget in under 5 minutes.

Prerequisites

Before you begin, make sure you have:
New to Convex? Sign up takes 30 seconds with GitHub auth. Create a new project after signing in.

Installation

1

Clone and install dependencies

git clone https://github.com/your-org/open-chat-widget.git
cd open-chat-widget
npm install
This installs all dependencies for the backend, dashboard, and widget workspaces.
2

Configure environment variables

Copy the example environment file:
cp .env.example .env
Edit .env with your credentials:
.env
# Convex
CONVEX_URL=https://your-deployment.convex.cloud

# OpenAI
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4.1-mini

# Widget backend
WIDGET_API_KEY=change-me-widget-key
ADMIN_API_KEY=change-me-admin-api-key
PORT=4000
CORS_ORIGIN=http://localhost:3000
WIDGET_BUNDLE_PATH=../widget/dist/chat-widget.js
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=30

# Dashboard
DASHBOARD_PASSWORD=change-me-admin-password
NEXT_PUBLIC_BACKEND_URL=http://localhost:4000
NEXT_PUBLIC_WIDGET_SCRIPT_URL=http://localhost:4000/widget/chat-widget.js
Security: Change WIDGET_API_KEY, ADMIN_API_KEY, and DASHBOARD_PASSWORD to strong random values before deploying to production.

Getting your Convex URL

Run npx convex dev once to create a dev deployment. Convex will display your URL:
npx convex dev
# Output: https://happy-animal-123.convex.cloud
Copy this URL to CONVEX_URL in your .env file.
3

Generate Convex types

Generate TypeScript types from your Convex schema:
npm run codegen
This creates type definitions in convex/_generated/ used by the backend.
4

Start Convex development server

In a terminal window, start Convex:
npm run dev:convex
Keep this running. Convex will sync your schema and functions to the cloud.
Convex provides the real-time database that stores conversations and messages.
5

Start all services

In a new terminal window, start the backend, dashboard, and widget:
npm run dev
This command runs:
  • Backend API on http://localhost:4000
  • Dashboard on http://localhost:3000
  • Widget builder (watches for changes)
Wait for all services to start. You should see:
Backend listening on http://localhost:4000
Dashboard ready on http://localhost:3000
Widget compiled successfully

Test the Widget

Now that everything is running, let’s test the chat widget.

Option 1: Built-in Test Page

Open the test page included with the dashboard:
http://localhost:3000/widget-test.html
You should see:
  • A chat button in the bottom-right corner
  • Click to open the chat panel
  • Type a message and get an AI response
The test page demonstrates the widget with default styling. Try asking: “What can you help me with?”

Option 2: Embed in Your Own Page

Create a simple HTML file to test the widget:
test-chat.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Chat Widget Test</title>
</head>
<body>
  <h1>Welcome to My Site</h1>
  <p>This is a test page with the chat widget.</p>
  
  <!-- Chat Widget -->
  <script
    src="http://localhost:4000/widget/chat-widget.js"
    data-api-url="http://localhost:4000/chat"
    data-api-key="change-me-widget-key"
    data-title="Support"
    data-welcome-message="Hey! How can I help?"
    data-input-placeholder="Type your question..."
    data-position="right"
    data-accent-color="#0ea5e9"
    defer
  ></script>
</body>
</html>
Open this file in your browser. The widget should appear and work immediately.
The data-api-key must match WIDGET_API_KEY from your .env file.

View Conversations in Dashboard

After sending a few test messages:
1

Open the dashboard

Navigate to http://localhost:3000
2

Log in

Enter the password from DASHBOARD_PASSWORD in your .env file (default: change-me-admin-password)
3

Browse conversations

You’ll see a list of all chat sessions, sorted by most recent activity. Click any conversation to view the full message thread.

Customize the Widget

The widget accepts these data attributes:
AttributeDescriptionDefault
data-api-urlBackend chat endpointRequired
data-api-keyWidget API keyRequired
data-titleHeader text"Assistant"
data-welcome-messageFirst message shown"Hi! Ask me anything..."
data-input-placeholderInput field placeholder"Type your message..."
data-position"left" or "right""right"
data-accent-colorPrimary color (hex)"#0ea5e9"

Example: Custom Branding

<script
  src="http://localhost:4000/widget/chat-widget.js"
  data-api-url="http://localhost:4000/chat"
  data-api-key="your-api-key"
  data-title="Acme Support"
  data-welcome-message="Welcome to Acme! How can we help you today?"
  data-input-placeholder="Describe your issue..."
  data-position="left"
  data-accent-color="#7c3aed"
  defer
></script>

Test the Headless API

Prefer to build your own UI? Test the REST endpoints:
curl -X POST http://localhost:4000/v1/chat \
  -H "Content-Type: application/json" \
  -H "x-api-key: change-me-widget-key" \
  -d '{
    "sessionId": "test-session-123",
    "message": "Hello, what can you do?"
  }'
The streaming endpoint returns NDJSON events:
{"type":"start","conversationId":"j57abc123..."}
{"type":"token","token":"I"}
{"type":"token","token":" can"}
{"type":"token","token":" help"}
{"type":"done","message":"I can help with...","conversationId":"j57abc123..."}

Next Steps

Learn the Architecture

Understand how Convex, Express, and the widget communicate

Deploy to Production

Deploy the backend, dashboard, and Convex to cloud providers

API Reference

Complete reference for all chat and admin endpoints

Customize the Widget

Customize widget appearance, colors, and positioning

Troubleshooting

Check these common issues:
  • Verify backend is running: curl http://localhost:4000/health
  • Check browser console for JavaScript errors
  • Confirm the script URL is correct: http://localhost:4000/widget/chat-widget.js
  • Ensure data-api-url and data-api-key attributes are set
The data-api-key attribute must match WIDGET_API_KEY in your .env file.Double-check:
# In .env
WIDGET_API_KEY=your-secret-key

# In HTML
data-api-key="your-secret-key"
Make sure:
  • npm run dev:convex is running in a separate terminal
  • CONVEX_URL in .env matches the URL shown in Convex dev output
  • You’ve run npm run codegen to generate types
Verify DASHBOARD_PASSWORD in .env. The login uses this exact value.If you recently changed it, restart the dashboard:
# Stop dev command (Ctrl+C), then restart
npm run dev
The backend limits requests by IP address. Default: 30 requests per minute.Adjust in .env:
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=100
Important: Never commit your .env file to version control. It contains sensitive API keys and passwords.

Build docs developers (and LLMs) love