Skip to main content

πŸ€– ActionBot

AI-powered support assistant for SaaS applications. Handles action-oriented customer queries securely.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Chat Widget    │────▢│  ActionBot Backend   │────▢│  SaaS Product   β”‚
β”‚  (Embedded)     │◀────│  (Action Orchestrator)│◀────│  Backend/API    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quick Start

Prerequisites

  • Node.js 18+
  • Supabase account (free tier works)
  • OpenAI API key

Installation

# Install dependencies
npm install

# Copy environment files
cp apps/api/.env.example apps/api/.env
cp apps/dashboard/.env.local.example apps/dashboard/.env.local

# Edit apps/api/.env with:
#   DATABASE_URL        β€” Supabase Dashboard > Settings > Database > Connection string
#   SUPABASE_URL        β€” Supabase Dashboard > Settings > API > URL
#   SUPABASE_SERVICE_ROLE_KEY β€” Supabase Dashboard > Settings > API > service_role key
#   OPENAI_API_KEY      β€” Your OpenAI key

# Edit apps/dashboard/.env.local with:
#   NEXT_PUBLIC_SUPABASE_URL      β€” Same Supabase URL
#   NEXT_PUBLIC_SUPABASE_ANON_KEY β€” Supabase Dashboard > Settings > API > anon key

Database Setup

# Push schema to database
npm run -w @actionbot/api db:push

# Seed with demo data (tenant, intents, integration)
npm run -w @actionbot/api db:seed

# ⚠️ SAVE THE OUTPUT! It contains your JWT_SECRET and TENANT_ID

Generate a Test Token

npm run -w @actionbot/api db:token

Run the Server

# Start the API server (port 3001)
npm run -w @actionbot/api dev

# In another terminal, start the dashboard (port 3002)
npm run -w @actionbot/dashboard dev

# In another terminal, start the widget dev server (port 5173)
npm run -w @actionbot/widget dev

Test the Dashboard

  1. Open http://localhost:3002
  2. Sign up with your email + password
  3. Complete onboarding (company name + slug)
  4. You’re in! The dashboard will show once your tenant is created.

Test the Widget

  1. Open http://localhost:5173 in your browser
  2. Paste your JWT token in the form
  3. Click β€œLoad Widget”
  4. Try these test messages:
    • Where is my order #1234? β†’ Track order
    • Cancel my order #5678 β†’ Cancel order
    • Where is my refund for order #9999? β†’ Check refund
    • Talk to a human β†’ Escalation

API Endpoints

Chat API (Widget β€” tenant JWT auth)

EndpointMethodDescription
/api/v1/chat/messagePOSTSend message, get AI response
/api/v1/chat/conversations/:idGETGet conversation history
/api/v1/chat/escalatePOSTManually request human support
/wsWebSocketReal-time bidirectional messaging

Admin API (Dashboard β€” Supabase auth)

EndpointMethodDescription
/api/v1/admin/auth/meGETCurrent user’s tenant info
/api/v1/admin/auth/onboardPOSTCreate tenant + link admin user
/api/v1/admin/statsGETDashboard overview stats
/api/v1/admin/conversationsGETList conversations
/api/v1/admin/ticketsGETList tickets
/api/v1/admin/intentsGET/POSTList / create intents
/api/v1/admin/integrationsGET/POSTList / create integrations
/api/v1/admin/analyticsGETAggregate metrics
/api/v1/admin/auditGETAudit log
/api/v1/admin/settingsGET/PUTTenant configuration

WebSocket Connection

// Connect to WebSocket
const ws = new WebSocket('ws://localhost:3001/ws?token=YOUR_JWT_TOKEN');

// Send a message
ws.send(JSON.stringify({
    type: 'message',
    payload: { message: 'Where is my order #1234?' }
}));

// Receive messages
ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log(data.type, data.payload);
};

API Example

curl -X POST http://localhost:3001/api/v1/chat/message \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{"message": "Where is my order #1234?"}'

Project Structure

actionbot/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ api/         # Backend API (Hono + Drizzle)
β”‚   β”‚   └── src/
β”‚   β”‚       β”œβ”€β”€ db/          # Database schema & migrations
β”‚   β”‚       β”œβ”€β”€ middleware/  # Auth (widget JWT + admin Supabase)
β”‚   β”‚       β”œβ”€β”€ routes/      # Chat + Admin API routes
β”‚   β”‚       β”œβ”€β”€ services/    # Business logic
β”‚   β”‚       β”‚   └── adapters/  # Integration adapters (Shopify, etc.)
β”‚   β”‚       └── ws/          # WebSocket handler
β”‚   β”œβ”€β”€ widget/      # Embeddable chat widget (Preact)
β”‚   └── dashboard/   # Admin dashboard (Next.js 14)
β”‚       └── src/
β”‚           β”œβ”€β”€ app/         # App Router pages (12 routes)
β”‚           β”œβ”€β”€ components/  # Auth, layout, UI components
β”‚           └── lib/         # API client, Supabase client
└── packages/
    └── shared/      # Shared types (TODO)

Environment Variables

API (apps/api/.env)

VariableDescription
DATABASE_URLPostgreSQL connection string (Supabase)
SUPABASE_URLSupabase project URL
SUPABASE_SERVICE_ROLE_KEYSupabase service role key (admin auth verification)
OPENAI_API_KEYOpenAI API key for intent detection
JWT_SECRETSecret for widget JWT signing (auto-generated per tenant)
PORTServer port (default: 3001)
NODE_ENVEnvironment (development/production)

Dashboard (apps/dashboard/.env.local)

VariableDescription
NEXT_PUBLIC_SUPABASE_URLSupabase project URL (public)
NEXT_PUBLIC_SUPABASE_ANON_KEYSupabase anon key (public)

Mock Data for Testing

The seed script creates a demo tenant with these test orders:
Order #StatusNotes
#1234ShippedHas tracking number
#5678ProcessingCan be cancelled
#9999RefundedHas refund info

Embedding the Widget

Option 1: Script with data attributes

<script 
    src="https://your-cdn.com/actionbot.js"
    data-api-url="https://api.yourapp.com"
    data-token="USER_JWT_TOKEN"
    data-primary-color="#4F46E5"
    data-welcome-message="Hi! Need help?"
></script>

Option 2: Programmatic initialization

<script src="https://your-cdn.com/actionbot.js"></script>
<script>
    ActionBot.init({
        apiUrl: 'https://api.yourapp.com',
        token: 'USER_JWT_TOKEN',
        primaryColor: '#4F46E5',
        welcomeMessage: 'Hi! How can I help?',
        position: 'bottom-right',
    });
</script>

License

MIT