A multi-tenant, AI-powered customer support platform built with Next.js 16, featuring customizable bots, knowledge base embeddings, and Braintrust evaluation integration.
- π€ Multi-Provider AI: Support for OpenAI, Anthropic, and Google AI models
- π’ Multi-Tenant: Each customer gets isolated configuration and branding
- π Knowledge Base: Upload markdown documents with automatic embedding via pgvector
- π¬ Embeddable Widget: Drop-in chat widget for any website
- π Braintrust Tracing: Every AI interaction is traced for evaluation
- π Datasets & Evals: Save examples, annotate responses, and run evaluations
- π¨ Customizable: Per-tenant branding, instructions, and AI configuration
- π Clerk Auth: Managed authentication with Google/GitHub/email/password
- Framework: Next.js 16 (App Router)
- Database: PostgreSQL with Drizzle ORM
- Vector Search: pgvector for document embeddings
- AI SDK: Vercel AI SDK with multi-provider support
- Tracing: Braintrust SDK for observability and evaluation
- Auth: Clerk (simple, hosted auth)
- Styling: Tailwind CSS + shadcn/ui
- Deployment: Vercel-ready
- Node.js 20+
- Clerk account (free at clerk.com)
- PostgreSQL with pgvector (optional for demo, required for full app)
- OpenAI API key for embeddings/evals (required) + any additional provider keys you plan to use
- Braintrust API key (optional, for tracing)
This repo uses pnpm exclusively. If you don't already have it, install it once:
corepack enable
corepack prepare pnpm@latest --activateClone and install dependencies:
git clone <repository-url>
cd braintrust-evals-app
pnpm installCopy the example environment file and fill in your values:
cp env.example .envRequired variables:
# Clerk Auth (get from dashboard.clerk.com)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_..."
CLERK_SECRET_KEY="sk_test_..."
# Database (optional for demo, required for real data)
DATABASE_URL="postgresql://postgres:postgres@localhost:5433/braintrust_support"
# App
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# Braintrust
BRAINTRUST_API_KEY="bt_sk_..."
# Use the numeric ID if available for faster BTQL queries, otherwise the name is used
BRAINTRUST_PROJECT_ID="proj_123"
BRAINTRUST_PROJECT_NAME="customer-support-platform"
# OpenAI (required for document embeddings + evals)
OPENAI_API_KEY="sk-..."A ready-to-go Postgres + pgvector instance is included via Docker.
# Start the database in the background
pnpm docker:db
# or manually
docker compose up db --detachThe service exposes postgresql://postgres:postgres@localhost:5433/braintrust_support.
Once the database is running, push the schema:
pnpm db:pushEnsure PostgreSQL is running with pgvector extension:
CREATE EXTENSION IF NOT EXISTS vector;Push the schema:
pnpm db:pushpnpm dev --port 3001Visit http://localhost:3001
βββ app/
β βββ api/
β β βββ tenants/ # Tenant CRUD
β β βββ widget/ # Chat API with tracing
β βββ dashboard/ # Admin dashboard
β βββ sign-in/ # Clerk sign-in route
β βββ sign-up/ # Clerk sign-up route
β βββ widget/ # Embeddable chat widget
βββ components/
β βββ ui/ # shadcn/ui components
βββ db/
β βββ index.ts # Drizzle client
β βββ schema.ts # Database schema
βββ lib/
β βββ ai/ # AI providers & embeddings
β βββ braintrust.ts # Braintrust integration
β βββ utils.ts # Utilities
βββ public/
βββ widget.js # Embeddable widget script
- Sign in with Google
- Click "Create Your First Bot"
- Configure:
- Name and URL slug
- AI provider and model
- System instructions
- API key for the chosen provider
Add this script to your website:
<script
src="https://your-deployment.vercel.app/widget.js"
data-tenant="your-bot-slug"
async
></script>All AI interactions are logged to:
- The local database (accessible via Dashboard β Traces)
- Braintrust (if configured) for advanced analysis and evaluation
- Annotate traces with expected outputs
- Save examples to a dataset
- Trigger an evaluation to run against your dataset
Key entities:
- Users/Sessions: Clerk authentication
- Tenants: Multi-tenant configuration (instructions, branding, API keys)
- Documents/DocumentChunks: Knowledge base with vector embeddings
- Conversations/Messages: Chat history
- Traces: AI interaction logs for evaluation
- Datasets/DatasetExamples: Evaluation test cases
- Evals: Evaluation runs and results
- Push to GitHub
- Import in Vercel
- Add environment variables
- Deploy
- Neon: Serverless Postgres with pgvector
- Supabase: Postgres with pgvector extension
- Railway: Managed Postgres
# Run dev server
pnpm dev --port 3001
# Push schema changes
pnpm db:push
# Generate migrations
pnpm db:generate
# Open Drizzle Studio
pnpm db:studio
# Lint
pnpm lintEach tenant has:
- Unique slug for widget URL
- Isolated API keys (stored encrypted)
- Separate conversation and trace history
- Custom branding and instructions
- User sends message via widget
- System retrieves relevant context from pgvector
- Builds prompt with instructions + context
- Streams response via Vercel AI SDK
- Logs trace to local DB + Braintrust
- Tracing: Every chat completion is wrapped with Braintrust tracing
- Metadata: Tenant info, model config, and context are logged
- Evaluation: Datasets can be exported and evaluated in Braintrust
MIT