Chat Widget Integration

Add an AI-powered chat widget to your website that provides instant, intelligent responses to customer questions. The chat uses RAG (Retrieval-Augmented Generation) to answer based on your uploaded documentation, with streaming responses for a smooth user experience.

What You Get

🤖

AI-Powered Responses

OpenAI-powered chat with context from your knowledge base

📚

Source Citations

AI responses include source references from your knowledge base

Streaming Responses

Real-time SSE streaming for instant, word-by-word responses

🔒

Anonymous Sessions

Short-lived tokens (5-min TTL) with auto-renewal, no login required

📝

Markdown Support

Rich text formatting, code blocks with syntax highlighting

1. Installation

Vanilla JS (CDN): No installation required — just add a script tag!

Svelte/React: The framework components use marked to render Markdown content from AI responses. Install it first:

npm install marked

2. Quick Start (Copy-Paste)

Choose your framework and copy the component directly into your project:

Add the widget to any HTML page with a single script tag — no build step required:

<!-- Add this script tag to your HTML -->
<script src="https://cdn.jsdelivr.net/gh/localhost5173/fleety-components@main/SupportChatWidget.js"></script>

Initialize the widget in the next step!

3. Add to Your Page

Import and use the component anywhere in your application:

Then use it in any page:

<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
</head>
<body>
  <!-- Your page content -->
  
  <!-- Fleety Chat Widget -->
  <script src="https://cdn.jsdelivr.net/gh/localhost5173/fleety-components@main/SupportChatWidget.js"></script>
  <script>
    new SupportChatWidget({
      projectId: 'your-project-id',
      theme: 'fleety',
      dockPosition: 'bottom-right'
    });
  </script>
</body>
</html>

⚠️ Important: Replace your-project-id with your actual project ID from the Fleety dashboard.

💡 Log in to see your personalized integration code with your project ID.

3. Configuration Options

Customize the widget's appearance and behavior:

Prop
Type
Default
Description
projectId
string
required
Your Fleety project ID
theme
string
'fleety'
'fleety' | 'material' | 'nord' | 'light' | 'dark' | 'system'
dockPosition
string
'bottom-right'
'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'

Example with custom configuration:

<SupportChatWidget 
  projectId="your-project-id"
  theme="midnight"
  dockPosition="bottom-left"
/>

How It Works

1

Session Initialization

When a user opens the chat, the widget calls https://api.fleety.dev/v1/init-session with your project ID and receives a short-lived anonymous token (5-minute TTL).

2

Auto Token Renewal

The token automatically renews after 4 minutes (before expiration) in the background. Users never notice interruptions.

3

Message Sending

User messages are sent to https://api.fleety.dev/v1/chat with the anonymous token and full conversation history for context.

4

RAG + AI Response

Fleety retrieves relevant chunks from your knowledge base, injects them as context, and streams the OpenAI response back in real-time.

Advanced: Custom Authentication

💡 Project ID Usage

Fleety project IDs are designed for frontend integration. You can safely use them in client-side code for fast, simple implementation. However, be aware:

  • Token usage: Malicious actors could potentially drain your Fleety tokens by using your exposed project ID
  • Risk level: For most small-to-medium apps, this risk is quite low and the convenience outweighs the concern
  • Mitigation: Use the "Allowed Origins" feature to restrict which domains can use your project ID

For high-traffic production apps: Consider calling the Fleety API from your backend server instead. Store your project ID as an environment variable and proxy requests through your server to have full control over usage.

By default, the chat works for anyone (anonymous sessions). If you want to restrict access to logged-in users only:

<script>
  import SupportChatWidget from '$lib/components/SupportChatWidget.svelte';
  import { user } from '$lib/stores/auth'; // Your auth store
</script>

{#if $user}
  <SupportChatWidget projectId="your-project-id" />
{:else}
  <p>Please log in to access support</p>
{/if}

💡 Tip: You can also modify the component to send user context (like email or user ID) to your backend for tracking who uses support.

Advanced: Component Customization

Since you have the full component source, you can customize it however you like:

🎨 Styling

Modify colors, fonts, sizes in the <style> section to match your brand.

💬 Messages

Change welcome messages, placeholder text, error messages to fit your tone.

🔧 Behavior

Add custom analytics, modify token renewal logic, or integrate with your monitoring tools.

📊 Tracking

Add event tracking for user interactions, message sending, or error occurrences.

API Endpoints Used

POST
https://api.fleety.dev/v1/init-session

Initialize anonymous chat session

View Request
{
  "project_id": "your-project-id"
}
POST
https://api.fleety.dev/v1/chat

Send chat message with conversation history (SSE streaming)

View Request
{
  "messages": [
    { "role": "user", "content": "Hello" },
    { "role": "assistant", "content": "Hi! How can I help?" },
    { "role": "user", "content": "What are your prices?" }
  ]
}

Headers:
Authorization: Bearer <anonymous-token>
View Response (SSE)
event: sources
data: [{"file_name":"PRICING.md","score":0.92,"section":1,"description":"Part 1 of Pricing Information"}]

data: {"content": "Our "}
data: {"content": "pricing "}
data: {"content": "starts at..."}
data: [DONE]
POST
https://api.fleety.dev/v1/chat/tools

Chat with tool calling support (ticket creation) - JSON response

View Request
{
  "prompt": "I need help with login issues"
}

Headers:
Authorization: Bearer <anonymous-token>
View Response (JSON)
{
  "type": "message",
  "message": "I can help with login issues...",
  "sources": [
    {
      "file_name": "LOGIN_GUIDE.md",
      "score": 0.92,
      "section": 2,
      "description": "Part 2 of Login Guide"
    }
  ]
}

📚 Source Citations

When the AI uses information from your knowledge base to answer a question, it automatically includes source citations showing which documents were referenced. The AI intelligently selects only the sources it actually used, filtering out irrelevant matches.

How it works: The RAG (Retrieval-Augmented Generation) system searches your uploaded documents, finds relevant content, and provides it to the AI. The AI then explicitly indicates which sources it actually referenced, ensuring only useful citations are shown.

What You'll See

Source citations appear as a list below AI responses, showing:

  • Human-readable description — Intelligently formatted based on document type (e.g., "Part 2 of Terms of Service", "FAQ", "API Documentation")
  • Relevance score — How well the content matched the question (0.0 - 1.0)
  • Section reference — Which part of the document was used
  • AI-filtered — Only sources the AI actually used appear, no irrelevant results

Example AI response with sources:

You can request a refund within 30 days of purchase. Simply contact our support team with your order number...

Sources:
Part 1 of Refund Policy (score: 0.92)
Part 3 of Terms of Service (score: 0.85)

Benefits

  • Transparency — Users can see where the AI's information comes from
  • Trust — Citations build confidence in the AI's responses
  • Verification — Users can verify information against your original documents
  • Smart Filtering — AI only shows sources it actually used, no noise
  • Auto-formatting — Source names are automatically cleaned up (e.g., "TOS.md" → "Terms of Service")
  • Debugging — Quickly identify which documents need updates if information is outdated

✨ Pro Tip: Organize your knowledge base documents with clear, descriptive filenames. This makes source citations more meaningful to users (e.g., "pricing-faq.md" instead of "doc1.md").

For Developers

Source citations are automatically handled by the official widgets. If you're building a custom implementation:

// SSE Streaming (/v1/chat)
const eventSource = new EventSource('/v1/chat');

eventSource.addEventListener('sources', (e) => {
  const sources = JSON.parse(e.data);
  // Display sources: array of { file_name, score, section, description }
  displaySources(sources);
});

// JSON Response (/v1/chat/tools)
const response = await fetch('/v1/chat/tools', {
  method: 'POST',
  body: JSON.stringify({ prompt: userMessage })
});
const data = await response.json();
if (data.sources) {
  // Display sources if present
  displaySources(data.sources);
}