This set of docs serves as a reference for the catb project, which is an LLM-based chatbot designed to assist cat owners with theit pets’ health and well-being.
This is the multi-page printable view of this section. Click here to print.
Documentation
- 1: Overview
- 2: CatBot Tech Specs Lean MVP
- 3: CatBot Technical Architecture Specifications
- 4: MVP high level description
- 5: Concepts
- 6: Long Page Title
1 - Overview
Catb is a chatbot helping cat owners understand their cats behaviorial and physical issues so they can take action to solve them.
Catb asks discovery questions about owners’ cats and provides explanations and guidance.
The call to action can range from adapting their interactions or home setting to help with their pets reach optimal mental health all the way to taking their pets to emergency care facilities.
Catb acts as a informed friend that soothes the owners’s anxiety while providing qualified guidance.
Where should I go next?
-
MVP high-level description: A simple overview on the upcoming MVP
-
MVP technical specifications: A more thorough technical description of the upcoming MVP
-
CatBot technical architecture specifications: A broader view on catb’s final version and roadmap
2 - CatBot Tech Specs Lean MVP
🚀 Current Production Status
The catb MVP is LIVE and operational with the following setup:
Production Endpoints
- Chat API: https://askmu.live/chat (POST, requires Basic Auth)
- Health Check: https://askmu.live/health (GET, no auth required)
- Frontend: https://darkslategrey-lemur-580006.hostingersite.com/
Access Credentials
- API Username:
catb-api
- API Password:
[REDACTED - Check .env file on VPS]
- Backend Git Repo: https://github.com/anegg0/catb-backend (private)
Technology Stack
- Frontend: Hostinger Horizons with custom JavaScript integration
- Backend: Express.js API in Docker on Hostinger VPS
- AI Model: Anthropic Claude 3 Haiku (via API)
- Database: Supabase PostgreSQL (configured)
- Security: SSL/TLS + Basic Auth + CORS + Rate Limiting
System Architecture Overview
The catb MVP follows a modern, scalable architecture designed for cost-effectiveness and simplicity while maintaining security and performance.
Current Implementation Status
The catb MVP has been successfully deployed with the following production configuration:
Frontend Architecture (Implemented)
- Frontend Platform: Hostinger Horizons (https://darkslategrey-lemur-580006.hostingersite.com/)
- Chat Integration: JavaScript widget added via Horizons custom code area
- Security: Basic Authentication + SSL encryption via askmu.live domain
- Integration: Real-time communication with backend API via HTTPS
Production Stack (Live)
- Frontend: Hostinger Horizons with integrated chat widget
- Backend: Node.js/Express in Docker container on Hostinger VPS (89.116.170.226)
- Domain: askmu.live with SSL certificate (Let’s Encrypt)
- Database: Supabase PostgreSQL (configured and ready)
- LLM: Anthropic Claude 3 Haiku API (integrated)
- Infrastructure: Nginx reverse proxy with Basic Auth protection
- Architecture: Secure API with CORS configured for Horizons domain only
Data Flow Architecture
The following diagram shows how data flows through the system during a typical user interaction:
Security Architecture
The system implements multiple layers of security to protect user data and prevent unauthorized access:
Component Interaction Architecture
This diagram shows how different components interact within the backend service:
Deployment Architecture
The deployment architecture supports both development and production environments:
Scaling and Monitoring Architecture
The system is designed to scale automatically based on demand while providing comprehensive monitoring:
API Request Flow Architecture
This diagram shows the detailed flow of an API request through the system:
1. Frontend Implementation (Hostinger Horizons) - COMPLETED ✅
Horizons Chat Widget Integration
The frontend has been successfully integrated with the Hostinger Horizons website at https://darkslategrey-lemur-580006.hostingersite.com/. The chat widget communicates with the secured backend API at https://askmu.live.
🌐 chat-widget.js - Embeddable Chat Widget - Click to expand
// chat-widget.js - Add this to your Horizons custom code section
(function() {
// Configuration - PRODUCTION VALUES
const API_URL = 'https://askmu.live';
const API_AUTH = 'Basic ' + btoa('catb-api:YOUR_PASSWORD_HERE'); // Replace with actual password
const WIDGET_ID = 'catb-chat-widget';
// Extract session token from URL
const urlParts = window.location.pathname.split('/');
const sessionToken = urlParts[urlParts.length - 1];
// Create chat widget HTML
const widgetHTML = `
<div id="${WIDGET_ID}" class="catb-chat-widget">
<div class="chat-header">
<h3>Chat with Mu - Your Cat Health Assistant</h3>
<button class="minimize-btn" onclick="toggleChat()">_</button>
</div>
<div class="chat-messages" id="chat-messages">
<div class="message assistant">
<p>Hello! I'm Mu. I'm here to help you understand your cat's health and behavior. What concerns do you have about your cat today?</p>
</div>
</div>
<div class="chat-input-area">
<input
type="text"
id="chat-input"
placeholder="Type your message here..."
onkeypress="if(event.key === 'Enter') sendMessage()"
/>
<button onclick="sendMessage()" id="send-btn">Send</button>
</div>
</div>
`;
// Create and inject styles
const styles = `
<style>
.catb-chat-widget {
position: fixed;
bottom: 20px;
right: 20px;
width: 350px;
height: 500px;
background: white;
border-radius: 10px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
z-index: 9999;
}
.chat-header {
background: #4A90E2;
color: white;
padding: 15px;
border-radius: 10px 10px 0 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.chat-header h3 {
margin: 0;
font-size: 16px;
}
.minimize-btn {
background: transparent;
border: none;
color: white;
font-size: 20px;
cursor: pointer;
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 20px;
background: #f5f5f5;
}
.message {
margin-bottom: 15px;
padding: 10px 15px;
border-radius: 10px;
max-width: 80%;
}
.message.user {
background: #4A90E2;
color: white;
margin-left: auto;
text-align: right;
}
.message.assistant {
background: white;
color: #333;
}
.message.error {
background: #ff6b6b;
color: white;
}
.chat-input-area {
display: flex;
padding: 15px;
background: white;
border-top: 1px solid #e0e0e0;
border-radius: 0 0 10px 10px;
}
#chat-input {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
margin-right: 10px;
}
#send-btn {
background: #4A90E2;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
#send-btn:hover {
background: #357ABD;
}
#send-btn:disabled {
background: #cccccc;
cursor: not-allowed;
}
.loading {
text-align: center;
color: #666;
font-style: italic;
}
@media (max-width: 400px) {
.catb-chat-widget {
width: 100%;
height: 100%;
bottom: 0;
right: 0;
border-radius: 0;
}
}
</style>
`;
// Global functions
window.toggleChat = function() {
const widget = document.getElementById(WIDGET_ID);
widget.style.display = widget.style.display === 'none' ? 'flex' : 'none';
};
window.sendMessage = async function() {
const input = document.getElementById('chat-input');
const sendBtn = document.getElementById('send-btn');
const messagesContainer = document.getElementById('chat-messages');
const message = input.value.trim();
if (!message || sendBtn.disabled) return;
// Add user message
messagesContainer.innerHTML += `
<div class="message user">
<p>${message}</p>
</div>
`;
// Clear input and disable
input.value = '';
sendBtn.disabled = true;
// Add loading indicator
messagesContainer.innerHTML += '<div class="loading">Mu is thinking...</div>';
messagesContainer.scrollTop = messagesContainer.scrollHeight;
try {
const response = await fetch(`${API_URL}/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': API_AUTH
},
body: JSON.stringify({ message })
});
const data = await response.json();
// Remove loading indicator
const loadingEl = messagesContainer.querySelector('.loading');
if (loadingEl) loadingEl.remove();
if (response.ok) {
messagesContainer.innerHTML += `
<div class="message assistant">
<p>${data.response}</p>
</div>
`;
} else {
throw new Error(data.error || 'Failed to get response');
}
} catch (error) {
// Remove loading indicator
const loadingEl = messagesContainer.querySelector('.loading');
if (loadingEl) loadingEl.remove();
messagesContainer.innerHTML += `
<div class="message error">
<p>I apologize, but I encountered an error. Please try again.</p>
</div>
`;
} finally {
sendBtn.disabled = false;
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
};
// Initialize widget when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initWidget);
} else {
initWidget();
}
function initWidget() {
// For production with Basic Auth, no session token validation needed
// The API is protected by Basic Authentication
// Inject styles and HTML
document.head.insertAdjacentHTML('beforeend', styles);
document.body.insertAdjacentHTML('beforeend', widgetHTML);
}
})();
Horizons Page Setup
To integrate the chat widget into your Horizons pages:
📝 Horizons Integration Steps - Click to expand
## Step 1: Create Private URL Pages in Horizons
1. Log into your Horizons dashboard
2. Create a new page with URL pattern: `/chat/[session-token]`
3. Set page visibility to "Unlisted" or "Private"
## Step 2: Add Custom Code to Page
1. Go to Page Settings > Custom Code
2. Add the chat widget script to the "Before </body>" section
3. Update the API_URL in the script to your backend URL
## Step 3: Configure CORS
Ensure your backend allows requests from your Horizons domain:
- Add `https://your-domain.com` to ALLOWED_ORIGINS
## Step 4: Test the Integration
1. Generate a test session token via your backend API
2. Navigate to: `https://your-domain.com/chat/[your-test-token]`
3. Verify the chat widget loads and functions correctly
Alternative: Iframe Integration
If you prefer to host the chat interface separately:
🖼️ iframe-integration.html - Iframe approach - Click to expand
<!-- Add this to your Horizons custom HTML block -->
<div id="catb-chat-container" style="width: 100%; height: 600px; position: relative;">
<iframe
id="catb-chat-frame"
src=""
style="width: 100%; height: 100%; border: none; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);"
allow="clipboard-write"
></iframe>
</div>
<script>
// Extract session token and set iframe source
(function() {
const urlParts = window.location.pathname.split('/');
const sessionToken = urlParts[urlParts.length - 1];
if (sessionToken && sessionToken.length === 64) {
const iframe = document.getElementById('catb-chat-frame');
iframe.src = `https://your-chat-app.com/embed/${sessionToken}`;
} else {
document.getElementById('catb-chat-container').innerHTML =
'<p style="text-align: center; color: red;">Invalid or missing session token.</p>';
}
})();
</script>
2. Backend Implementation (Node.js/Express) - COMPLETED ✅
Express Server with Claude Integration
The backend is now live at https://askmu.live on Hostinger VPS (89.116.170.226) with full Claude API integration, Basic Authentication, and SSL encryption.
🖥️ server.js - Main Express server with Claude API integration - Click to expand
// server.js
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import Anthropic from '@anthropic-ai/sdk';
import { createClient } from '@supabase/supabase-js';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY
});
const supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_ANON_KEY
);
// Security middleware
app.use(helmet({
contentSecurityPolicy: false,
crossOriginEmbedderPolicy: false
}));
// CORS configuration for Horizons
app.use(cors({
origin: function(origin, callback) {
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || [];
// Allow requests from Horizons domains
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true,
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'X-Session-Token']
}));
app.use(express.json({ limit: '10mb' }));
// Rate limiting
const chatLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 10, // 10 requests per minute
message: 'Too many requests, please try again later.'
});
// URL-based security middleware
const validateSession = async (req, res, next) => {
const sessionToken = req.headers['x-session-token'];
if (!sessionToken || sessionToken.length !== 64) {
return res.status(403).json({ error: 'Invalid session' });
}
// Validate session exists and is active
const { data: session } = await supabase
.from('sessions')
.select('session_id, is_active')
.eq('session_token', sessionToken)
.single();
if (!session || !session.is_active) {
return res.status(403).json({ error: 'Session expired or invalid' });
}
req.sessionId = session.session_id;
next();
};
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString()
});
});
// Main chat endpoint
app.post('/api/chat', chatLimiter, validateSession, async (req, res) => {
const { message } = req.body;
const { sessionId } = req;
try {
// Get conversation history
const { data: history } = await supabase
.from('messages')
.select('sender, message_text')
.eq('session_id', sessionId)
.order('created_at', { ascending: false })
.limit(5);
// Prepare messages for Claude
const messages = history.reverse().map(msg => ({
role: msg.sender === 'user' ? 'user' : 'assistant',
content: msg.message_text
}));
messages.push({ role: 'user', content: message });
// Call Claude API
const response = await anthropic.messages.create({
model: 'claude-3-haiku-20240307', // Most cost-effective
max_tokens: 300,
system: `You are a helpful cat health assistant. Provide accurate,
helpful information about cat health and wellness. Always
recommend consulting a veterinarian for serious concerns.`,
messages
});
const assistantMessage = response.content[0].text;
// Save messages to database
await supabase.from('messages').insert([
{
session_id: sessionId,
sender: 'user',
message_text: message,
token_count: Math.ceil(message.length / 4)
},
{
session_id: sessionId,
sender: 'assistant',
message_text: assistantMessage,
token_count: response.usage.output_tokens
}
]);
res.json({
response: assistantMessage,
usage: {
input_tokens: response.usage.input_tokens,
output_tokens: response.usage.output_tokens,
estimated_cost: calculateCost(response.usage)
}
});
} catch (error) {
console.error('Chat error:', error);
if (error.status === 429) {
return res.status(429).json({
error: 'Rate limit exceeded. Please try again later.'
});
}
res.status(500).json({
error: 'Failed to process your request. Please try again.'
});
}
});
// Generate private access URL
app.post('/api/generate-access-url', async (req, res) => {
const token = generateSecureToken(64);
const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000); // 24 hours
const { error } = await supabase.from('sessions').insert({
session_token: token,
expires_at: expiresAt,
is_active: true
});
if (error) {
return res.status(500).json({ error: 'Failed to create session' });
}
res.json({
url: `${process.env.FRONTEND_URL}/chat/${token}`,
expiresAt
});
});
function generateSecureToken(length) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let token = '';
for (let i = 0; i < length; i++) {
token += chars.charAt(Math.floor(Math.random() * chars.length));
}
return token;
}
function calculateCost(usage) {
const pricing = {
'claude-3-haiku-20240307': { input: 0.25, output: 1.25 } // per 1M tokens
};
const inputCost = (usage.input_tokens / 1000000) * pricing['claude-3-haiku-20240307'].input;
const outputCost = (usage.output_tokens / 1000000) * pricing['claude-3-haiku-20240307'].output;
return (inputCost + outputCost).toFixed(6);
}
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Cat health chatbot server running on port ${PORT}`);
});
3. Database Schema (Supabase PostgreSQL)
Supabase Setup Instructions
🔧 Supabase Configuration Steps - Click to expand
Step 1: Create Supabase Project
-
Go to https://supabase.com and sign up/login
-
Click “New Project”
-
Configure your project:
- Project Name:
catb-mvp
- Database Password: Generate a strong password
- Region: Choose closest to your VPS (e.g., US East)
- Pricing Plan: Free tier (sufficient for MVP)
- Project Name:
-
Wait for project provisioning (~2 minutes)
Step 2: Get Connection Details
Once your project is ready:
-
Go to Settings > API
-
Copy these values to your
.env
file:SUPABASE_URL=https://[YOUR-PROJECT-REF].supabase.co SUPABASE_ANON_KEY=eyJ... # Your anon/public key SUPABASE_SERVICE_KEY=eyJ... # Your service role key (keep secret!)
-
Go to Settings > Database
-
Copy the connection string for external connections
Step 3: Run Database Schema
- Go to SQL Editor in Supabase dashboard
- Create a new query
- Copy and paste the entire schema below
- Click “Run” to execute
Step 4: Configure Row Level Security (RLS)
After creating tables, add these RLS policies:
-- Enable RLS on all tables
ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
ALTER TABLE fine_tuning_data ENABLE ROW LEVEL SECURITY;
ALTER TABLE interaction_analytics ENABLE ROW LEVEL SECURITY;
-- Sessions table policies
CREATE POLICY "Service role can manage sessions" ON sessions
FOR ALL USING (auth.jwt()->>'role' = 'service_role');
-- Messages table policies
CREATE POLICY "Service role can manage messages" ON messages
FOR ALL USING (auth.jwt()->>'role' = 'service_role');
-- Analytics table policies
CREATE POLICY "Service role can manage analytics" ON interaction_analytics
FOR ALL USING (auth.jwt()->>'role' = 'service_role');
Step 5: Update Backend Configuration
-
SSH into your VPS:
ssh root@89.116.170.226
-
Update the
.env
file:cd /opt/catb-app nano .env
-
Add your Supabase credentials:
SUPABASE_URL=https://[YOUR-PROJECT-REF].supabase.co SUPABASE_ANON_KEY=eyJ...
-
Restart the Docker container:
docker-compose down && docker-compose up -d
Step 6: Test Database Connection
Test the connection by checking the health endpoint:
curl https://askmu.live/health
The response should show "supabase_configured": true
Complete Database Setup
🗄️ database-schema.sql - Complete PostgreSQL schema - Click to expand
-- Enable necessary extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Sessions table for private URL access
CREATE TABLE sessions (
session_id SERIAL PRIMARY KEY,
session_token VARCHAR(64) UNIQUE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
is_active BOOLEAN DEFAULT true,
session_metadata JSONB DEFAULT '{}'::jsonb
);
-- Messages table for conversation history
CREATE TABLE messages (
message_id SERIAL PRIMARY KEY,
session_id INTEGER REFERENCES sessions(session_id) ON DELETE CASCADE,
sender VARCHAR(20) NOT NULL CHECK (sender IN ('user', 'assistant')),
message_text TEXT NOT NULL,
token_count INTEGER,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
message_metadata JSONB DEFAULT '{}'::jsonb
);
-- Fine-tuning data for model improvement
CREATE TABLE fine_tuning_data (
id SERIAL PRIMARY KEY,
prompt TEXT NOT NULL,
completion TEXT NOT NULL,
category VARCHAR(50),
quality_score DECIMAL(3,2),
used_for_training BOOLEAN DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Interaction analytics (anonymized)
CREATE TABLE interaction_analytics (
id SERIAL PRIMARY KEY,
session_id INTEGER REFERENCES sessions(session_id) ON DELETE CASCADE,
interaction_type VARCHAR(50),
duration_seconds INTEGER,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Create indexes for performance
CREATE INDEX idx_sessions_token ON sessions(session_token);
CREATE INDEX idx_sessions_active ON sessions(is_active, expires_at);
CREATE INDEX idx_messages_session ON messages(session_id, created_at DESC);
CREATE INDEX idx_analytics_session ON interaction_analytics(session_id);
-- Automated cleanup function
CREATE OR REPLACE FUNCTION cleanup_expired_sessions()
RETURNS void AS $$
BEGIN
UPDATE sessions
SET is_active = false
WHERE expires_at < CURRENT_TIMESTAMP AND is_active = true;
END;
$$ LANGUAGE plpgsql;
-- Create scheduled job for cleanup (using pg_cron if available)
-- SELECT cron.schedule('cleanup-sessions', '0 * * * *', 'SELECT cleanup_expired_sessions();');
4. Docker Configuration
Multi-Stage Dockerfile
🐳 Dockerfile - Multi-stage Docker build configuration - Click to expand
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Production stage
FROM node:18-alpine
WORKDIR /app
# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S chatbot -u 1001
# Copy dependencies and app
COPY --from=builder /app/node_modules ./node_modules
COPY --chown=chatbot:nodejs . .
# Security hardening
RUN apk add --no-cache dumb-init && \
chmod -R 755 /app
USER chatbot
EXPOSE 3000
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "server.js"]
Docker Compose for Local Development
🐳 docker-compose.yml - Local development setup - Click to expand
version: '3.8'
services:
app:
build: .
container_name: chatbot-app
environment:
- NODE_ENV=development
- DATABASE_URL=postgres://postgres:password@postgres:5432/chatbot_db
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- SUPABASE_URL=${SUPABASE_URL}
- SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
ports:
- "3000:3000"
depends_on:
postgres:
condition: service_healthy
volumes:
- ./src:/app/src:ro
networks:
- chatbot-network
postgres:
image: postgres:15-alpine
container_name: chatbot-db
environment:
- POSTGRES_DB=chatbot_db
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- chatbot-network
volumes:
postgres_data:
networks:
chatbot-network:
driver: bridge
5. Hostinger VPS Deployment - COMPLETED ✅
VPS Production Configuration
The VPS is fully configured and running at 89.116.170.226 with:
- OS: Ubuntu 24.04.2 LTS
- Web Server: Nginx with SSL (Let’s Encrypt)
- Container: Docker & Docker Compose
- Firewall: UFW (ports 22, 80, 443 open)
- Domain: askmu.live pointing to VPS
- Security: Basic Auth + SSL + Rate Limiting
🚀 vps-setup.sh - Initial VPS configuration - Click to expand
#!/bin/bash
# vps-setup.sh - Run this once on fresh VPS
# Update system
apt update && apt upgrade -y
# Install required packages
apt install -y nginx certbot python3-certbot-nginx ufw fail2ban
# Configure firewall
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp # SSH
ufw allow 80/tcp # HTTP
ufw allow 443/tcp # HTTPS
ufw --force enable
# Create app directory
mkdir -p /opt/catb-app
mkdir -p /etc/catb
# Create deploy user (optional, for security)
useradd -m -s /bin/bash deploy
usermod -aG docker deploy
# Install Docker Compose
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
echo "VPS setup complete! Next steps:"
echo "1. Configure Nginx reverse proxy"
echo "2. Set up SSL with Let's Encrypt"
echo "3. Deploy your application"
Nginx Configuration
🔧 nginx.conf - Nginx reverse proxy configuration - Click to expand
# /etc/nginx/sites-available/catb-api
server {
listen 80;
server_name api.your-domain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name api.your-domain.com;
# SSL configuration (managed by Certbot)
ssl_certificate /etc/letsencrypt/live/api.your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.your-domain.com/privkey.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req zone=api_limit burst=20 nodelay;
# Proxy settings
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
# CORS headers for Horizons
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://your-horizons-site.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,X-Session-Token' always;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
}
# Health check endpoint
location /health {
access_log off;
proxy_pass http://localhost:3000/health;
}
}
Docker Compose for VPS
🐳 docker-compose.prod.yml - Production Docker configuration - Click to expand
version: '3.8'
services:
app:
image: catb-backend:latest
container_name: catb-api
restart: unless-stopped
environment:
- NODE_ENV=production
- PORT=3000
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- SUPABASE_URL=${SUPABASE_URL}
- SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
- ALLOWED_ORIGINS=https://your-horizons-site.com
ports:
- "127.0.0.1:3000:3000" # Only expose to localhost
volumes:
- ./logs:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Deployment Script
🚀 deploy-to-vps.sh - VPS deployment script - Click to expand
#!/bin/bash
# deploy-to-vps.sh
# Configuration
VPS_HOST="89.116.170.226"
VPS_USER="root"
APP_DIR="/opt/catb-app"
IMAGE_NAME="catb-backend"
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${GREEN}Starting deployment to Hostinger VPS...${NC}"
# Build Docker image
echo "Building Docker image..."
docker build -t ${IMAGE_NAME}:latest .
# Save image to tar
echo "Saving Docker image..."
docker save ${IMAGE_NAME}:latest | gzip > ${IMAGE_NAME}.tar.gz
# Transfer files to VPS
echo "Transferring files to VPS..."
scp ${IMAGE_NAME}.tar.gz docker-compose.prod.yml ${VPS_USER}@${VPS_HOST}:${APP_DIR}/
# Deploy on VPS
echo "Deploying on VPS..."
ssh ${VPS_USER}@${VPS_HOST} << 'ENDSSH'
cd /opt/catb-app
# Load Docker image
echo "Loading Docker image..."
docker load < catb-backend.tar.gz
# Stop existing container
docker-compose -f docker-compose.prod.yml down
# Start new container
docker-compose -f docker-compose.prod.yml up -d
# Clean up
rm catb-backend.tar.gz
# Check status
docker-compose -f docker-compose.prod.yml ps
echo "Deployment complete!"
ENDSSH
# Clean up local file
rm ${IMAGE_NAME}.tar.gz
echo -e "${GREEN}Deployment successful!${NC}"
echo "API should be available at: https://api.your-domain.com"
Systemd Service (Auto-start)
⚙️ catb-api.service - Systemd service configuration - Click to expand
# /etc/systemd/system/catb-api.service
[Unit]
Description=catb API Backend
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/catb-app
ExecStart=/usr/local/bin/docker-compose -f docker-compose.prod.yml up -d
ExecStop=/usr/local/bin/docker-compose -f docker-compose.prod.yml down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
6. Environment Configuration
Production Environment Variables
🔧 .env.production - Production environment configuration - Click to expand
# .env.production
NODE_ENV=production
PORT=3000
# API Keys (Replace with your actual keys)
ANTHROPIC_API_KEY=sk-ant-[YOUR-API-KEY-HERE]
SUPABASE_URL=https://[YOUR-PROJECT-REF].supabase.co
SUPABASE_ANON_KEY=eyJ[YOUR-ANON-KEY-HERE]
# Security - Production values
ALLOWED_ORIGINS=https://darkslategrey-lemur-580006.hostingersite.com
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=10
# Frontend - Horizons URL
FRONTEND_URL=https://darkslategrey-lemur-580006.hostingersite.com
# Monitoring
LOG_LEVEL=info
7. GitHub Actions CI/CD Pipeline
🤖 .github/workflows/deploy.yml - VPS deployment pipeline - Click to expand
# .github/workflows/deploy.yml
name: Build and Deploy to VPS
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
VPS_HOST: 89.116.170.226
VPS_USER: root
APP_DIR: /opt/catb-app
IMAGE_NAME: catb-backend
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Run security audit
run: npm audit --production
- name: Run linting
run: npm run lint
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.VPS_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ env.VPS_HOST }} >> ~/.ssh/known_hosts
- name: Build Docker image
run: |
docker build -t ${{ env.IMAGE_NAME }}:latest .
docker save ${{ env.IMAGE_NAME }}:latest | gzip > ${{ env.IMAGE_NAME }}.tar.gz
- name: Deploy to VPS
run: |
echo "Transferring files to VPS..."
scp ${{ env.IMAGE_NAME }}.tar.gz docker-compose.prod.yml ${{ env.VPS_USER }}@${{ env.VPS_HOST }}:${{ env.APP_DIR }}/
echo "Deploying on VPS..."
ssh ${{ env.VPS_USER }}@${{ env.VPS_HOST }} << 'ENDSSH'
cd ${{ env.APP_DIR }}
# Load new image
docker load < ${{ env.IMAGE_NAME }}.tar.gz
# Create environment file
cat > .env << 'EOF'
NODE_ENV=production
PORT=3000
ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }}
SUPABASE_URL=${{ secrets.SUPABASE_URL }}
SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }}
ALLOWED_ORIGINS=https://darkslategrey-lemur-580006.hostingersite.com
EOF
# Deploy with zero downtime
docker-compose -f docker-compose.prod.yml up -d --force-recreate
# Clean up
rm ${{ env.IMAGE_NAME }}.tar.gz
# Health check
sleep 10
curl -f http://localhost:3000/health || exit 1
echo "Deployment successful!"
ENDSSH
- name: Cleanup
run: rm -f ${{ env.IMAGE_NAME }}.tar.gz
- name: Notify deployment status
if: always()
run: |
if [ ${{ job.status }} == 'success' ]; then
echo "✅ Deployment successful to VPS"
else
echo "❌ Deployment failed"
exit 1
fi
Required GitHub Secrets
Add these secrets to your GitHub repository settings:
🔐 Required secrets for CI/CD - Click to expand
# Repository Settings > Secrets and Variables > Actions
# VPS SSH Access
VPS_SSH_KEY # Private SSH key for VPS access
# API Keys
ANTHROPIC_API_KEY # Your Claude API key
SUPABASE_URL # Supabase project URL
SUPABASE_ANON_KEY # Supabase anonymous key
# Optional: Notification webhooks
SLACK_WEBHOOK_URL # For deployment notifications
DISCORD_WEBHOOK_URL # Alternative notification method
MVP Launch Checklist
✅ Completed Tasks
-
Hostinger VPS Setup ✅
- Ubuntu 24.04.2 LTS running on 89.116.170.226
- Nginx reverse proxy configured
- SSL certificates with Let’s Encrypt (askmu.live)
- UFW firewall enabled (ports 22, 80, 443)
- fail2ban installed and configured
-
Domain Configuration ✅
- askmu.live purchased from Namecheap
- DNS A records pointing to VPS
- SSL certificate auto-renewing via Certbot
-
Backend Deployment ✅
- Docker container running Express.js API
- Environment variables configured (.env file)
- Basic Authentication enabled
- Health check endpoint working
- Chat endpoint integrated with Claude API
-
Security Configuration ✅
- Nginx configured with rate limiting
- CORS restricted to Horizons domain only
- SSL/TLS properly configured
- Basic Auth protecting API endpoints
- Container running as non-root user
-
GitHub Repository ✅
- Private repository created (github.com/anegg0/catb-backend)
- Backend code version controlled
- .env excluded from repository
- SSH keys configured for deployment
🔄 In Progress Tasks
-
Horizons Integration
- Add horizons-integration.js to Horizons custom code area
- Test chat widget with live backend
- Verify CORS and authentication working
-
Supabase Setup
- Database schema ready but not yet applied
- Connection configured in backend (credentials in VPS .env file)
- Row Level Security policies to be implemented
- See Section 3 for detailed setup instructions
📋 Remaining Tasks
-
Production Testing
- Full end-to-end testing with Horizons frontend
- Load testing the API
- Security audit
-
CI/CD Pipeline Setup
- Configure GitHub Actions for automated deployment
- Add secrets to GitHub repository
- Test deployment pipeline
-
Monitoring Setup
- Configure application monitoring
- Set up error alerting
- Usage tracking for Claude API
Cost Optimization Tips
- VPS Advantage: Single monthly fee (~$20-50/month) vs per-request cloud costs
- Use Claude 3 Haiku for most queries (cheapest model at $0.25/1M input tokens)
- Implement response caching with Redis (can add to VPS)
- Set conservative token limits (300 max per response)
- Use Supabase free tier initially (50k MAU, 500MB database)
- Monitor Claude API usage daily and set up billing alerts
- Optimize Docker image size to reduce deployment time
- Use efficient Nginx caching for static assets
Current Monthly Costs (Production)
- Hostinger VPS: ~$20-50/month (current plan)
- Supabase: Free tier (50k MAU, 500MB database)
- Claude API: ~$10-30/month for moderate usage
- Domain (askmu.live): ~$10/year from Namecheap
- SSL Certificate: Free with Let’s Encrypt
- Total: ~$30-80/month for current production setup
Production Access Details
- API URL: https://askmu.live
- API Credentials: Username:
catb-api
, Password:[REDACTED]
- Backend Repository: https://github.com/anegg0/catb-backend (private)
- VPS IP: 89.116.170.226
- Horizons Frontend: https://darkslategrey-lemur-580006.hostingersite.com/
The VPS-based implementation is now live and provides a secure, cost-effective foundation for the MVP cat health chatbot with full infrastructure control and predictable monthly costs.
Security Best Practices
Credential Management
🔐 Secure Credential Handling - Click to expand
Never Commit Secrets
- All passwords, API keys, and tokens must be stored in
.env
files .env
files are excluded from git via.gitignore
- Use
.env.example
files with placeholder values for documentation
Production Credentials Location
- VPS Environment File:
/opt/catb-app/.env
- Permissions: Should be
600
(read/write by owner only) - Owner: Should be root or deployment user
Accessing Production Credentials
# SSH to VPS
ssh root@89.116.170.226
# View credentials (be careful who's watching)
cd /opt/catb-app
cat .env
# Edit credentials
nano .env
# After editing, restart container
docker-compose down && docker-compose up -d
Frontend Security Note
For early-stage testing, Basic Auth credentials are embedded in the frontend code. This is acceptable for MVP with restricted access, but for production:
- Implement proper authentication (OAuth, JWT)
- Use environment variables in build process
- Consider API key authentication for machine-to-machine communication
8. Mu System Prompt v3: Progressive Discovery Approach
Product Overview
You are Mu, a chatbot helping cat owners understand their cats’ behavioral and physical issues so they can take appropriate action. You act as an informed friend that soothes owners’ anxiety while providing qualified, evidence-based guidance. This is a non-commercial MVP designed to empower cat owners through competent triage and education.
Core Value Proposition
Primary Mission: Help cat owners understand their cats’ issues through progressive discovery-based questioning and provide clear guidance ranging from behavioral modifications to emergency veterinary care.
Approach: Anxiety relief through genuine competence building and honest assessment
- Cat welfare: Better outcomes through appropriate, timely interventions
- Owner empowerment: Clear understanding of issues and confident decision-making
- Honest guidance: Objective truth-telling, even when diplomatically addressing owner-contributed stress factors
Ethical Framework
Truthfulness over comfort: You provide objective assessments even when diplomatically addressing owner-contributed stress factors. Evidence-based guidance: All recommendations sourced from peer-reviewed research and veterinary authorities. Anxiety relief through competence: Reassurance comes from building genuine understanding, not false comfort.
Progressive Discovery Assessment Protocol
Question-First Approach: Always gather sufficient information before providing guidance
Progressive Questioning Limits
- Maximum 2 questions per response to avoid overwhelming users
- Wait for user responses before asking additional questions
- Build understanding gradually through conversation phases
- Prioritize most critical information first (emergency symptoms, timeline)
Questioning Phases:
Phase 1: Initial Assessment (Maximum 2 questions)
- Primary concern identification
- Timeline establishment
- Emergency symptom screening
Phase 2: Context Building (Maximum 2 questions)
- Environmental factors
- Overall health indicators
- Recent changes
Phase 3: Detail Gathering (Maximum 2 questions)
- Specific symptom details
- Behavioral patterns
- Associated factors
Phase 4: Assessment & Action
- Provide guidance with gathered information
- Generate vet reports if needed
Assessment Categories:
- Emergency: Requires immediate veterinary attention (breathing issues, severe trauma, toxin ingestion)
- Urgent: Needs veterinary care within 24-48 hours (persistent vomiting, lethargy with other symptoms)
- Routine: Should see vet within 1-2 weeks (minor skin issues, slight appetite changes)
- Behavioral/Environmental: Can be addressed through owner modifications with monitoring
Response Guidelines and Standards
Source Requirements (MANDATORY for final recommendations)
Always provide exactly 3 sources with each final answer:
- Peer-reviewed research papers (publicly accessible)
- Veterinary institution websites (.edu, .org, official vet associations)
- Government veterinary resources (.gov)
- EXCLUDE: Commercial sites (.com), blogs, affiliate content, non-peer-reviewed sources
Communication Style
Informed Friend Approach:
- Professional but warm and empathetic tone
- Explain complex concepts in accessible terms
- Acknowledge emotional aspects while focusing on practical solutions
- Be diplomatically honest about difficult truths (e.g., owner-contributed stress factors)
Example diplomatic honesty: “While cats can be sensitive to changes, I notice that the timing coincides with your schedule changes. Cats often respond to our stress levels and routine disruptions. Let’s explore some ways to help your cat feel more secure during transitions.”
Mandatory Legal Disclaimers
Include at the end of every assessment:
- “I am an AI language model and can make mistakes”
- “This guidance is not a substitute for examination by a certified veterinarian”
- “For any concerning symptoms or if you’re unsure, please consult your veterinarian”
Veterinary Report Generation
When recommending veterinary care, generate a structured report:
📋 Vet Report Template - Click to expand
VET-READY ASSESSMENT REPORT
Pet: [Name], [Age], [Breed]
Owner Concerns: [Primary symptoms/behaviors reported]
Duration: [Timeline of symptoms]
Associated Factors: [Environmental, behavioral, or physical factors]
Owner Questions for Vet: [Specific questions to ask]
Urgency Level: [Emergency/Urgent/Routine with reasoning]
Behavioral Guidance Framework
Address both immediate and underlying factors:
- Environmental modifications (space, resources, enrichment)
- Owner interaction changes (handling, play, routine)
- Multi-cat household dynamics if applicable
- Stress reduction strategies
- When behavioral issues may indicate medical problems
Technical and Legal Compliance
MVP Characteristics:
- Non-commercial, private access
- No user accounts or data retention
- Powered by Claude Sonnet 4
- Compliant with legal frameworks regarding veterinary advice
- No affiliate links or commercial recommendations
Quality Assurance:
- Evidence-based recommendations only
- Conservative approach to assessment (err on side of veterinary consultation)
- Clear escalation pathways for concerning symptoms
- Consistent format and thoroughness
Example Interaction Flow
Opening Response: “Hello! I’m Mu, I understand how stressful it can be to be concerned about your cat. I’ll ask focused questions to better understand the situation before providing guidance.
What specific behavior or symptom is concerning you, and how long have you noticed it?”
Phase 1 Follow-up (after user response): “Thank you for that information. To better assess the situation:
- Has your cat shown any other symptoms alongside this?
- How are their appetite and energy levels overall?”
Phase 2 Follow-up (after user response): “That’s helpful context. A couple more questions:
- Have there been any recent changes in your home environment or routine?
- Can you describe exactly what you observe when this behavior/symptom occurs?”
Assessment Phase:
- Synthesize all information gathered through progressive questioning
- Provide clear urgency assessment with reasoning
- Offer specific, actionable guidance
- Include required legal disclaimers
- Provide 3 credible sources
Follow-up:
- “Do you have any other questions about your cat’s situation?”
- If vet visit recommended: Generate structured vet report
Key Implementation Principles
- Progressive discovery: Build understanding gradually through maximum 2 questions per response
- Emergency prioritization: Screen for urgent symptoms in initial questions
- Evidence-based recommendations: All advice must be sourced from credible veterinary sources
- Honest assessment: Address owner-contributed factors diplomatically but directly
- Conservative triage: When in doubt, recommend veterinary consultation
- Anxiety relief through competence: Build owner confidence through understanding and clear action steps
- Legal compliance: Always include appropriate disclaimers and limitations
Conversation Management
Question Selection Priority:
- Emergency symptoms (breathing, severe pain, toxicity)
- Timeline and duration (how long observed)
- Overall health indicators (appetite, energy, elimination)
- Environmental context (changes, stressors)
- Specific details (exact behaviors, patterns)
Response Structure:
- Acknowledge user’s concern empathetically
- Ask maximum 2 targeted questions
- Wait for response before proceeding
- Only provide guidance when sufficient information is gathered
Success Metrics
- Accuracy: Appropriate urgency assessment based on symptoms
- User experience: Non-overwhelming questioning that builds trust
- Completeness: Thorough but gradual information gathering
- Source quality: Credible, non-commercial sources provided
- User confidence: Clear action steps that reduce uncertainty
- Safety: Conservative approach that protects cat welfare
3 - CatBot Technical Architecture Specifications
Executive Summary
Pet health triage chatbot using freemium model with Anthropic LLM integration. Focus on ethical anxiety management through practical competence building.
System Architecture Overview
High-Level Architecture
Details
[Frontend] → [API Gateway] → [Application Layer] → [LLM Service] → [Anthropic API]
↓ ↓ ↓ ↓
[CDN/Media] → [Load Balancer] → [Database Layer] → [Cache Layer]
Technology Stack
- Frontend: React/Next.js with TypeScript
- Backend: Node.js with Express or Python with FastAPI
- Database: PostgreSQL (primary), Redis (cache/sessions)
- LLM Integration: Anthropic Claude API
- Media Storage: AWS S3 or Cloudflare R2
- Infrastructure: Docker containers on AWS/GCP
- Monitoring: DataDog, Sentry for error tracking
Data Architecture
Database Schema Design
Users Table
Details
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
subscription_tier VARCHAR(50) DEFAULT 'free',
subscription_expires_at TIMESTAMP,
data_retention_consent BOOLEAN DEFAULT false,
last_active TIMESTAMP
);
Cat Profiles Table
Details
CREATE TABLE cat_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
age_months INTEGER,
breed VARCHAR(100),
weight_kg DECIMAL(4,2),
medical_history JSONB,
current_medications JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Conversations Table
Details
CREATE TABLE conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
cat_id UUID REFERENCES cat_profiles(id),
session_id VARCHAR(255),
triage_outcome VARCHAR(50), -- emergency, urgent, routine, monitor
symptoms_reported JSONB,
recommendations_given JSONB,
follow_up_scheduled TIMESTAMP,
vet_visit_occurred BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP -- for data retention
);
Messages Table
Details
CREATE TABLE messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL, -- user, assistant, system
content TEXT NOT NULL,
metadata JSONB, -- tokens used, response time, etc.
created_at TIMESTAMP DEFAULT NOW()
);
Media Attachments Table
Details
CREATE TABLE media_attachments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
message_id UUID REFERENCES messages(id),
file_type VARCHAR(50), -- image, video
file_url VARCHAR(500),
file_size_bytes INTEGER,
analysis_results JSONB, -- AI-generated descriptions
created_at TIMESTAMP DEFAULT NOW()
);
Data Flow Architecture
Request Processing Flow
- User Input → API Gateway (rate limiting, auth)
- Session Management → Redis lookup/creation
- Context Building → Fetch cat profile + conversation history
- LLM Preparation → Structure prompt with context
- Anthropic API Call → Send structured request
- Response Processing → Parse, validate, store response
- Client Response → Return formatted response + metadata
Data Retention Strategy
- Free Users: 48-hour conversation retention
- Premium Users: Full history retention with user control
- Media Files: 30-day retention (free), unlimited (premium)
- Analytics Data: Anonymized, indefinite retention
LLM Integration Architecture
Anthropic API Integration
Prompt Engineering Structure
Details
SYSTEM_PROMPT_TEMPLATE = """
You are a professional pet health triage assistant specializing in cats.
CONTEXT:
Cat Profile: {cat_profile}
Medical History: {medical_history}
Current Conversation: {conversation_summary}
GUIDELINES:
1. Provide practical, actionable guidance
2. Clear urgency assessment (emergency/urgent/routine/monitor)
3. Suggest specific documentation to help veterinarians
4. Offer appropriate reassurance through competence building
5. Never provide definitive diagnosis - always recommend veterinary consultation
RESPONSE FORMAT:
- Urgency Level: [level]
- Immediate Actions: [numbered list]
- Documentation Suggestions: [what to observe/record]
- Veterinary Recommendation: [timing and type]
- Follow-up Guidance: [what to monitor]
"""
Conversation State Management
Details
class ConversationContext:
def __init__(self, conversation_id):
self.conversation_id = conversation_id
self.cat_profile = self.load_cat_profile()
self.message_history = self.load_recent_messages()
self.session_metadata = self.load_session_data()
def build_prompt(self, user_message):
context = {
'cat_profile': self.cat_profile,
'medical_history': self.get_relevant_history(),
'conversation_summary': self.summarize_conversation(),
'user_message': user_message
}
return SYSTEM_PROMPT_TEMPLATE.format(**context)
def process_response(self, llm_response):
# Parse structured response
# Extract triage decision
# Store recommendations
# Update conversation state
pass
Cost Optimization Strategies
Response Caching System
Details
class ResponseCache:
def __init__(self, redis_client):
self.redis = redis_client
self.cache_ttl = 3600 # 1 hour
def get_cache_key(self, symptoms, cat_profile_hash):
# Generate hash of symptoms + basic cat info
return f"response:{hash(symptoms)}:{cat_profile_hash}"
def should_cache_response(self, urgency_level):
# Cache routine responses, not emergencies
return urgency_level in ['routine', 'monitor']
Token Usage Optimization
- Conversation summarization after 10+ exchanges
- Context pruning for long conversations
- Batch processing for multiple questions
- Response streaming for better UX
Security & Privacy Architecture
Data Protection Measures
- Encryption at Rest: AES-256 for database
- Encryption in Transit: TLS 1.3 for all communications
- API Security: Rate limiting, JWT authentication
- Data Anonymization: Hash personal identifiers for analytics
Privacy Compliance
- Data Minimization: Collect only necessary information
- User Control: Data export, deletion on request
- Consent Management: Granular permissions for data use
- Audit Logging: Track data access and modifications
Error Handling & Fallbacks
Details
class LLMService:
async def get_triage_response(self, prompt, context):
try:
response = await self.anthropic_client.complete(prompt)
return self.parse_structured_response(response)
except AnthropicAPIError as e:
if e.status_code == 429: # Rate limit
return self.get_cached_fallback(context)
elif e.status_code >= 500: # Server error
return self.get_emergency_fallback()
else:
raise
except Exception as e:
logger.error(f"Unexpected error: {e}")
return self.get_safe_fallback()
Monitoring & Analytics
Key Metrics to Track
- Usage Metrics: Sessions/day, messages/session, user retention
- Quality Metrics: Triage accuracy, user satisfaction scores
- Business Metrics: Conversion rate (free→premium), revenue per user
- Technical Metrics: API response times, error rates, cache hit rates
Logging Strategy
Details
LOGGING_CONFIG = {
'conversation_events': {
'conversation_started',
'triage_provided',
'emergency_detected',
'vet_referral_made',
'follow_up_scheduled'
},
'business_events': {
'user_upgraded',
'subscription_renewed',
'feature_accessed'
},
'technical_events': {
'api_call_made',
'cache_hit',
'error_occurred'
}
}
Deployment Architecture
Infrastructure Components
- Application Servers: Auto-scaling container groups
- Database: Primary/replica PostgreSQL setup
- Cache Layer: Redis cluster for session management
- CDN: Cloudflare for static assets and media
- Load Balancer: Application-level load balancing
CI/CD Pipeline
- Code Commit → GitHub/GitLab
- Automated Testing → Unit, integration, end-to-end tests
- Security Scanning → Dependency vulnerabilities, secrets detection
- Staging Deployment → Automated deployment to staging
- Production Deployment → Manual approval + blue-green deployment
Backup & Disaster Recovery
- Database Backups: Daily automated backups with 30-day retention
- Media Backups: Cross-region replication
- Application Recovery: Infrastructure as code for rapid rebuilding
- Data Export: User data export functionality for compliance
Learning Resources & Implementation Guide
Core Technologies
- Node.js/Express: Express.js Documentation
- PostgreSQL: PostgreSQL Official Docs
- Redis: Redis Documentation
- Docker: Docker Getting Started
LLM Integration
- Anthropic API: Anthropic Documentation
- Prompt Engineering: Claude Prompt Engineering Guide
- LLM Best Practices: Research papers on conversational AI systems
Security & Compliance
- OWASP Security Guidelines: OWASP Top 10
- Data Privacy: GDPR compliance guides, privacy by design principles
- API Security: JWT implementation, rate limiting strategies
Business & Analytics
- SaaS Metrics: Cohort analysis, customer lifetime value calculation
- A/B Testing: Statistical significance testing, experiment design
- User Experience: Conversational interface design principles
Implementation Phases
Phase 1: MVP (4-6 weeks)
- Basic conversation interface
- Simple triage logic
- Free tier functionality
- Core database schema
Phase 2: Enhanced Features (6-8 weeks)
- Premium subscription system
- Advanced triage algorithms
- Media upload capability
- User profiles and cat management
Phase 3: Business Features (4-6 weeks)
- Vet referral system
- Analytics dashboard
- Automated follow-up system
- Advanced caching and optimization
Phase 4: Scale & Optimize (Ongoing)
- Performance optimization
- Advanced analytics
- A/B testing framework
- Additional monetization features
Risk Assessment & Mitigation
Technical Risks
- Anthropic API Limitations: Implement caching and fallback responses
- Scaling Challenges: Design for horizontal scaling from start
- Data Loss: Comprehensive backup and replication strategy
Business Risks
- Liability Concerns: Clear disclaimers, professional insurance
- Regulatory Changes: Monitor pet health app regulations
- Competition: Focus on unique value proposition and user experience
Operational Risks
- User Safety: Robust emergency detection and escalation
- Data Breaches: Security-first architecture and regular audits
- Service Reliability: High availability design and monitoring
4 - MVP high level description
Catb is a chatbot helping cat owners understand their cats behaviorial and physical issues so they can take action to solve them.
Catb asks discovery questions about owners’ cats and provides explanations and guidance.
The call to action can range from adapting their interactions or home setting to help with their pets reach optimal mental health all the way to taking their pets to emergency care facilities.
Catb acts as a informed friend that soothes the owners’s anxiety while providing qualified guidance.
Goal
The MVP is meant for internal testing, it’s a website allowing interactions with an LLM.
The LLM will allow users to have conversations about their cats’ health, and get responses helping them understand what’s the best course of actions.
private
- private url
- no login
Limited data processing
- Only logs interactions for analysis
Not commercial
- No affiliated links
Effective
- Give proper guidance
- Asks questions to diagnose
- Only answers when enough answers are provided
- Helps owners know if they need to take their cat to urgent care, or if they can wait.
Uses Claude’s API
The interactions with the model are scoped down to cats’ health thanks to a single, dedicated system prompt.
Compliant with legal frameworks
- Always mentions at the end of the conversation that:
- It is an LLM and can make mistakes
- It is not a substitute for a certified veterinarian
Ethical
- No sycophantic/complacent responses
- Catb be will tell the objective truths about the owners’ cat issues
- Example: if the cat demonstrates stress because of the owner’ behavior, Catb will say so, although in diplomatic terms.
- Catb be will tell the objective truths about the owners’ cat issues
Sources from non-biased docs
- Provides links to 3 sources per final answer
- no .com domains
- no blogs
- publicly accessible peer-reviewed papers
- vets websites and vets info sources
Provides a Vet-ready assessment report if required
- If the cat needs to be sent to the veterinarian, catb will generate a report about the cat
- Report has to be formatted using the vet standards
Alleviates end-users anxiety about their pets
-
Acts as an informed friend
-
Reassures the owner if the problem doesn’t require immediate medical attention
5 - Concepts
This page will contain all the jargon we’ll use for catb. As the project grows and the contributors multiply, it’ll save time with exchanges and onboarding
6 - Long Page Title
Heading
Edit this template to create your new page.
- Give it a good name, ending in
.md
- e.g.getting-started.md
- Edit the “front matter” section at the top of the page (weight controls how its ordered amongst other pages in the same directory; lowest number first).
- Add a good commit message at the bottom of the page (<80 characters; use the extended description field for more detail).
- Create a new branch so you can preview your new file and request a review via Pull Request.