A production-ready, feature-rich AI chat application powered by Cloudflare Workers AI with support for 22+ language models, including local Ollama integration, web search capabilities, and advanced authentication.
- Overview
- Features
- Screenshots
- System Requirements
- Installation
- Usage
- Configuration
- Available Models
- API Reference
- Development
- Deployment
- Architecture
- Troubleshooting
- Contributing
- License
- Acknowledgments
deploy-production.batCommits changes, pushes to Git, and deploys to Cloudflare Workers.
start-local-dev.batRuns Wrangler dev server with cloud AI models at localhost:8787.
start-ollama.bat
setup-ollama-models.batStart Ollama server and download models for free offline development.
π Full instructions in Deployment section below.
DrewChatApp is a sophisticated AI-powered chat application that bridges cloud-based AI models with local inference capabilities. Built on Cloudflare's edge infrastructure, it delivers blazing-fast responses with sub-100ms latency while supporting both premium cloud models and free local alternatives.
- Cost-Effective Development: Seamlessly switch between free local models (Ollama) and production cloud models (Cloudflare Workers AI)
- Model Flexibility: Access 22+ state-of-the-art language models including reasoning, code generation, and vision models
- Enterprise Features: Built-in authentication, user management, and email notifications
- Web-Enhanced Responses: Integrate real-time web search results for up-to-date information
- Production-Ready: Edge deployment with global CDN, automatic scaling, and 99.9% uptime
- Developers: Building AI-powered applications or prototyping with LLMs
- Enterprises: Deploying secure, scalable chat interfaces for internal tools
- Researchers: Experimenting with multiple AI models and comparing outputs
- Startups: Launching AI products without managing infrastructure
- 22+ Cloud Models: Access Llama 3.3 70B, Qwen 2.5, Mistral, Gemma, DeepSeek, and more
- Local Ollama Integration: Run models offline during development (free, no API costs)
- Automatic Fallback: Seamlessly switches between local and cloud models
- Specialized Models:
- π§ Code Generation: Qwen 2.5 Coder, DeepSeek R1
- π§ Reasoning: QwQ 32B (o1-mini equivalent)
- ποΈ Vision: Llama 3.2 Vision 11B (image understanding)
- π‘οΈ Safety: Llama Guard 3 (content filtering)
- Real-Time Streaming: Server-Sent Events (SSE) for instant word-by-word responses
- Multi-Turn Conversations: Maintains context across messages with conversation history
- File Attachments: Upload and discuss documents, code, or images
- Web Search Integration: Query web results via SearXNG with MCP bridge
- Message Persistence: Automatic conversation saving to browser storage
- Conversation Management: Create, rename, archive, and delete chat threads
- Admin Approval Workflow: New registrations require manual approval
- Email Notifications: Automated notifications via Resend API
- Session Management: Secure 30-day sessions with token-based auth
- Password Reset: Self-service password recovery flow
- D1 Database: Persistent user storage with Cloudflare D1 (SQLite)
- Responsive Design: Mobile-first UI that adapts to all screen sizes (375px to 4K)
- Dark/Light Theme Toggle: Manual theme switcher with localStorage persistence + system preference detection
- Model Backend Indicator: Visual badge showing βοΈ Cloud or π» Local model usage
- Syntax Highlighting: Code blocks with language detection (via highlight.js)
- Markdown Rendering: Rich text formatting with Marked.js
- Typing Indicators: Visual feedback during AI response generation
- Model Selection: Dynamic dropdown to switch between 22+ models
- Touch-Friendly: 44x44px minimum touch targets for mobile devices
- TypeScript: Fully typed codebase with Workers AI SDK types
- Hot Reload: Instant updates during local development
- Comprehensive Logging: Debug-friendly console output with emojis
- Error Handling: Graceful fallbacks and user-friendly error messages
- Docker Support: Containerized MCP bridge for web search
- Batch Scripts: One-click deployment and setup automation
(Add screenshots here of your live application)
[Chat Interface] [Model Selection] [Web Search] [Settings]
- Node.js: v18.0.0+ (v24.0.4 recommended)
- npm: v8.0.0+ or compatible package manager
- Cloudflare Account: Free tier is sufficient for development
- Wrangler CLI: v4.50.0+ (installed via npm)
- Ollama: v0.1.0+ (for local model testing)
- Docker: v20.10+ (for MCP bridge web search)
- Resend Account: For email notifications (free tier available)
# 1. Clone the repository
git clone https://github.com/techaboo/drewchatapp.git
cd drewchatapp
# 2. Install dependencies
npm install
# 3. Login to Cloudflare
npx wrangler login
# 4. Create D1 database
npx wrangler d1 create techaboo_chat
# Copy the database ID and update wrangler.jsonc
# 5. Run migrations
npx wrangler d1 migrations apply techaboo_chat --remote
# 6. Start local development
npm run devYour app is now running at http://localhost:8787/
git clone https://github.com/techaboo/drewchatapp.git
cd drewchatapp
npm install-
Create a Cloudflare Account (if you don't have one):
- Sign up at dash.cloudflare.com
- Navigate to Workers & Pages > Overview
-
Authenticate Wrangler CLI:
npx wrangler login
This opens a browser window to authorize the CLI.
-
Create D1 Database:
npx wrangler d1 create techaboo_chat
Copy the database ID from the output:
[[d1_databases]] binding = "DB" database_name = "techaboo_chat" database_id = "078cde78-1beb-4d7a-a642-d42e8def88c9" # Your ID here -
Update
wrangler.jsonc: Replace thedatabase_idin the file with your newly created ID.
# Apply migrations to create tables (users, sessions, etc.)
npx wrangler d1 migrations apply techaboo_chat --remoteThis creates the following tables:
users- User accounts and credentialssessions- Authentication session tokensconversations- Chat history storage
To enable user registration and password reset emails:
-
Create a Resend Account:
- Sign up at resend.com
- Get your API key from the dashboard
-
Add Environment Variables:
npx wrangler secret put SMTP_USER # Paste your Resend API key npx wrangler secret put ADMIN_EMAIL # Enter your admin email (e.g., admin@example.com)
-
Update
wrangler.jsonc:[vars] SMTP_HOST = "smtp.resend.com" SMTP_PORT = "587" SMTP_FROM = "noreply@yourdomain.com" ADMIN_EMAIL = "admin@example.com"
For free local development without API costs:
-
Install Ollama:
- Download from ollama.com
- Or use Homebrew:
brew install ollama
-
Start Ollama Server:
ollama serve
-
Pull Models:
ollama pull llama3.3:70b ollama pull qwen2.5:32b ollama pull mistral:7b
-
Configure in Code: The app automatically detects Ollama at
http://localhost:11434/and uses it when available.
For web-enhanced AI responses via SearXNG:
-
Start MCP Bridge:
cd mcp-bridge npm install node server.jsThe bridge runs on
http://localhost:3001/ -
Verify Connection:
curl http://localhost:3001/api/search/status # Should return: {"available": true, "provider": "searxng"} -
Docker Setup (alternative):
docker-compose up -d
See SETUP-WEB-SEARCH.md for detailed configuration.
-
Open the Application:
- Local:
http://localhost:8787/ - Production:
https://drewchatapp.cloudflare-liftoff137.workers.dev/
- Local:
-
Select a Model:
- Click the model dropdown (default: Llama 3.3 70B)
- Choose from 22+ available models
-
Start Chatting:
You: Explain quantum computing in simple terms AI: [Streaming response appears word-by-word...]
// Available model categories:
const models = {
general: [
"Llama 3.3 70B", // Best overall performance
"Llama 3.1 8B", // Fast, efficient
"Qwen 2.5 72B", // Strong multilingual
"Mistral 7B v0.2", // Good balance
],
code: [
"Qwen 2.5 Coder 32B", // Code generation specialist
"DeepSeek R1 32B", // Code reasoning
],
reasoning: [
"QwQ 32B", // o1-mini equivalent
],
vision: [
"Llama 3.2 Vision", // Image understanding
]
}Toggle the "π Web Search" button to enhance responses with real-time information:
You: What are the latest AI advancements in 2025?
AI: [Searches web, then synthesizes results...]
Upload and discuss documents, code, or text files:
How It Works:
- Click "Attach files" button (π icon)
- Select one or more files (max 2MB each)
- Files appear as tags below the input box
- Type your question or leave blank for automatic analysis
- Send message - AI reads and analyzes the file contents
Supported File Types:
- Code:
.js,.ts,.py,.java,.cpp,.go,.rs,.rb,.php,.html,.css,.json,.xml,.yaml - Documents:
.txt,.md,.csv,.log - Others: Any text-based file under 2MB
File Formatting:
- Code files: Automatically wrapped in syntax-highlighted code blocks
- Markdown files: Rendered with original formatting
- Text files: Wrapped in plain code blocks
Tips for Best Results:
- Ask specific questions: "What does this function do?" or "Find bugs in this code"
- Use larger models for complex code: Llama 3.3 70B, Qwen 2.5 Coder 32B
- Attach multiple related files together for context
- File contents appear before your message so AI sees them first
Example Prompts:
"Explain this code"
"Find security vulnerabilities"
"Convert this Python to JavaScript"
"Summarize this document"
"What are the main functions?"
Note: Authentication is currently disabled for testing. To enable:
-
Uncomment session validation in
src/index.ts:// Restore lines 327-340 in handleChat() -
Create an account:
- Navigate to
/register.html - Fill out registration form
- Wait for admin approval email
- Navigate to
-
Login:
- Navigate to
/login.html - Enter credentials
- Session lasts 30 days
- Navigate to
curl -X POST https://drewchatapp.cloudflare-liftoff137.workers.dev/api/chat \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"role": "user", "content": "Hello, world!"}
],
"model": "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
"stream": true
}'curl https://drewchatapp.cloudflare-liftoff137.workers.dev/api/modelsResponse:
{
"models": [
{
"id": "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
"name": "Llama 3.3 70B Instruct",
"description": "High-performance general-purpose model"
},
...
]
}curl https://drewchatapp.cloudflare-liftoff137.workers.dev/api/search/statusResponse:
{
"available": false,
"provider": "disabled"
}Create .dev.vars for local development:
# Resend Email Configuration
SMTP_USER=re_YOUR_API_KEY_HERE
ADMIN_EMAIL=admin@example.com
# Optional: Custom AI Gateway
AI_GATEWAY_ENDPOINT=https://gateway.ai.cloudflare.com/v1/YOUR_ACCOUNT/YOUR_GATEWAYEdit src/index.ts to add/remove models:
const MODELS = [
{
id: '@cf/meta/llama-3.3-70b-instruct-fp8-fast',
name: 'Llama 3.3 70B Instruct',
description: 'High-performance general-purpose model',
category: 'general'
},
// Add your custom models here...
]| Model | Size | Description | Best For |
|---|---|---|---|
| Llama 3.3 70B | 70B | Meta's flagship model | Complex reasoning, long context |
| Llama 3.1 8B | 8B | Fast, efficient | Quick responses, simple tasks |
| Llama 3.2 3B | 3B | Ultra-fast | Low-latency applications |
| Llama 3.2 1B | 1B | Edge-optimized | Mobile/edge deployment |
| Qwen 2.5 72B | 72B | Alibaba's flagship | Multilingual, coding |
| Qwen 1.5 14B | 14B | Balanced performance | General use (deprecated) |
| Mistral 7B v0.2 | 7B | Open-source favorite | Balanced speed/quality |
| Gemma 3 12B | 12B | Google DeepMind | Instruction following |
| Gemma 7B | 7B | Efficient | Quick tasks |
| DeepSeek V3 | β | Latest reasoning | Complex problem-solving |
| Model | Focus | Description |
|---|---|---|
| Qwen 2.5 Coder 32B | Code generation | Specialized for programming tasks |
| DeepSeek R1 32B | Code reasoning | Advanced code understanding |
| Model | Description | Equivalent To |
|---|---|---|
| QwQ 32B | Chain-of-thought reasoning | OpenAI o1-mini |
| Model | Capabilities | Input |
|---|---|---|
| Llama 3.2 Vision 11B | Image understanding, OCR, visual QA | Text + Images |
Note: Vision models automatically accept the Llama 3.2 License on first use. By using this model, you agree to Meta's Community License and Acceptable Use Policy.
| Model | Purpose | Output |
|---|---|---|
| Llama Guard 3 8B | Content filtering, safety classification | Safe/Unsafe labels |
| Model | Base | Description |
|---|---|---|
| Llama 3.1 8B LoRA | Llama 3.1 8B | Customizable with your data |
| Llama 3.2 1B LoRA | Llama 3.2 1B | Edge-optimized fine-tuning |
| Mistral 7B LoRA | Mistral 7B | Open-weight customization |
| Gemma 2B LoRA | Gemma 2B | Lightweight fine-tuning |
Total: 22 models (19 cloud + 3 deprecated but functional)
Send a chat message and receive streaming AI responses.
Request Body:
{
"messages": [
{"role": "user", "content": "Your message here"}
],
"model": "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
"stream": true,
"max_tokens": 2048,
"temperature": 0.7,
"top_p": 0.9
}Response (Server-Sent Events):
data: {"response":"Hello"}
data: {"response":" there"}
data: {"response":"!"}
data: [DONE]
Parameters:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
messages |
Array | Yes | β | Chat history with role/content pairs |
model |
String | Yes | β | Model ID from /api/models |
stream |
Boolean | No | true | Enable SSE streaming |
max_tokens |
Number | No | 2048 | Maximum response length |
temperature |
Number | No | 0.7 | Randomness (0.0-1.0) |
top_p |
Number | No | 0.9 | Nucleus sampling threshold |
Authentication: Currently disabled (no session required)
Retrieve all available AI models.
Response:
{
"models": [
{
"id": "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
"name": "Llama 3.3 70B Instruct",
"description": "High-performance general-purpose model",
"category": "general",
"context_length": 8192,
"supports_vision": false
},
{
"id": "@cf/meta/llama-3.2-11b-vision-instruct",
"name": "Llama 3.2 Vision 11B",
"description": "Vision-language model",
"category": "vision",
"context_length": 4096,
"supports_vision": true
}
]
}Check web search availability.
Response:
{
"available": false,
"provider": "disabled"
}When MCP bridge is running:
{
"available": true,
"provider": "searxng",
"endpoint": "http://localhost:3001"
}Create a new user account (requires admin approval).
Request Body:
{
"email": "user@example.com",
"password": "securePassword123",
"username": "johndoe"
}Response:
{
"message": "Registration successful. Please wait for admin approval.",
"userId": "uuid-here"
}Authenticate and create a session.
Request Body:
{
"email": "user@example.com",
"password": "securePassword123"
}Response:
{
"message": "Login successful",
"sessionToken": "token-here",
"expiresAt": "2025-03-04T12:00:00Z"
}Request a password reset email.
Request Body:
{
"email": "user@example.com"
}Response:
{
"message": "Password reset email sent"
}# Start development server with hot reload
npm run dev
# Access at http://localhost:8787/# Run unit tests
npm test
# Run tests in watch mode
npm run test:watch# Check TypeScript types
npm run typecheck
# Format code (if configured)
npm run format# Create migration
npx wrangler d1 migrations create techaboo_chat migration_name
# Apply migrations locally
npx wrangler d1 migrations apply techaboo_chat --local
# Apply migrations to production
npx wrangler d1 migrations apply techaboo_chat --remote
# Query database
npx wrangler d1 execute techaboo_chat --command "SELECT * FROM users"Edit src/index.ts and add:
console.log('π DEBUG: Request details:', {
url: request.url,
method: request.method,
headers: Object.fromEntries(request.headers.entries())
});# Stream production logs
npx wrangler tail
# Stream with filtering
npx wrangler tail --format=json | grep ERROR# Check if Ollama is running
curl http://localhost:11434/api/tags
# Test chat endpoint
curl http://localhost:11434/api/chat -d '{
"model": "llama3.3:70b",
"messages": [{"role": "user", "content": "Hello"}],
"stream": false
}'Use these batch scripts for one-click operations:
deploy-production.batStages changes, commits to Git, pushes to GitHub, and deploys to Cloudflare Workers.
start-local-dev.batStarts Wrangler dev server with Cloudflare Workers AI (cloud models).
start-ollama.batStarts Ollama server on localhost:11434 for free local models.
setup-ollama-models.batInteractive menu to download recommended Ollama models (1-8GB).
start-mcp-bridge.batStarts Docker container for web search via SearXNG.
# Deploy with one command
npm run deploy
# Or use the batch script (Windows)
deploy-production.bat
# Or deploy directly
npx wrangler deploy# 1. Stage and commit changes
git add .
git commit -m "Your commit message"
git push origin main
# 2. Deploy to Cloudflare
npx wrangler deploy
# 3. View deployment URL
# https://drewchatapp.YOUR_SUBDOMAIN.workers.dev/-
Add Domain in Cloudflare Dashboard:
- Workers & Pages > Your Worker > Settings > Domains
- Click "Add Domain"
- Enter your domain (e.g.,
chat.example.com)
-
Update DNS Records:
- Cloudflare automatically creates CNAME record
- Wait 1-5 minutes for propagation
-
Enable HTTPS:
- SSL/TLS > Overview > Select "Full (strict)"
- Free SSL certificate is auto-provisioned
# Deploy to staging
npx wrangler deploy --env staging
# Deploy to production
npx wrangler deploy --env productionAdd to wrangler.jsonc:
{
"env": {
"staging": {
"name": "drewchatapp-staging",
"vars": {
"ENVIRONMENT": "staging"
}
},
"production": {
"name": "drewchatapp",
"vars": {
"ENVIRONMENT": "production"
}
}
}
}# List recent deployments
npx wrangler deployments list
# Rollback to specific version
npx wrangler rollback --message "Reverting due to bug"# View live traffic
npx wrangler tail --format=pretty
# View analytics in dashboard
# Cloudflare Dashboard > Workers & Pages > Your Worker > Analyticsβββββββββββββββ HTTPS ββββββββββββββββββββ
β Browser β ββββββββββββββββΊ β Cloudflare Edge β
β (Client) β SSE Streaming β (CDN + WAF) β
βββββββββββββββ ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββββ
β Cloudflare Worker β
β (src/index.ts) β
ββββββββββ¬ββββββββββββ
β
βββββββββββββββββββββββΌββββββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββ βββββββββββββββββ ββββββββββββββββββββ
β Workers AI API β β D1 Database β β Resend Email β
β (22+ models) β β (SQLite) β β (SMTP) β
βββββββββββββββββββ βββββββββββββββββ ββββββββββββββββββββ
β
β Fallback
βΌ
βββββββββββββββββββ
β Ollama (Local) β
β localhost:11434 β
βββββββββββββββββββ
- Client Request β Browser sends POST to
/api/chat - Edge Routing β Cloudflare edge routes to nearest Worker datacenter
- Authentication β (Optional) Validate session token from D1
- Model Selection β Choose cloud (Workers AI) or local (Ollama) model
- AI Inference β Stream tokens via SSE as they're generated
- Response β Client receives word-by-word updates
- Vanilla JavaScript: No framework dependencies
- Marked.js v15.0.7: Markdown parsing
- Highlight.js v11.11.1: Syntax highlighting
- CSS3: Custom responsive design with dark mode
- Cloudflare Workers: V8 isolate-based serverless runtime
- TypeScript 5.8.3: Type-safe development
- Wrangler 4.50.0: Deployment & local dev CLI
- Workers AI SDK: Native AI model bindings
- Cloudflare D1: Edge-native SQLite database
- Schema: Users, sessions, conversations tables
- Migrations: Version-controlled SQL migrations
- Resend API: Transactional email (SMTP)
- Ollama: Local LLM inference (optional)
- SearXNG: Web search via MCP bridge (optional)
- Edge Execution: Code runs at 275+ Cloudflare datacenters (zero-trust)
- Session Tokens: Cryptographically secure random tokens
- Password Hashing: Bcrypt-like hashing with salts
- CORS Protection: Strict origin validation
- Rate Limiting: Cloudflare's built-in DDoS protection
- Content Security Policy: XSS prevention headers
- Streaming Responses: SSE reduces time-to-first-token
- Edge Caching: Static assets cached at 275+ locations
- Model Fallback: Ollama reduces API latency during dev
- Lazy Loading: Frontend loads markdown/highlight.js on-demand
- Connection Pooling: D1 maintains persistent connections
Symptom: /api/chat returns 401 even though authentication is disabled
Solution:
// In src/index.ts, comment out session validation:
async function handleChat(request: Request, env: Env) {
// const session = await validateSession(request, env);
// if (!session) {
// return new Response('Unauthorized', { status: 401 });
// }
// Continue with chat logic...
}Symptom: Selected model returns 404 or "model not available"
Solution:
- Check model ID matches exactly:
@cf/meta/llama-3.3-70b-instruct-fp8-fast - Verify model is in MODELS array in
src/index.ts - Some models may be deprecated (use alternatives)
Symptom: Local development can't reach Ollama at http://localhost:11434
Solution:
# Verify Ollama is running
ollama serve
# Check in another terminal
curl http://localhost:11434/api/tags
# If not working, restart Ollama
killall ollama
ollama serveSymptom: Error 5016 - "Prior to using this model, you must submit the prompt 'agree'"
What This Means: Llama 3.2 Vision models require accepting Meta's license agreement.
Solution:
The app automatically sends the "agree" message on first use. If you see this error:
-
Automatic handling (already implemented in v1.1.0):
- The backend automatically accepts license on first vision model use
- No user action required
-
Manual acceptance (required if automatic fails):
# Via Wrangler (one-time setup) npx wrangler ai run @cf/meta/llama-3.2-11b-vision-instruct --prompt "agree"
This sends "agree" to Meta's license server and enables vision models for your account.
-
If still not working:
- Ensure you're not in the EU or a company based in the EU (license restriction)
- Check Cloudflare Workers AI dashboard for account status
- Try logging out and back in:
npx wrangler logout && npx wrangler login - Use a different model temporarily while investigating
License Links:
By using vision models, you agree that you are not in the EU or a company with principal place of business in the EU.
Symptom: Error: table users already exists
Solution:
# Delete and recreate database
npx wrangler d1 delete techaboo_chat
npx wrangler d1 create techaboo_chat
# Update database_id in wrangler.jsonc
# Re-run migrations
npx wrangler d1 migrations apply techaboo_chat --remoteSymptom: Registration emails not received
Solution:
-
Verify Resend API Key:
npx wrangler secret list # Should show SMTP_USER -
Check Email Logs:
npx wrangler tail # Look for "Email sent successfully" or error messages -
Verify Sender Domain:
- Resend requires verified domain (or use
noreply@resend.devfor testing)
- Resend requires verified domain (or use
Symptom: npx wrangler deploy returns error
Common Solutions:
# Re-authenticate
npx wrangler logout
npx wrangler login
# Check wrangler.jsonc syntax
# (JSON comments must use // not /* */)
# Clear cache and rebuild
rm -rf node_modules dist
npm install
npm run build
npx wrangler deploySymptom: /api/search/status returns {"available": false}
Solution:
# Start MCP bridge
cd mcp-bridge
npm install
node server.js
# Verify in browser
curl http://localhost:3001/api/search/status
# Should return: {"available": true, "provider": "searxng"}Symptom: AI response cuts off after a few words
Solution:
- Check
max_tokensparameter (increase to 4096+) - Verify model supports streaming (all current models do)
- Check browser console for JavaScript errors
- Inspect network tab for closed SSE connection
Symptom: Double-clicking .bat files does nothing or shows errors
Solutions:
A. "command not found" errors:
# Verify npm is in PATH
where npm
# If not found, add Node.js to system PATH:
# System Properties > Environment Variables > Path
# Add: C:\Program Files\nodejs\B. deploy-production.bat fails:
# Ensure Git is installed and authenticated
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
# Test Git access
git status
# If permission denied, set up SSH keys
ssh-keygen -t ed25519 -C "your@email.com"C. start-ollama.bat says "Ollama not found":
# Install Ollama first
# Download from: https://ollama.ai/download/windows
# Verify installation
ollama --version
# If not found, add to PATH manually
set PATH=%PATH%;C:\Users\%USERNAME%\AppData\Local\Programs\OllamaD. setup-ollama-models.bat downloads fail:
# Check internet connection
ping ollama.ai
# Verify Ollama server is running
start-ollama.bat
# Wait 10 seconds, then retry download
setup-ollama-models.batE. start-mcp-bridge.bat fails:
# Ensure Docker Desktop is installed and running
# Download from: https://www.docker.com/products/docker-desktop/
# Verify Docker is running
docker --version
docker ps
# If permission error, run as Administrator:
# Right-click start-mcp-bridge.bat > Run as administratorEnable comprehensive logging:
// Add to src/index.ts
const DEBUG = true;
if (DEBUG) {
console.log('π Request:', request.method, request.url);
console.log('π Headers:', Object.fromEntries(request.headers));
console.log('π Body:', await request.clone().text());
}- GitHub Issues: github.com/techaboo/drewchatapp/issues
- Cloudflare Discord: discord.gg/cloudflaredev
- Cloudflare Docs: developers.cloudflare.com/workers
Contributions are welcome! Please follow these guidelines:
-
Fork the Repository
git clone https://github.com/techaboo/drewchatapp.git cd drewchatapp -
Create a Feature Branch
git checkout -b feature/amazing-feature
-
Make Changes
- Follow existing code style
- Add comments for complex logic
- Update documentation if needed
-
Test Locally
npm run dev # Test your changes thoroughly -
Commit Changes
git commit -m "Add amazing feature" -
Push to GitHub
git push origin feature/amazing-feature
-
Open a Pull Request
- Describe your changes clearly
- Reference related issues
- Wait for review
- TypeScript: Use strict type checking
- Formatting: Follow Prettier defaults
- Comments: Use JSDoc for functions
- Naming: camelCase for variables, PascalCase for types
Example:
/**
* Handles streaming AI chat responses
* @param messages - Array of chat messages with role/content
* @param model - Cloudflare Workers AI model ID
* @returns ReadableStream of SSE responses
*/
async function handleChatStream(
messages: ChatMessage[],
model: string
): Promise<ReadableStream> {
// Implementation...
}Use GitHub Issues with this template:
**Describe the bug**
A clear description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '...'
3. See error
**Expected behavior**
What you expected to happen.
**Screenshots**
If applicable, add screenshots.
**Environment**
- OS: [e.g., Windows 11]
- Browser: [e.g., Chrome 120]
- Node.js: [e.g., v20.0.0]Use GitHub Issues with this template:
**Feature Description**
Clear description of the feature you want.
**Use Case**
Explain why this feature would be useful.
**Proposed Solution**
How you think it should work.
**Alternatives Considered**
Other solutions you've thought about.This project is licensed under the MIT License.
MIT License
Copyright (c) 2025 techaboo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
See LICENSE file for full details.
- Cloudflare Workers AI - For providing access to 22+ state-of-the-art language models
- Ollama - For enabling free local LLM inference during development
- Resend - For reliable transactional email delivery
- Meta AI - For Llama 3.x model family (open-weight foundation models)
- Qwen Team (Alibaba) - For Qwen 2.5 series models
- Mistral AI - For Mistral 7B and fine-tuning support
- Google DeepMind - For Gemma model family
- DeepSeek - For reasoning and code-specialized models
- ChatGPT - UI/UX inspiration for streaming responses
- Cloudflare Templates - Base template structure and best practices
- open-webui - Ollama integration patterns
- LangChain - Agent architecture concepts
- Cloudflare Developers Discord - For troubleshooting and support
- r/CloudFlare - Community feedback and feature requests
- GitHub Sponsors - Thank you to all contributors and supporters
- @cloudflare - For building an incredible edge computing platform
- @ollama - For democratizing local LLM access
- @resend - For developer-friendly email APIs
- All contributors who submitted bug reports, feature requests, and pull requests
Built with β€οΈ by techaboo
drewchatapp/
βββ public/ # Frontend static assets
β βββ index.html # Main chat interface
β βββ chat.js # Frontend JavaScript (SSE handling)
β βββ login.html # User login page
β βββ register.html # User registration page
β βββ reset-password.html # Password recovery page
β
βββ src/ # Backend TypeScript source
β βββ index.ts # Main Worker entry point
β βββ auth.ts # Authentication logic
β βββ types.ts # Type definitions
β
βββ mcp-bridge/ # Web search integration
β βββ server.js # MCP proxy server (Node.js)
β βββ Dockerfile # Docker container config
β βββ package.json # Node dependencies
β
βββ migrations/ # Database schema
β βββ 0001_init_auth.sql # User/session tables
β
βββ wrangler.jsonc # Cloudflare Worker config
βββ tsconfig.json # TypeScript compiler settings
βββ docker-compose.yml # Docker orchestration
β
βββ Documentation/
βββ README.md # This file
βββ OLLAMA-SETUP.md # Local model guide
βββ SETUP-WEB-SEARCH.md # Web search setup
βββ DEPLOY-TO-CLOUDFLARE.md # Deployment guide
βββ DOCKER-SETUP.md # Docker instructions
βββ QUICK-DEPLOY.md # Fast deployment
1. User types message in chat.js
β
2. POST /api/chat with messages array
β
3. Worker validates session (optional)
β
4. Worker selects model (cloud vs local)
β
5. AI inference begins (Workers AI or Ollama)
β
6. SSE stream starts { data: {response: "token"} }
β
7. Frontend renders word-by-word
β
8. Stream ends with [DONE]
β
9. Conversation saved to localStorage
src/index.ts - Main Worker Logic
- handleChat(): Processes chat requests, manages streaming
- handleWorkersAiRequest(): Routes to Workers AI models
- handleOllamaRequest(): Fallback to local Ollama
- handleListModels(): Returns model metadata
- validateSession(): Checks authentication tokens
src/auth.ts - Authentication System
- User registration with admin approval
- Password hashing with bcrypt-like algorithm
- Session token generation and validation
- Email notifications via Resend
src/types.ts - TypeScript Definitions
interface Env {
AI: Ai; // Workers AI binding
DB: D1Database; // Database binding
SMTP_USER: string; // Email credentials
ADMIN_EMAIL: string; // Admin notifications
}
interface ChatMessage {
role: 'system' | 'user' | 'assistant';
content: string;
}public/chat.js - Chat Interface
- sendMessage(): Sends requests to /api/chat
- processStream(): Parses SSE responses
- renderMarkdown(): Formats AI responses with syntax highlighting
- saveConversation(): Persists chat history to localStorage
Streaming Protocol:
// SSE format from server
data: {"response": "Hello"}
data: {"response": " world"}
data: [DONE]
// JavaScript parsing
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const {done, value} = await reader.read();
if (done) break;
buffer += decoder.decode(value, {stream: true});
const lines = buffer.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6));
updateUI(data.response);
}
}
}Edit src/index.ts:
const DEFAULT_MODEL = '@cf/meta/llama-3.3-70b-instruct-fp8-fast';
// Change to:
const DEFAULT_MODEL = '@cf/qwen/qwen-2.5-coder-32b-instruct';const MODELS = [
{
id: '@cf/your-custom/model',
name: 'Your Custom Model',
description: 'Fine-tuned for your use case',
category: 'custom'
},
...existingModels
];const SYSTEM_PROMPT = `You are a helpful AI assistant specialized in [YOUR_DOMAIN].
Your responses should be [YOUR_STYLE] and focus on [YOUR_GOAL].`;
// Add to messages array
messages.unshift({
role: 'system',
content: SYSTEM_PROMPT
});-
Create AI Gateway in Cloudflare Dashboard:
- Navigate to AI > AI Gateway
- Click "Create Gateway"
- Copy your gateway slug
-
Update
src/index.ts:
const aiResponse = await env.AI.run(model, {
messages,
max_tokens: 2048,
gateway: {
id: 'your-gateway-slug',
skipCache: false,
cacheTtl: 3600
}
});Benefits:
- Caching: Reduces API costs for repeated queries
- Rate Limiting: Prevent abuse
- Analytics: Track usage patterns
Edit public/index.html CSS variables:
:root {
--primary-color: #0066cc; /* Brand color */
--bg-color: #1a1a1a; /* Dark background */
--text-color: #e0e0e0; /* Light text */
--accent-color: #ff6b35; /* Highlight color */
}Restore session validation in src/index.ts:
async function handleChat(request: Request, env: Env) {
// Uncomment these lines:
const session = await validateSession(request, env);
if (!session) {
return new Response('Unauthorized', { status: 401 });
}
// Rest of chat logic...
}- Cloudflare Workers: developers.cloudflare.com/workers
- Workers AI: developers.cloudflare.com/workers-ai
- D1 Database: developers.cloudflare.com/d1
- Wrangler CLI: developers.cloudflare.com/workers/wrangler
- Llama 3.x: llama.meta.com
- Qwen 2.5: qwenlm.github.io
- Mistral 7B: mistral.ai/news/announcing-mistral-7b
- DeepSeek: deepseek.com
- Ollama: ollama.com/library
- Resend: resend.com/docs
- Marked.js: marked.js.org
- Highlight.js: highlightjs.org
- Cloudflare Discord: discord.gg/cloudflaredev
- Cloudflare Community: community.cloudflare.com
- GitHub Discussions: github.com/techaboo/drewchatapp/discussions
- Multi-User Chat Rooms - Collaborative AI conversations
- Conversation Search - Full-text search across chat history
- Custom Agents - Pre-configured personas (coding assistant, writer, etc.)
- Voice Input - Speech-to-text integration
- Export Conversations - Download as Markdown/PDF
- Model Comparison - Side-by-side response comparison
- Cost Tracking - Monitor Workers AI usage and costs
- RAG Support - Connect to vector databases (Vectorize)
- Function Calling - Tool use and external API integration
- Mobile App - React Native client
- Web Search Integration - SearXNG via MCP bridge β
- 22+ Model Support - Full Workers AI model catalog β
- Authentication System - User accounts and sessions β
- Local Ollama Support - Free development mode β
- Streaming Responses - Real-time SSE implementation β
- Markdown Rendering - Code highlighting and formatting β
- Model Selection - Dynamic model switching β
- Email Notifications - Registration and password reset β
- Cloudflare Deployment - Production-ready edge hosting β
Q: How much does it cost to run this application?
A: Cloudflare Workers AI pricing (as of 2025):
- Free Tier: 10,000 neurons/day (~1,000 messages)
- Paid: $0.01 per 1,000 neurons (~$0.001 per message)
- Ollama: Completely free for local development
Q: Can I use this commercially?
A: Yes, MIT License permits commercial use. However, review Cloudflare's Workers AI Terms of Service.
Q: Which model should I choose?
A: Depends on your use case:
- General chat: Llama 3.3 70B (best quality)
- Fast responses: Llama 3.1 8B (low latency)
- Code generation: Qwen 2.5 Coder 32B
- Complex reasoning: QwQ 32B
- Image analysis: Llama 3.2 Vision 11B
Q: How do I enable authentication?
A: Uncomment session validation in src/index.ts (lines 327-340). Users must register at /register.html and await admin approval.
Q: Can I self-host this?
A: The MCP bridge can run locally, but the main app requires Cloudflare Workers for Workers AI access. You can use Ollama for fully self-hosted inference.
Q: How do I report a security vulnerability?
A: Email security concerns to techaboo@gmail.com. Do not create public GitHub issues for security bugs.
Q: Can I fine-tune models?
A: Yes! Use the LoRA-enabled models (Llama 3.1 8B LoRA, Mistral 7B LoRA, etc.) with Cloudflare's fine-tuning API.
Q: Does this work offline?
A: With Ollama running, the app can work offline during development. Production deployment requires Cloudflare's network.
Q: How do I add a custom domain?
A: See Deployment β Custom Domain Setup section above.
Q: How do I switch between dark and light themes?
A: Click the theme toggle button (π/βοΈ) in the header. Your preference is saved to localStorage and persists across sessions.
Q: What does the model indicator badge mean?
A: The badge shows which backend is active:
- βοΈ Cloud (purple): Using Cloudflare Workers AI
- π» Local (pink): Using Ollama on your machine
β οΈ Offline (red): Ollama server not detected
Q: Can I use local models in production?
A: No. Ollama models only work during local development (npm run dev). Production deployments on Cloudflare Workers must use cloud models (@cf/ prefix).
Q: How do I download more Ollama models?
A: Run setup-ollama-models.bat for an interactive menu, or use:
ollama pull llama3.2:1b
ollama pull qwen2.5-coder:7bThe model will appear in the dropdown after download completes.
techaboo - Creator and lead developer
No contributors yet. Be the first to contribute!
See CONTRIBUTING.md for guidelines.
This project builds upon the excellent work of:
- Cloudflare Workers AI Team - For the serverless AI platform
- Ollama Community - For local LLM inference tools
- Meta AI - For Llama model family (open-weight models)
- Alibaba Cloud - For Qwen model series
- Mistral AI - For open-source Mistral 7B
- Google DeepMind - For Gemma models
- Resend Team - For developer-friendly email APIs
MIT License Β© 2025 techaboo
See LICENSE section for full terms.
{ "name": "drewchatapp", "main": "src/index.ts", "compatibility_date": "2025-02-04", // Assets directory (HTML/JS/CSS) "assets": { "directory": "./public" }, // Workers AI binding "ai": { "binding": "AI" }, // D1 Database "d1_databases": [ { "binding": "DB", "database_name": "techaboo_chat", "database_id": "YOUR_DATABASE_ID_HERE" } ], // Environment variables "vars": { "SMTP_HOST": "smtp.resend.com", "SMTP_PORT": "587", "SMTP_FROM": "noreply@yourdomain.com", "ADMIN_EMAIL": "admin@example.com" } }