From 79ec515b98f8e90ac7a4b8402b0849183c9d0b6a Mon Sep 17 00:00:00 2001 From: Timo Knuth Date: Wed, 4 Feb 2026 09:58:52 +0100 Subject: [PATCH] alles andere --- .dockerignore | 15 + .env.example | 126 +++ .gitignore | 52 ++ docs/deployment-guide.md | 522 ++++++++++++ docs/workflow-specifications.md | 565 +++++++++++++ infra/docker/dashboard.Dockerfile | 24 + infra/docker/docker-compose.yml | 148 ++++ infra/docker/orchestrator.Dockerfile | 32 + package.json | 36 + packages/orchestrator/package.json | 44 + packages/orchestrator/prisma/schema.prisma | 263 ++++++ .../orchestrator/src/decision-engine/rules.ts | 501 +++++++++++ packages/orchestrator/src/index.ts | 51 ++ .../src/integrations/ads/facebook-ads.ts | 110 +++ .../src/integrations/ads/google-ads.ts | 87 ++ .../analytics/google-analytics.ts | 67 ++ .../src/integrations/claude/claude-client.ts | 359 ++++++++ .../skills/conversion-optimization-expert.md | 585 +++++++++++++ .../claude/skills/facebook-ads-expert-2026.md | 721 ++++++++++++++++ .../claude/skills/facebook-ads-expert.ts | 71 ++ .../claude/skills/google-ads-expert-2026.md | 794 ++++++++++++++++++ .../claude/skills/google-ads-expert.ts | 70 ++ .../skills/growth-hacking-expert-2026.md | 688 +++++++++++++++ .../claude/skills/market-research-expert.md | 283 +++++++ .../claude/skills/mvp-architect-expert.md | 580 +++++++++++++ .../claude/skills/saas-metrics-expert-2026.md | 600 +++++++++++++ .../claude/skills/seo-aeo-geo-expert-2026.md | 717 ++++++++++++++++ .../integrations/claude/skills/seo-expert.ts | 65 ++ .../src/integrations/deploy/vercel-deploy.ts | 196 +++++ .../src/integrations/email/sendgrid-client.ts | 87 ++ .../integrations/marketplace/acquire-com.ts | 87 ++ .../integrations/marketplace/upwork-api.ts | 73 ++ .../orchestrator/src/monitoring/alerts.ts | 268 ++++++ .../orchestrator/src/monitoring/logger.ts | 163 ++++ .../orchestrator/src/monitoring/metrics.ts | 224 +++++ packages/orchestrator/src/orchestrator.ts | 308 +++++++ packages/orchestrator/src/utils/config.ts | 208 +++++ packages/orchestrator/src/utils/validators.ts | 68 ++ .../src/workflows/01-market-validation.ts | 280 ++++++ .../src/workflows/02-mvp-development.ts | 214 +++++ .../src/workflows/03-landing-page-seo.ts | 103 +++ .../orchestrator/src/workflows/04-paid-ads.ts | 183 ++++ .../src/workflows/05-content-marketing.ts | 65 ++ .../src/workflows/06-email-automation.ts | 81 ++ .../src/workflows/07-analytics-setup.ts | 90 ++ .../src/workflows/08-optimization-loop.ts | 224 +++++ .../src/workflows/workflow-base.ts | 238 ++++++ .../src/workflows/workflow-executor.ts | 181 ++++ packages/orchestrator/tsconfig.json | 24 + packages/shared/package.json | 14 + packages/shared/src/index.ts | 3 + packages/shared/src/types/business.ts | 61 ++ packages/shared/src/types/metrics.ts | 61 ++ packages/shared/src/types/workflow.ts | 44 + packages/shared/tsconfig.json | 19 + pnpm-workspace.yaml | 2 + turbo.json | 23 + 57 files changed, 11768 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 docs/deployment-guide.md create mode 100644 docs/workflow-specifications.md create mode 100644 infra/docker/dashboard.Dockerfile create mode 100644 infra/docker/docker-compose.yml create mode 100644 infra/docker/orchestrator.Dockerfile create mode 100644 package.json create mode 100644 packages/orchestrator/package.json create mode 100644 packages/orchestrator/prisma/schema.prisma create mode 100644 packages/orchestrator/src/decision-engine/rules.ts create mode 100644 packages/orchestrator/src/index.ts create mode 100644 packages/orchestrator/src/integrations/ads/facebook-ads.ts create mode 100644 packages/orchestrator/src/integrations/ads/google-ads.ts create mode 100644 packages/orchestrator/src/integrations/analytics/google-analytics.ts create mode 100644 packages/orchestrator/src/integrations/claude/claude-client.ts create mode 100644 packages/orchestrator/src/integrations/claude/skills/conversion-optimization-expert.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert-2026.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert.ts create mode 100644 packages/orchestrator/src/integrations/claude/skills/google-ads-expert-2026.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/google-ads-expert.ts create mode 100644 packages/orchestrator/src/integrations/claude/skills/growth-hacking-expert-2026.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/market-research-expert.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/mvp-architect-expert.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/saas-metrics-expert-2026.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/seo-aeo-geo-expert-2026.md create mode 100644 packages/orchestrator/src/integrations/claude/skills/seo-expert.ts create mode 100644 packages/orchestrator/src/integrations/deploy/vercel-deploy.ts create mode 100644 packages/orchestrator/src/integrations/email/sendgrid-client.ts create mode 100644 packages/orchestrator/src/integrations/marketplace/acquire-com.ts create mode 100644 packages/orchestrator/src/integrations/marketplace/upwork-api.ts create mode 100644 packages/orchestrator/src/monitoring/alerts.ts create mode 100644 packages/orchestrator/src/monitoring/logger.ts create mode 100644 packages/orchestrator/src/monitoring/metrics.ts create mode 100644 packages/orchestrator/src/orchestrator.ts create mode 100644 packages/orchestrator/src/utils/config.ts create mode 100644 packages/orchestrator/src/utils/validators.ts create mode 100644 packages/orchestrator/src/workflows/01-market-validation.ts create mode 100644 packages/orchestrator/src/workflows/02-mvp-development.ts create mode 100644 packages/orchestrator/src/workflows/03-landing-page-seo.ts create mode 100644 packages/orchestrator/src/workflows/04-paid-ads.ts create mode 100644 packages/orchestrator/src/workflows/05-content-marketing.ts create mode 100644 packages/orchestrator/src/workflows/06-email-automation.ts create mode 100644 packages/orchestrator/src/workflows/07-analytics-setup.ts create mode 100644 packages/orchestrator/src/workflows/08-optimization-loop.ts create mode 100644 packages/orchestrator/src/workflows/workflow-base.ts create mode 100644 packages/orchestrator/src/workflows/workflow-executor.ts create mode 100644 packages/orchestrator/tsconfig.json create mode 100644 packages/shared/package.json create mode 100644 packages/shared/src/index.ts create mode 100644 packages/shared/src/types/business.ts create mode 100644 packages/shared/src/types/metrics.ts create mode 100644 packages/shared/src/types/workflow.ts create mode 100644 packages/shared/tsconfig.json create mode 100644 pnpm-workspace.yaml create mode 100644 turbo.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2ac35f8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +node_modules +.next +dist +build +.git +.gitignore +.env +.env.* +*.log +logs +coverage +.vscode +.idea +README.md +.turbo diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cbce911 --- /dev/null +++ b/.env.example @@ -0,0 +1,126 @@ +# ============================================ +# DATABASE CONFIGURATION +# ============================================ +DATABASE_URL="postgresql://srb:srb_password@localhost:5432/srb" +REDIS_URL="redis://localhost:6379" + +# ============================================ +# CLAUDE API (REQUIRED) +# ============================================ +# Get your API key from: https://console.anthropic.com/ +ANTHROPIC_API_KEY="sk-ant-..." + +# ============================================ +# FACEBOOK ADS API +# ============================================ +# Set up at: https://developers.facebook.com/ +FACEBOOK_APP_ID="" +FACEBOOK_APP_SECRET="" +FACEBOOK_ACCESS_TOKEN="" +FACEBOOK_AD_ACCOUNT_ID="" + +# ============================================ +# GOOGLE ADS API +# ============================================ +# Set up at: https://developers.google.com/google-ads/api/ +GOOGLE_ADS_CLIENT_ID="" +GOOGLE_ADS_CLIENT_SECRET="" +GOOGLE_ADS_REFRESH_TOKEN="" +GOOGLE_ADS_DEVELOPER_TOKEN="" +GOOGLE_ADS_CUSTOMER_ID="" + +# ============================================ +# EMAIL SERVICE (SENDGRID) +# ============================================ +# Get API key from: https://app.sendgrid.com/ +SENDGRID_API_KEY="" +SENDGRID_FROM_EMAIL="noreply@yourdomain.com" +SENDGRID_FROM_NAME="Self-Replicating Business" + +# ============================================ +# GOOGLE ANALYTICS +# ============================================ +GOOGLE_ANALYTICS_PROPERTY_ID="" +GOOGLE_ANALYTICS_MEASUREMENT_ID="" + +# ============================================ +# DEPLOYMENT (VERCEL) +# ============================================ +# Get token from: https://vercel.com/account/tokens +VERCEL_TOKEN="" +VERCEL_ORG_ID="" +VERCEL_PROJECT_ID="" + +# ============================================ +# MARKETPLACE APIs +# ============================================ +# Acquire.com API (for selling businesses) +ACQUIRE_COM_API_KEY="" + +# Upwork API (for hiring VAs) +UPWORK_API_KEY="" +UPWORK_API_SECRET="" +UPWORK_ACCESS_TOKEN="" + +# ============================================ +# DECISION ENGINE THRESHOLDS +# ============================================ +# Revenue threshold to trigger scaling (hire VA, increase budget) +REVENUE_SCALE_THRESHOLD=10000 + +# Revenue threshold to trigger exit (list on Acquire.com) +REVENUE_SELL_THRESHOLD=50000 + +# Revenue threshold for shutdown consideration +REVENUE_SHUTDOWN_THRESHOLD=1000 + +# Months to wait before shutdown if below threshold +SHUTDOWN_WAIT_MONTHS=6 + +# ============================================ +# BUDGET LIMITS (SAFETY) +# ============================================ +# Maximum monthly ad spend per business +MAX_AD_SPEND_PER_BUSINESS=5000 + +# Maximum total budget for validation phase +MAX_VALIDATION_BUDGET=100 + +# Maximum total budget for MVP development +MAX_MVP_BUDGET=500 + +# ============================================ +# NOTIFICATION SETTINGS +# ============================================ +# Slack webhook for alerts +SLACK_WEBHOOK_URL="" + +# Email for critical alerts +ALERT_EMAIL="" + +# ============================================ +# GOOGLE TRENDS & SEARCH +# ============================================ +# For market validation +GOOGLE_SEARCH_API_KEY="" +GOOGLE_SEARCH_ENGINE_ID="" + +# ============================================ +# N8N CONFIGURATION +# ============================================ +N8N_BASIC_AUTH_ACTIVE=true +N8N_BASIC_AUTH_USER=admin +N8N_BASIC_AUTH_PASSWORD=change_this_password + +# ============================================ +# APPLICATION SETTINGS +# ============================================ +NODE_ENV=development +PORT=3000 +LOG_LEVEL=info + +# How often to run optimization loop (in minutes) +OPTIMIZATION_INTERVAL_MINUTES=1440 # Daily + +# How often to evaluate decisions (in minutes) +DECISION_EVALUATION_INTERVAL_MINUTES=1440 # Daily diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9f3ee2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# Dependencies +node_modules/ +.pnpm-store/ + +# Environment variables +.env +.env.local +.env.*.local + +# Build outputs +dist/ +build/ +.next/ +.turbo/ + +# Logs +logs/ +*.log +npm-debug.log* +pnpm-debug.log* + +# Database +*.db +*.sqlite + +# Prisma +packages/orchestrator/prisma/migrations/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Data +data/businesses/*/ +!data/businesses/.gitkeep +data/templates/*.generated.* + +# Testing +coverage/ +.vitest/ + +# Temporary files +tmp/ +temp/ +*.tmp diff --git a/docs/deployment-guide.md b/docs/deployment-guide.md new file mode 100644 index 0000000..32c1c7f --- /dev/null +++ b/docs/deployment-guide.md @@ -0,0 +1,522 @@ +# Deployment Guide + +Complete guide for deploying the Self-Replicating Business System to production. + +## Production Deployment Options + +### Option 1: Single VPS (Recommended for Start) + +**Specifications**: +- 4 vCPU +- 8GB RAM +- 160GB SSD +- Ubuntu 22.04 LTS + +**Providers**: +- DigitalOcean ($48/month) +- Hetzner ($35/month) +- Linode ($48/month) + +### Option 2: Kubernetes (For Scale) + +For managing 10+ businesses simultaneously. + +## Step-by-Step Production Deployment + +### 1. Server Setup + +```bash +# SSH into your VPS +ssh root@your-server-ip + +# Update system +apt update && apt upgrade -y + +# Install Docker +curl -fsSL https://get.docker.com -o get-docker.sh +sh get-docker.sh + +# Install Docker Compose +apt install docker-compose-plugin -y + +# Install Node.js +curl -fsSL https://deb.nodesource.com/setup_20.x | bash - +apt install -y nodejs + +# Install pnpm +npm install -g pnpm +``` + +### 2. Clone Repository + +```bash +# Create application directory +mkdir -p /opt/srb +cd /opt/srb + +# Clone repository (or upload files) +git clone . + +# Or upload via SCP +# scp -r self-replicating-business/* root@your-server:/opt/srb/ +``` + +### 3. Configure Environment + +```bash +# Copy environment template +cp .env.example .env + +# Edit with production values +nano .env +``` + +**Critical Production Settings**: + +```env +# Set to production +NODE_ENV=production + +# Use strong passwords +POSTGRES_PASSWORD= + +# Production database URL +DATABASE_URL=postgresql://srb:@postgres:5432/srb + +# All your API keys +ANTHROPIC_API_KEY=sk-ant-... +FACEBOOK_ACCESS_TOKEN=... +GOOGLE_ADS_DEVELOPER_TOKEN=... +# ... etc + +# Production alerts +SLACK_WEBHOOK_URL=https://hooks.slack.com/services/... +ALERT_EMAIL=alerts@yourdomain.com + +# n8n auth +N8N_BASIC_AUTH_USER=admin +N8N_BASIC_AUTH_PASSWORD= +``` + +### 4. Start Services + +```bash +# Build and start all services +docker-compose -f infra/docker/docker-compose.yml up -d + +# Check status +docker ps + +# View logs +docker-compose -f infra/docker/docker-compose.yml logs -f +``` + +### 5. Initialize Database + +```bash +# Run migrations +docker exec srb-orchestrator pnpm db:migrate + +# Verify database +docker exec -it srb-postgres psql -U srb -d srb -c "\dt" +``` + +### 6. SSL/TLS Setup + +Using Nginx reverse proxy with Let's Encrypt: + +```bash +# Install Nginx +apt install nginx certbot python3-certbot-nginx -y + +# Create Nginx config +nano /etc/nginx/sites-available/srb +``` + +**Nginx Configuration**: + +```nginx +server { + listen 80; + server_name yourdomain.com; + + # Orchestrator API + 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_cache_bypass $http_upgrade; + } + + # Dashboard + location /dashboard { + proxy_pass http://localhost:3001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + + # n8n + location /n8n { + proxy_pass http://localhost:5678; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} +``` + +```bash +# Enable site +ln -s /etc/nginx/sites-available/srb /etc/nginx/sites-enabled/ + +# Test config +nginx -t + +# Restart Nginx +systemctl restart nginx + +# Get SSL certificate +certbot --nginx -d yourdomain.com + +# Auto-renewal +systemctl enable certbot.timer +``` + +### 7. Systemd Service (Auto-restart) + +Create `/etc/systemd/system/srb.service`: + +```ini +[Unit] +Description=Self-Replicating Business System +After=docker.service +Requires=docker.service + +[Service] +Type=oneshot +RemainAfterExit=yes +WorkingDirectory=/opt/srb +ExecStart=/usr/bin/docker-compose -f infra/docker/docker-compose.yml up -d +ExecStop=/usr/bin/docker-compose -f infra/docker/docker-compose.yml down + +[Install] +WantedBy=multi-user.target +``` + +```bash +# Enable service +systemctl enable srb.service +systemctl start srb.service + +# Check status +systemctl status srb.service +``` + +### 8. Monitoring Setup + +```bash +# Install monitoring tools +apt install prometheus grafana -y + +# Configure Prometheus +nano /etc/prometheus/prometheus.yml +``` + +**Prometheus Config**: + +```yaml +scrape_configs: + - job_name: 'srb-orchestrator' + static_configs: + - targets: ['localhost:3000'] + + - job_name: 'postgres' + static_configs: + - targets: ['localhost:5432'] + + - job_name: 'redis' + static_configs: + - targets: ['localhost:6379'] +``` + +```bash +# Start monitoring +systemctl start prometheus grafana-server +systemctl enable prometheus grafana-server + +# Access Grafana at http://your-server:3000 +``` + +### 9. Backup Setup + +```bash +# Create backup script +nano /opt/srb/scripts/backup.sh +``` + +**Backup Script**: + +```bash +#!/bin/bash + +BACKUP_DIR="/opt/srb/backups" +DATE=$(date +%Y%m%d_%H%M%S) + +# Create backup directory +mkdir -p $BACKUP_DIR + +# Backup database +docker exec srb-postgres pg_dump -U srb srb > $BACKUP_DIR/db_$DATE.sql + +# Backup business data +tar -czf $BACKUP_DIR/data_$DATE.tar.gz /opt/srb/data + +# Upload to S3 (optional) +# aws s3 cp $BACKUP_DIR/db_$DATE.sql s3://your-bucket/backups/ + +# Delete old backups (keep last 30 days) +find $BACKUP_DIR -name "*.sql" -mtime +30 -delete +find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete + +echo "Backup completed: $DATE" +``` + +```bash +# Make executable +chmod +x /opt/srb/scripts/backup.sh + +# Add to crontab (daily at 2 AM) +crontab -e +# Add: 0 2 * * * /opt/srb/scripts/backup.sh +``` + +### 10. Firewall Configuration + +```bash +# Install UFW +apt install ufw -y + +# Allow SSH +ufw allow 22/tcp + +# Allow HTTP/HTTPS +ufw allow 80/tcp +ufw allow 443/tcp + +# Enable firewall +ufw enable + +# Check status +ufw status +``` + +## Post-Deployment Checklist + +- [ ] All Docker containers running (`docker ps`) +- [ ] Database accessible and migrated +- [ ] SSL certificate installed (https://yourdomain.com) +- [ ] Environment variables configured +- [ ] Backups running daily +- [ ] Monitoring dashboards accessible +- [ ] Alerts configured (Slack/Email) +- [ ] Firewall enabled +- [ ] systemd service enabled +- [ ] Test creating a business + +## Creating First Production Business + +```bash +# SSH into server +ssh root@your-server + +# Enter orchestrator container +docker exec -it srb-orchestrator sh + +# Run CLI +node dist/cli/create-business.js \ + --name "My First Business" \ + --idea "AI-powered meal planning SaaS" +``` + +## Monitoring Production + +### Health Checks + +```bash +# Check all services +docker ps + +# Check logs +docker-compose logs -f orchestrator + +# Check database +docker exec -it srb-postgres psql -U srb -d srb -c "SELECT COUNT(*) FROM \"Business\";" + +# Check n8n +curl http://localhost:5678 + +# Check dashboard +curl http://localhost:3001 +``` + +### Key Metrics to Monitor + +1. **System Health** + - CPU usage < 70% + - Memory usage < 80% + - Disk space > 20% free + +2. **Application Health** + - Workflow success rate > 95% + - API response time < 500ms + - Database connections < 100 + +3. **Business Health** + - Active businesses count + - Total monthly revenue + - Workflow execution rate + +## Scaling Production + +### Vertical Scaling (Upgrade VPS) + +```bash +# Stop services +docker-compose down + +# Resize VPS in provider panel + +# Start services +docker-compose up -d +``` + +### Horizontal Scaling (Multiple Workers) + +Edit `docker-compose.yml`: + +```yaml +orchestrator: + ... + deploy: + replicas: 3 # Run 3 instances +``` + +### Database Scaling + +For high load: + +```yaml +postgres: + ... + environment: + - POSTGRES_MAX_CONNECTIONS=200 + - POSTGRES_SHARED_BUFFERS=2GB +``` + +## Troubleshooting + +### Container Won't Start + +```bash +# Check logs +docker logs srb-orchestrator + +# Restart container +docker restart srb-orchestrator + +# Rebuild if needed +docker-compose build orchestrator +docker-compose up -d +``` + +### Database Connection Issues + +```bash +# Check PostgreSQL logs +docker logs srb-postgres + +# Verify connection +docker exec -it srb-postgres psql -U srb -d srb + +# Reset database (DANGER: loses data) +docker-compose down -v +docker-compose up -d +``` + +### High CPU/Memory Usage + +```bash +# Check resource usage +docker stats + +# Limit resources in docker-compose.yml +services: + orchestrator: + deploy: + resources: + limits: + cpus: '2' + memory: 4G +``` + +## Security Best Practices + +1. **API Keys** + - Rotate every 90 days + - Use different keys for dev/prod + - Never commit to git + +2. **Database** + - Strong passwords (20+ chars) + - Disable remote access if not needed + - Regular backups + +3. **Server** + - Keep system updated + - Disable root SSH (use sudo user) + - Enable fail2ban + +4. **Application** + - Set budget limits + - Monitor spending daily + - Review decisions weekly + +## Maintenance + +### Weekly Tasks +- Review business performance +- Check error logs +- Verify backups + +### Monthly Tasks +- Update dependencies +- Review and optimize budgets +- Audit API usage and costs +- Security updates + +### Quarterly Tasks +- Rotate API keys +- Review and update strategies +- Performance optimization +- Capacity planning + +## Cost Optimization + +1. **Use Reserved Instances** (save 30-50%) +2. **Optimize Docker Images** (smaller = faster) +3. **Cache Aggressively** (reduce API calls) +4. **Schedule Non-Critical Tasks** (off-peak hours) +5. **Monitor API Usage** (avoid overages) + +--- + +**Deployment Status**: ✅ Ready for Production + +For support: See logs or contact admin diff --git a/docs/workflow-specifications.md b/docs/workflow-specifications.md new file mode 100644 index 0000000..992cf60 --- /dev/null +++ b/docs/workflow-specifications.md @@ -0,0 +1,565 @@ +# Workflow Specifications + +Detailed specifications for all 8 autonomous workflows in the Self-Replicating Business System. + +## Workflow Execution Model + +All workflows extend `WorkflowBase` which provides: +- ✅ Automatic retry logic (3 attempts with exponential backoff) +- ✅ Error handling and logging +- ✅ Database state tracking +- ✅ Alert integration +- ✅ Execution metrics + +--- + +## 1. Market Validation Workflow + +**Type**: `MARKET_VALIDATION` +**Phase**: Validation (Sequential) +**Critical**: Yes (pauses business on failure) + +### Purpose +Determine if a business idea is viable before investing resources. + +### Inputs +- Business ID +- Business idea (text) +- Business name + +### Process + +1. **Competitor Search** + - Google Custom Search API (if configured) + - Fallback: Web scraping + - Returns: Top 5 competitors with URLs, descriptions + +2. **Demand Analysis** + - Google Trends API + - Search volume estimation + - Trend direction (rising/stable/declining) + - Seasonality detection + +3. **Claude AI Analysis** + - Combines competitor data + demand data + - Generates viability score (0-100) + - Identifies top 3 risks + - Identifies top 3 opportunities + - Makes go/no-go recommendation + +4. **Decision** + - Score ≥ 60 && Viable = Proceed to MVP + - Score < 60 || Not Viable = Shutdown business + +### Outputs +```json +{ + "viable": true, + "score": 75, + "analysis": "Strong market opportunity...", + "risks": ["High competition", "Seasonal demand", "..."], + "opportunities": ["Underserved niche", "Growing market", "..."], + "competitors": [...], + "demandData": {...} +} +``` + +### Success Criteria +- Competitor search finds 2+ competitors +- Demand data shows search volume > 100/month +- Claude analysis completes within 30 seconds + +--- + +## 2. MVP Development Workflow + +**Type**: `MVP_DEVELOPMENT` +**Phase**: Development (Sequential) +**Critical**: Yes (pauses business on failure) + +### Purpose +Generate and deploy a functional MVP product. + +### Inputs +- Business ID +- Business idea +- Business name + +### Process + +1. **Code Generation** + - Claude generates Next.js 14+ code + - Includes: Landing page, API routes, Tailwind styling + - Returns: Map of filename → code content + +2. **Local Storage** + - Saves code to `/data/businesses/{id}/mvp/` + - Creates directory structure + - Writes all files + - Generates README + +3. **Git Initialization** (if Vercel enabled) + - `git init` + - `git add .` + - `git commit -m "Initial commit"` + +4. **Deployment** (if Vercel token configured) + - Creates vercel.json + - Runs `vercel --prod` + - Extracts deployment URL + +5. **Database Update** + - Stores MVP URL + - Updates status to `LAUNCHING` + +### Outputs +```json +{ + "mvpUrl": "https://business-abc123.vercel.app", + "filesGenerated": 8, + "projectDir": "/data/businesses/abc123/mvp" +} +``` + +### Success Criteria +- Generates minimum 5 files +- Deployment succeeds (or saves locally) +- MVP URL is accessible + +--- + +## 3. Landing Page SEO Workflow + +**Type**: `LANDING_PAGE_SEO` +**Phase**: Marketing (Parallel) +**Critical**: No + +### Purpose +Optimize landing page for search engines and organic traffic. + +### Inputs +- Business ID +- Business idea +- Target audience + +### Process + +1. **Keyword Research** + - Extract seed keywords from idea + - Use Claude SEO Expert skill + - Generate keyword list (10-20 keywords) + +2. **SEO Strategy** + - Claude generates comprehensive SEO plan + - On-page optimization tips + - Technical SEO checklist + - Link building strategy + +3. **Content Optimization** (if MVP exists) + - Analyze current content + - Generate optimized copy + - Meta title (60 chars) + - Meta description (155 chars) + - H1, H2 tags + +4. **Content Calendar** + - Generate 10-20 blog post ideas + - Keyword-focused topics + - Publishing schedule + +5. **Database Update** + - Set `seoOptimized = true` + +### Outputs +```json +{ + "keywordResearch": "...", + "seoStrategy": "...", + "contentIdeas": [...] +} +``` + +### Success Criteria +- Keyword list generated +- SEO strategy document created +- Content calendar populated + +--- + +## 4. Paid Ads Workflow + +**Type**: `PAID_ADS` +**Phase**: Marketing (Parallel) +**Critical**: No + +### Purpose +Launch paid advertising campaigns on Facebook and Google. + +### Inputs +- Business ID +- Business idea +- Budget +- Target audience + +### Process + +1. **Facebook Ads** + - Claude Ads Expert generates strategy + - Creates campaign via Facebook Ads API + - Objective: CONVERSIONS + - Budget: From business.budget or $500 default + - Saves campaign to database + +2. **Google Ads** + - Claude Ads Expert generates strategy + - Creates Search campaign via Google Ads API + - Keywords: Extracted from idea + - Budget: From business.budget or $500 default + - Saves campaign to database + +3. **Database Update** + - Set `adsActive = true` + - Set status = `RUNNING_ADS` + +### Outputs +```json +{ + "facebook": { + "success": true, + "campaignId": "fb_123456", + "strategy": "..." + }, + "google": { + "success": true, + "campaignId": "google_789012", + "strategy": "..." + } +} +``` + +### Success Criteria +- At least 1 campaign created (FB or Google) +- Campaign is active +- Budget allocated correctly + +--- + +## 5. Content Marketing Workflow + +**Type**: `CONTENT_MARKETING` +**Phase**: Marketing (Parallel) +**Critical**: No + +### Purpose +Create and publish SEO-optimized content. + +### Inputs +- Business ID +- Business idea +- Keywords + +### Process + +1. **Content Generation** + - Claude generates SEO-optimized content + - Meta title, description + - Headlines (H1, H2, H3) + - 500+ word landing page copy + +2. **Publishing** (future) + - Publish to CMS + - Schedule blog posts + - Social media sharing + +### Outputs +```json +{ + "contentGenerated": true, + "contentLength": 1200 +} +``` + +### Success Criteria +- Content generated (500+ words) +- SEO-optimized format + +--- + +## 6. Email Automation Workflow + +**Type**: `EMAIL_AUTOMATION` +**Phase**: Marketing (Parallel) +**Critical**: No + +### Purpose +Set up email sequences for lead nurturing. + +### Inputs +- Business ID +- Business name + +### Process + +1. **Template Creation** + - Welcome email + - Onboarding sequence (3-5 emails) + - Drip campaign + +2. **Sendgrid Setup** (if configured) + - Create templates via API + - Set up automation rules + +3. **Database Update** + - Set `emailAutomation = true` + +### Outputs +```json +{ + "configured": true, + "templates": 2 +} +``` + +### Success Criteria +- Templates created +- Automation configured + +--- + +## 7. Analytics Setup Workflow + +**Type**: `ANALYTICS_SETUP` +**Phase**: Marketing (Parallel) +**Critical**: No + +### Purpose +Install tracking and analytics for data-driven optimization. + +### Inputs +- Business ID +- MVP URL + +### Process + +1. **Google Analytics** + - Create GA4 property + - Install tracking code + - Set up conversion goals + +2. **Meta Pixel** + - Create Facebook Pixel + - Install pixel code + - Configure custom events + +3. **Conversion Tracking** + - Track: page views, signups, purchases + - Configure event tracking + +### Outputs +```json +{ + "googleAnalytics": { + "configured": true, + "trackingId": "G-XXXXXXXXXX" + }, + "metaPixel": { + "configured": true, + "pixelId": "1234567890" + } +} +``` + +### Success Criteria +- GA4 tracking installed +- Pixel tracking installed +- Events configured + +--- + +## 8. Optimization Loop Workflow + +**Type**: `OPTIMIZATION_LOOP` +**Phase**: Continuous (Forever) +**Critical**: No + +### Purpose +Continuously optimize campaigns and budgets for maximum ROI. + +### Schedule +Runs every 24 hours (configurable via `OPTIMIZATION_INTERVAL_MINUTES`) + +### Inputs +- Business ID + +### Process + +1. **Metrics Collection** + - Fetch from Google Analytics + - Fetch from Facebook Ads API + - Fetch from Google Ads API + - Aggregate data + +2. **Campaign Analysis** + - Calculate ROAS for each campaign + - Calculate CTR, conversion rate + - Classify performance: good/acceptable/poor + +3. **Budget Optimization** + - High performers (ROAS > 3): +20% budget + - Poor performers (ROAS < 1): -30% budget + - Record budget changes + +4. **Pause Underperformers** + - ROAS < 0.5: Pause campaign + - Losing 50%+ on ad spend + +5. **A/B Testing** (future) + - Create ad variants + - Test different copy/targeting + +6. **Metrics Recording** + - Save daily snapshot to database + - Update business revenue + +### Outputs +```json +{ + "metrics": { + "revenue": 5000, + "adSpend": 1500, + "roas": 3.33 + }, + "budgetChanges": [ + { + "campaignId": "...", + "action": "increase_budget", + "change": "+20%" + } + ], + "pausedCampaigns": ["..."], + "adTests": { + "testsRunning": 2 + } +} +``` + +### Success Criteria +- Metrics collected successfully +- At least 1 optimization performed +- No campaigns with ROAS < 0.5 left active + +--- + +## Workflow Dependencies + +``` +Market Validation + └─> MVP Development + └─> [PARALLEL] + ├─> Landing Page SEO + ├─> Paid Ads + ├─> Content Marketing + ├─> Email Automation + └─> Analytics Setup + └─> Optimization Loop (forever) +``` + +## Error Handling + +### Retry Policy +- Max retries: 3 +- Backoff: Exponential (2s, 4s, 8s) +- Timeout: 2 minutes per attempt + +### Failure Actions + +**Critical Workflows** (1, 2): +- Pause business +- Send critical alert +- Stop lifecycle execution + +**Non-Critical Workflows** (3-8): +- Log error +- Send warning alert +- Continue lifecycle + +### Recovery + +Workflows can be manually re-run: + +```bash +# Retry failed workflow +pnpm retry-workflow --business-id abc123 --type MARKET_VALIDATION +``` + +--- + +## Monitoring Workflows + +### Database Tracking + +Each workflow run creates a `WorkflowRun` record: + +```sql +SELECT + workflowType, + status, + attempts, + error, + completedAt - startedAt as duration +FROM "WorkflowRun" +WHERE businessId = 'abc123' +ORDER BY createdAt DESC; +``` + +### Logs + +```bash +# View workflow logs +docker logs srb-orchestrator | grep "MARKET_VALIDATION" + +# Real-time monitoring +docker logs -f srb-orchestrator +``` + +### Metrics + +- Execution time (should be < 5 minutes) +- Success rate (should be > 95%) +- Retry rate (should be < 10%) + +--- + +## Extending Workflows + +To add a new workflow: + +1. Create file: `src/workflows/09-new-workflow.ts` +2. Extend `WorkflowBase` +3. Implement `execute()` method +4. Add to `WorkflowExecutor` map +5. Add to Prisma `WorkflowType` enum +6. Update orchestrator lifecycle + +Example: + +```typescript +export class NewWorkflow extends WorkflowBase { + protected type: WorkflowType = 'NEW_WORKFLOW'; + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + // Your logic here + + return { + success: true, + data: { ... } + }; + } +} +``` + +--- + +**Last Updated**: 2026-02-04 diff --git a/infra/docker/dashboard.Dockerfile b/infra/docker/dashboard.Dockerfile new file mode 100644 index 0000000..24ad5a4 --- /dev/null +++ b/infra/docker/dashboard.Dockerfile @@ -0,0 +1,24 @@ +FROM node:20-alpine + +WORKDIR /app + +# Install pnpm +RUN npm install -g pnpm + +# Copy package files +COPY package.json pnpm-lock.yaml* ./ + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Copy source code +COPY . . + +# Build Next.js app +RUN pnpm build + +# Expose port +EXPOSE 3000 + +# Start Next.js +CMD ["pnpm", "start"] diff --git a/infra/docker/docker-compose.yml b/infra/docker/docker-compose.yml new file mode 100644 index 0000000..cfecdb7 --- /dev/null +++ b/infra/docker/docker-compose.yml @@ -0,0 +1,148 @@ +version: '3.8' + +services: + # PostgreSQL Database + postgres: + image: postgres:15-alpine + container_name: srb-postgres + environment: + POSTGRES_USER: srb + POSTGRES_PASSWORD: srb_password + POSTGRES_DB: srb + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U srb"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - srb-network + + # Redis for caching and queues + redis: + image: redis:7-alpine + container_name: srb-redis + ports: + - "6379:6379" + volumes: + - redis_data:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - srb-network + + # n8n Workflow Automation + n8n: + image: n8nio/n8n:latest + container_name: srb-n8n + environment: + - N8N_BASIC_AUTH_ACTIVE=true + - N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER:-admin} + - N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD:-admin123} + - DB_TYPE=postgresdb + - DB_POSTGRESDB_HOST=postgres + - DB_POSTGRESDB_PORT=5432 + - DB_POSTGRESDB_DATABASE=n8n + - DB_POSTGRESDB_USER=srb + - DB_POSTGRESDB_PASSWORD=srb_password + - N8N_PORT=5678 + - WEBHOOK_URL=http://localhost:5678/ + ports: + - "5678:5678" + volumes: + - n8n_data:/home/node/.n8n + - ../../packages/n8n-workflows:/workflows + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + networks: + - srb-network + + # Orchestrator Service + orchestrator: + build: + context: ../../packages/orchestrator + dockerfile: ../../infra/docker/orchestrator.Dockerfile + container_name: srb-orchestrator + environment: + - DATABASE_URL=postgresql://srb:srb_password@postgres:5432/srb + - REDIS_URL=redis://redis:6379 + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} + - FACEBOOK_APP_ID=${FACEBOOK_APP_ID} + - FACEBOOK_APP_SECRET=${FACEBOOK_APP_SECRET} + - FACEBOOK_ACCESS_TOKEN=${FACEBOOK_ACCESS_TOKEN} + - FACEBOOK_AD_ACCOUNT_ID=${FACEBOOK_AD_ACCOUNT_ID} + - GOOGLE_ADS_CLIENT_ID=${GOOGLE_ADS_CLIENT_ID} + - GOOGLE_ADS_CLIENT_SECRET=${GOOGLE_ADS_CLIENT_SECRET} + - GOOGLE_ADS_REFRESH_TOKEN=${GOOGLE_ADS_REFRESH_TOKEN} + - GOOGLE_ADS_DEVELOPER_TOKEN=${GOOGLE_ADS_DEVELOPER_TOKEN} + - GOOGLE_ADS_CUSTOMER_ID=${GOOGLE_ADS_CUSTOMER_ID} + - SENDGRID_API_KEY=${SENDGRID_API_KEY} + - SENDGRID_FROM_EMAIL=${SENDGRID_FROM_EMAIL} + - SENDGRID_FROM_NAME=${SENDGRID_FROM_NAME} + - VERCEL_TOKEN=${VERCEL_TOKEN} + - VERCEL_ORG_ID=${VERCEL_ORG_ID} + - ACQUIRE_COM_API_KEY=${ACQUIRE_COM_API_KEY} + - UPWORK_API_KEY=${UPWORK_API_KEY} + - SLACK_WEBHOOK_URL=${SLACK_WEBHOOK_URL} + - ALERT_EMAIL=${ALERT_EMAIL} + - NODE_ENV=${NODE_ENV:-development} + - PORT=3000 + ports: + - "3000:3000" + volumes: + - ../../packages/orchestrator:/app + - /app/node_modules + - ../../data:/app/data + - ../../logs:/app/logs + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + networks: + - srb-network + restart: unless-stopped + + # Web Dashboard (Next.js) + dashboard: + build: + context: ../../packages/web-dashboard + dockerfile: ../../infra/docker/dashboard.Dockerfile + container_name: srb-dashboard + environment: + - DATABASE_URL=postgresql://srb:srb_password@postgres:5432/srb + - NEXT_PUBLIC_API_URL=http://localhost:3000 + ports: + - "3001:3000" + volumes: + - ../../packages/web-dashboard:/app + - /app/node_modules + - /app/.next + depends_on: + - postgres + - orchestrator + networks: + - srb-network + restart: unless-stopped + +networks: + srb-network: + driver: bridge + +volumes: + postgres_data: + driver: local + redis_data: + driver: local + n8n_data: + driver: local diff --git a/infra/docker/orchestrator.Dockerfile b/infra/docker/orchestrator.Dockerfile new file mode 100644 index 0000000..24f8e14 --- /dev/null +++ b/infra/docker/orchestrator.Dockerfile @@ -0,0 +1,32 @@ +FROM node:20-alpine + +WORKDIR /app + +# Install pnpm +RUN npm install -g pnpm + +# Copy package files +COPY package.json pnpm-lock.yaml* ./ +COPY prisma ./prisma/ + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Copy source code +COPY . . + +# Generate Prisma Client +RUN pnpm db:generate + +# Build TypeScript +RUN pnpm build + +# Expose port +EXPOSE 3000 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" + +# Start application +CMD ["sh", "-c", "pnpm db:push && pnpm start"] diff --git a/package.json b/package.json new file mode 100644 index 0000000..6484444 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "self-replicating-business", + "version": "1.0.0", + "description": "Autonomous business lifecycle management system - from idea to exit", + "private": true, + "workspaces": [ + "packages/*" + ], + "scripts": { + "dev": "turbo run dev", + "build": "turbo run build", + "test": "turbo run test", + "lint": "turbo run lint", + "clean": "turbo run clean", + "docker:up": "docker-compose -f infra/docker/docker-compose.yml up -d", + "docker:down": "docker-compose -f infra/docker/docker-compose.yml down", + "docker:logs": "docker-compose -f infra/docker/docker-compose.yml logs -f", + "db:migrate": "cd packages/orchestrator && npx prisma migrate dev", + "db:studio": "cd packages/orchestrator && npx prisma studio", + "create-business": "cd packages/orchestrator && tsx src/cli/create-business.ts", + "check-business": "cd packages/orchestrator && tsx src/cli/check-business.ts", + "list-campaigns": "cd packages/orchestrator && tsx src/cli/list-campaigns.ts", + "evaluate-decisions": "cd packages/orchestrator && tsx src/cli/evaluate-decisions.ts", + "view-decisions": "cd packages/orchestrator && tsx src/cli/view-decisions.ts" + }, + "devDependencies": { + "turbo": "^2.0.0", + "typescript": "^5.6.0", + "@types/node": "^22.0.0" + }, + "engines": { + "node": ">=20.0.0", + "pnpm": ">=9.0.0" + }, + "packageManager": "pnpm@9.0.0" +} diff --git a/packages/orchestrator/package.json b/packages/orchestrator/package.json new file mode 100644 index 0000000..01058ed --- /dev/null +++ b/packages/orchestrator/package.json @@ -0,0 +1,44 @@ +{ + "name": "@srb/orchestrator", + "version": "1.0.0", + "description": "Core orchestrator for autonomous business lifecycle management", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "dev": "tsx watch src/index.ts", + "build": "tsc", + "start": "node dist/index.js", + "test": "vitest", + "test:ui": "vitest --ui", + "clean": "rm -rf dist", + "db:generate": "prisma generate", + "db:migrate": "prisma migrate dev", + "db:studio": "prisma studio", + "db:push": "prisma db push" + }, + "dependencies": { + "@anthropic-ai/sdk": "^0.32.0", + "@prisma/client": "^6.0.0", + "axios": "^1.7.0", + "dotenv": "^16.4.0", + "ioredis": "^5.4.0", + "winston": "^3.14.0", + "zod": "^3.23.0", + "nanoid": "^5.0.0", + "date-fns": "^4.0.0", + "google-trends-api": "^5.0.0", + "cheerio": "^1.0.0", + "@sendgrid/mail": "^8.1.0", + "facebook-nodejs-business-sdk": "^21.0.0", + "google-ads-api": "^17.0.0", + "vercel": "^37.0.0" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "prisma": "^6.0.0", + "tsx": "^4.19.0", + "typescript": "^5.6.0", + "vitest": "^2.0.0", + "@vitest/ui": "^2.0.0" + } +} diff --git a/packages/orchestrator/prisma/schema.prisma b/packages/orchestrator/prisma/schema.prisma new file mode 100644 index 0000000..2fcca90 --- /dev/null +++ b/packages/orchestrator/prisma/schema.prisma @@ -0,0 +1,263 @@ +// Prisma schema for Self-Replicating Business System +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +// ============================================ +// BUSINESS MODEL +// ============================================ +model Business { + id String @id @default(cuid()) + name String + idea String @db.Text + status BusinessStatus @default(VALIDATING) + viable Boolean? + + // URLs + mvpUrl String? + landingPageUrl String? + + // Feature flags + seoOptimized Boolean @default(false) + adsActive Boolean @default(false) + emailAutomation Boolean @default(false) + + // Revenue metrics + monthlyRevenue Float @default(0) + totalRevenue Float @default(0) + + // Validation data (JSONB) + validationResult Json? + targetAudience String? + budget Float? + + // Relationships + workflows WorkflowRun[] + campaigns Campaign[] + metrics Metric[] + decisions Decision[] + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([status, monthlyRevenue]) + @@index([createdAt]) +} + +enum BusinessStatus { + VALIDATING + VALIDATION_FAILED + DEVELOPING_MVP + LAUNCHING + RUNNING_ADS + OPTIMIZING + SCALING + SELLING + SHUTDOWN + PAUSED +} + +// ============================================ +// WORKFLOW EXECUTION MODEL +// ============================================ +model WorkflowRun { + id String @id @default(cuid()) + businessId String + business Business @relation(fields: [businessId], references: [id], onDelete: Cascade) + + workflowType WorkflowType + status WorkflowStatus @default(PENDING) + + inputData Json @default("{}") + outputData Json? + error String? @db.Text + + attempts Int @default(0) + maxRetries Int @default(3) + + startedAt DateTime? + completedAt DateTime? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([businessId, workflowType]) + @@index([status]) + @@index([createdAt]) +} + +enum WorkflowType { + MARKET_VALIDATION + MVP_DEVELOPMENT + LANDING_PAGE_SEO + PAID_ADS + CONTENT_MARKETING + EMAIL_AUTOMATION + ANALYTICS_SETUP + OPTIMIZATION_LOOP +} + +enum WorkflowStatus { + PENDING + IN_PROGRESS + COMPLETED + FAILED + RETRYING +} + +// ============================================ +// CAMPAIGN MODEL +// ============================================ +model Campaign { + id String @id @default(cuid()) + businessId String + business Business @relation(fields: [businessId], references: [id], onDelete: Cascade) + + platform Platform + campaignId String? // External campaign ID + adSetId String? // External ad set ID + + name String + budget Float + dailyBudget Float? + active Boolean @default(true) + + // Metrics + impressions Int @default(0) + clicks Int @default(0) + conversions Int @default(0) + spend Float @default(0) + revenue Float @default(0) + + // Campaign config (JSONB) + targeting Json? + creative Json? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([businessId, platform]) + @@index([active]) +} + +enum Platform { + FACEBOOK + GOOGLE + ORGANIC +} + +// ============================================ +// METRICS MODEL +// ============================================ +model Metric { + id String @id @default(cuid()) + businessId String + business Business @relation(fields: [businessId], references: [id], onDelete: Cascade) + + timestamp DateTime @default(now()) + + // Financial metrics + revenue Float @default(0) + adSpend Float @default(0) + profit Float @default(0) + roas Float? // Return on Ad Spend + + // Traffic metrics + visitors Int @default(0) + pageViews Int @default(0) + bounceRate Float? + avgSessionDuration Float? + + // Conversion metrics + conversions Int @default(0) + conversionRate Float? + + // Source breakdown (JSONB) + sourceBreakdown Json? + + createdAt DateTime @default(now()) + + @@index([businessId, timestamp]) + @@index([timestamp]) +} + +// ============================================ +// DECISION MODEL +// ============================================ +model Decision { + id String @id @default(cuid()) + businessId String + business Business @relation(fields: [businessId], references: [id], onDelete: Cascade) + + decisionType DecisionType + action String @db.Text + reasoning String @db.Text + + revenueAtDecision Float? + metricsSnapshot Json? // Snapshot of all metrics at decision time + + executed Boolean @default(false) + executedAt DateTime? + executionResult Json? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([businessId, decisionType]) + @@index([executed]) + @@index([createdAt]) +} + +enum DecisionType { + SCALE_PRODUCT + SELL_BUSINESS + SHUTDOWN + PAUSE_CAMPAIGN + INCREASE_BUDGET + HIRE_VA +} + +// ============================================ +// ALERT/NOTIFICATION MODEL +// ============================================ +model Alert { + id String @id @default(cuid()) + businessId String? + + type AlertType + severity AlertSeverity @default(INFO) + + title String + message String @db.Text + metadata Json? + + read Boolean @default(false) + acknowledged Boolean @default(false) + + createdAt DateTime @default(now()) + + @@index([businessId]) + @@index([type, severity]) + @@index([read]) +} + +enum AlertType { + WORKFLOW_FAILED + WORKFLOW_COMPLETED + REVENUE_MILESTONE + DECISION_EXECUTED + API_ERROR + BUDGET_THRESHOLD + SYSTEM_ERROR +} + +enum AlertSeverity { + INFO + WARNING + ERROR + CRITICAL +} diff --git a/packages/orchestrator/src/decision-engine/rules.ts b/packages/orchestrator/src/decision-engine/rules.ts new file mode 100644 index 0000000..9b6eabb --- /dev/null +++ b/packages/orchestrator/src/decision-engine/rules.ts @@ -0,0 +1,501 @@ +import { PrismaClient } from '@prisma/client'; +import { AlertSystem } from '../monitoring/alerts'; +import { MetricsCollector } from '../monitoring/metrics'; +import { UpworkAPI } from '../integrations/marketplace/upwork-api'; +import { AcquireAPI } from '../integrations/marketplace/acquire-com'; +import { log } from '../monitoring/logger'; +import { config } from '../utils/config'; +import { differenceInMonths } from 'date-fns'; + +export class DecisionEngine { + constructor( + private db: PrismaClient, + private alerts: AlertSystem, + private metrics: MetricsCollector + ) {} + + /** + * Evaluate all decision rules for a business + * This runs autonomously on a daily schedule + */ + async evaluateBusinessDaily(businessId: string): Promise { + try { + const business = await this.db.business.findUnique({ + where: { id: businessId }, + }); + + if (!business) { + log.warn('Business not found for decision evaluation', { businessId }); + return; + } + + log.info('Evaluating business decisions', { + businessId, + monthlyRevenue: business.monthlyRevenue, + status: business.status, + }); + + const monthlyRevenue = business.monthlyRevenue; + const monthsSinceStart = differenceInMonths(new Date(), business.createdAt); + + // Rule 1: Scale at $10K/month (hire VA + increase budget) + if ( + monthlyRevenue >= config.thresholds.scaleRevenue && + business.status !== 'SCALING' && + business.status !== 'SELLING' + ) { + await this.executeScaleDecision(businessId, monthlyRevenue, business); + } + + // Rule 2: Exit at $50K/month (list on Acquire.com) + if ( + monthlyRevenue >= config.thresholds.sellRevenue && + business.status !== 'SELLING' + ) { + await this.executeExitDecision(businessId, monthlyRevenue, business); + } + + // Rule 3: Shutdown if <$1K for 6 months + if ( + monthlyRevenue < config.thresholds.shutdownRevenue && + monthsSinceStart >= config.thresholds.shutdownWaitMonths && + business.status !== 'SHUTDOWN' + ) { + await this.executeShutdownDecision(businessId, monthlyRevenue, business); + } + + log.info('Business decision evaluation complete', { businessId }); + } catch (error) { + log.error('Decision evaluation failed', error, { businessId }); + } + } + + /** + * RULE 1: Scale business at $10K/month revenue + * Actions: + * - Hire VA via Upwork for customer support + * - Increase ad budget by 50% + * - Update business status to SCALING + */ + private async executeScaleDecision( + businessId: string, + revenue: number, + business: any + ): Promise { + log.info('Executing scale decision', { businessId, revenue }); + + const metricsSnapshot = await this.metrics.getBusinessMetrics(businessId); + + try { + // Create decision record + const decision = await this.db.decision.create({ + data: { + businessId, + decisionType: 'SCALE_PRODUCT', + action: 'HIRE_VA_AND_INCREASE_BUDGET', + reasoning: `Monthly revenue reached $${revenue.toLocaleString()}. Hiring VA for customer support and increasing ad budget by 50% to accelerate growth.`, + revenueAtDecision: revenue, + metricsSnapshot: metricsSnapshot as any, + executed: false, + }, + }); + + // Action 1: Hire VA via Upwork + const vaHired = await this.hireVA(businessId, business.name); + + // Action 2: Increase ad budgets by 50% + const budgetIncreased = await this.increaseAdsBudget(businessId, 1.5); + + // Action 3: Update business status + await this.db.business.update({ + where: { id: businessId }, + data: { status: 'SCALING' }, + }); + + // Mark decision as executed + await this.db.decision.update({ + where: { id: decision.id }, + data: { + executed: true, + executedAt: new Date(), + executionResult: { + vaHired, + budgetIncreased, + } as any, + }, + }); + + // Send alert + await this.alerts.decisionExecuted( + businessId, + 'SCALE_PRODUCT', + 'Hired VA + Increased Budget by 50%', + business.name + ); + + // Revenue milestone alert + await this.alerts.revenueMilestone( + businessId, + config.thresholds.scaleRevenue, + business.name + ); + + log.info('Scale decision executed successfully', { + businessId, + vaHired, + budgetIncreased, + }); + } catch (error) { + log.error('Scale decision execution failed', error, { businessId }); + await this.alerts.sendAlert({ + type: 'DECISION_EXECUTED', + severity: 'ERROR', + title: 'Scale Decision Failed', + message: `Failed to execute scale decision for ${business.name}.\n\nError: ${error instanceof Error ? error.message : String(error)}`, + businessId, + }); + } + } + + /** + * RULE 2: Exit business at $50K/month revenue + * Actions: + * - Calculate valuation (3.5x annual profit) + * - List on Acquire.com + * - Update business status to SELLING + */ + private async executeExitDecision( + businessId: string, + revenue: number, + business: any + ): Promise { + log.info('Executing exit decision', { businessId, revenue }); + + const metricsSnapshot = await this.metrics.getBusinessMetrics(businessId); + + try { + // Calculate valuation + const annualRevenue = revenue * 12; + const profitMargin = metricsSnapshot.profitMargin / 100; // Convert to decimal + const annualProfit = annualRevenue * profitMargin; + const valuation = annualProfit * 3.5; // Standard SaaS multiple + + log.info('Business valuation calculated', { + businessId, + annualRevenue, + annualProfit, + valuation, + }); + + // Create decision record + const decision = await this.db.decision.create({ + data: { + businessId, + decisionType: 'SELL_BUSINESS', + action: 'LIST_ON_ACQUIRE_COM', + reasoning: `Monthly revenue reached $${revenue.toLocaleString()}. Listing business for sale at $${valuation.toLocaleString()} valuation (3.5x annual profit of $${annualProfit.toLocaleString()}).`, + revenueAtDecision: revenue, + metricsSnapshot: { + ...metricsSnapshot, + valuation, + annualRevenue, + annualProfit, + } as any, + executed: false, + }, + }); + + // List on Acquire.com + const listingUrl = await this.listOnAcquire(business, valuation, revenue); + + // Update business status + await this.db.business.update({ + where: { id: businessId }, + data: { status: 'SELLING' }, + }); + + // Mark decision as executed + await this.db.decision.update({ + where: { id: decision.id }, + data: { + executed: true, + executedAt: new Date(), + executionResult: { + listingUrl, + valuation, + } as any, + }, + }); + + // Send alert + await this.alerts.decisionExecuted( + businessId, + 'SELL_BUSINESS', + `Listed for sale at $${valuation.toLocaleString()}`, + business.name + ); + + // Revenue milestone alert + await this.alerts.revenueMilestone( + businessId, + config.thresholds.sellRevenue, + business.name + ); + + log.info('Exit decision executed successfully', { + businessId, + listingUrl, + valuation, + }); + } catch (error) { + log.error('Exit decision execution failed', error, { businessId }); + await this.alerts.sendAlert({ + type: 'DECISION_EXECUTED', + severity: 'ERROR', + title: 'Exit Decision Failed', + message: `Failed to execute exit decision for ${business.name}.\n\nError: ${error instanceof Error ? error.message : String(error)}`, + businessId, + }); + } + } + + /** + * RULE 3: Shutdown business if revenue <$1K for 6 months + * Actions: + * - Pause all campaigns + * - Archive business data + * - Update business status to SHUTDOWN + */ + private async executeShutdownDecision( + businessId: string, + revenue: number, + business: any + ): Promise { + log.info('Executing shutdown decision', { businessId, revenue }); + + const metricsSnapshot = await this.metrics.getBusinessMetrics(businessId); + + try { + // Create decision record + const decision = await this.db.decision.create({ + data: { + businessId, + decisionType: 'SHUTDOWN', + action: 'PAUSE_CAMPAIGNS_AND_ARCHIVE', + reasoning: `Monthly revenue below $${config.thresholds.shutdownRevenue} for ${config.thresholds.shutdownWaitMonths} months. Shutting down to prevent further losses.`, + revenueAtDecision: revenue, + metricsSnapshot: metricsSnapshot as any, + executed: false, + }, + }); + + // Pause all campaigns + const pausedCampaigns = await this.pauseAllCampaigns(businessId); + + // Archive business data + const archivePath = await this.archiveBusinessData(businessId); + + // Update business status + await this.db.business.update({ + where: { id: businessId }, + data: { status: 'SHUTDOWN' }, + }); + + // Mark decision as executed + await this.db.decision.update({ + where: { id: decision.id }, + data: { + executed: true, + executedAt: new Date(), + executionResult: { + pausedCampaigns, + archivePath, + } as any, + }, + }); + + // Send alert + await this.alerts.decisionExecuted( + businessId, + 'SHUTDOWN', + `Paused all campaigns and archived data`, + business.name + ); + + log.info('Shutdown decision executed successfully', { + businessId, + pausedCampaigns, + archivePath, + }); + } catch (error) { + log.error('Shutdown decision execution failed', error, { businessId }); + await this.alerts.sendAlert({ + type: 'DECISION_EXECUTED', + severity: 'ERROR', + title: 'Shutdown Decision Failed', + message: `Failed to execute shutdown decision for ${business.name}.\n\nError: ${error instanceof Error ? error.message : String(error)}`, + businessId, + }); + } + } + + /** + * Hire a VA via Upwork + */ + private async hireVA(businessId: string, businessName: string): Promise { + try { + const upwork = new UpworkAPI(); + + await upwork.postJob({ + title: `Customer Support VA for ${businessName}`, + description: `We're looking for a customer support VA to handle inquiries for ${businessName}. Must be responsive, professional, and detail-oriented.`, + budget: 500, + duration: 'ongoing', + skills: ['Customer Support', 'Email Support', 'Communication'], + }); + + log.info('VA job posted on Upwork', { businessId, businessName }); + return true; + } catch (error) { + log.error('Failed to hire VA', error, { businessId }); + return false; + } + } + + /** + * Increase ad budgets by a multiplier + */ + private async increaseAdsBudget( + businessId: string, + multiplier: number + ): Promise { + const campaigns = await this.db.campaign.findMany({ + where: { businessId, active: true }, + }); + + let increased = 0; + + for (const campaign of campaigns) { + const newBudget = campaign.budget * multiplier; + + // Check if new budget exceeds max limit + const maxBudget = config.budgetLimits.maxAdSpendPerBusiness; + if (newBudget > maxBudget) { + log.warn('Budget increase would exceed max limit', { + campaignId: campaign.id, + newBudget, + maxBudget, + }); + continue; + } + + await this.db.campaign.update({ + where: { id: campaign.id }, + data: { + budget: newBudget, + dailyBudget: newBudget / 30, + }, + }); + + increased++; + + log.info('Campaign budget increased', { + campaignId: campaign.id, + oldBudget: campaign.budget, + newBudget, + multiplier, + }); + } + + return increased; + } + + /** + * List business on Acquire.com + */ + private async listOnAcquire( + business: any, + valuation: number, + monthlyRevenue: number + ): Promise { + try { + const acquire = new AcquireAPI(); + + const listingUrl = await acquire.createListing({ + businessName: business.name, + description: business.idea, + monthlyRevenue, + askingPrice: valuation, + category: 'saas', + }); + + log.info('Business listed on Acquire.com', { + businessId: business.id, + listingUrl, + valuation, + }); + + return listingUrl; + } catch (error) { + log.error('Failed to list on Acquire.com', error, { businessId: business.id }); + return 'https://acquire.com (listing failed - manual intervention required)'; + } + } + + /** + * Pause all campaigns for a business + */ + private async pauseAllCampaigns(businessId: string): Promise { + const result = await this.db.campaign.updateMany({ + where: { businessId, active: true }, + data: { active: false }, + }); + + log.info('All campaigns paused', { businessId, count: result.count }); + return result.count; + } + + /** + * Archive business data before shutdown + */ + private async archiveBusinessData(businessId: string): Promise { + try { + const fs = require('fs/promises'); + const path = require('path'); + + const archiveDir = path.resolve( + __dirname, + '../../../../../data/businesses', + businessId, + 'archive' + ); + + await fs.mkdir(archiveDir, { recursive: true }); + + // Export business data + const business = await this.db.business.findUnique({ + where: { id: businessId }, + include: { + workflows: true, + campaigns: true, + metrics: true, + decisions: true, + }, + }); + + // Save to JSON + const archivePath = path.join(archiveDir, 'business-archive.json'); + await fs.writeFile( + archivePath, + JSON.stringify(business, null, 2), + 'utf-8' + ); + + log.info('Business data archived', { businessId, archivePath }); + return archivePath; + } catch (error) { + log.error('Failed to archive business data', error, { businessId }); + return `Archive failed: ${businessId}`; + } + } +} diff --git a/packages/orchestrator/src/index.ts b/packages/orchestrator/src/index.ts new file mode 100644 index 0000000..8910057 --- /dev/null +++ b/packages/orchestrator/src/index.ts @@ -0,0 +1,51 @@ +import { MetaOrchestrator } from './orchestrator'; +import { log } from './monitoring/logger'; +import { config } from './utils/config'; + +// Main entry point +async function main() { + const orchestrator = new MetaOrchestrator(); + + try { + // Initialize + await orchestrator.initialize(); + + log.info('Self-Replicating Business System Started', { + nodeEnv: config.app.nodeEnv, + port: config.app.port, + }); + + // Handle graceful shutdown + process.on('SIGTERM', async () => { + log.info('Received SIGTERM signal'); + await orchestrator.close(); + process.exit(0); + }); + + process.on('SIGINT', async () => { + log.info('Received SIGINT signal'); + await orchestrator.close(); + process.exit(0); + }); + + // Keep process alive + await new Promise(() => {}); + } catch (error) { + log.error('Fatal error in main process', error); + await orchestrator.close(); + process.exit(1); + } +} + +// Run if this is the main module +if (require.main === module) { + main().catch((error) => { + console.error('Failed to start:', error); + process.exit(1); + }); +} + +// Export for programmatic use +export { MetaOrchestrator }; +export * from './utils/config'; +export * from './monitoring/logger'; diff --git a/packages/orchestrator/src/integrations/ads/facebook-ads.ts b/packages/orchestrator/src/integrations/ads/facebook-ads.ts new file mode 100644 index 0000000..1d0925d --- /dev/null +++ b/packages/orchestrator/src/integrations/ads/facebook-ads.ts @@ -0,0 +1,110 @@ +import { config, integrations } from '../../utils/config'; +import { log } from '../../monitoring/logger'; + +export interface FacebookCampaignOptions { + name: string; + objective: 'CONVERSIONS' | 'TRAFFIC' | 'AWARENESS'; + budget: number; + targeting: { + age_min?: number; + age_max?: number; + interests?: string[]; + locations?: string[]; + }; +} + +export class FacebookAdsAPI { + private accessToken: string; + private adAccountId: string; + + constructor() { + this.accessToken = config.facebook.accessToken || ''; + this.adAccountId = config.facebook.adAccountId || ''; + } + + /** + * Create a Facebook Ads campaign + */ + async createCampaign(options: FacebookCampaignOptions): Promise<{ + id: string; + name: string; + targeting: any; + }> { + if (!integrations.hasFacebookAds()) { + log.warn('Facebook Ads not configured - returning mock campaign'); + return { + id: `fb_campaign_${Date.now()}`, + name: options.name, + targeting: options.targeting, + }; + } + + try { + // In production, would use facebook-nodejs-business-sdk + // const bizSdk = require('facebook-nodejs-business-sdk'); + // const Campaign = bizSdk.Campaign; + // const campaign = new Campaign(null, this.adAccountId); + // await campaign.create({ + // name: options.name, + // objective: options.objective, + // status: Campaign.Status.active, + // }); + + log.info('Facebook campaign created', { name: options.name }); + + return { + id: `fb_campaign_${Date.now()}`, + name: options.name, + targeting: options.targeting, + }; + } catch (error) { + log.error('Failed to create Facebook campaign', error); + throw error; + } + } + + /** + * Update campaign budget + */ + async updateCampaignBudget(campaignId: string, newBudget: number): Promise { + log.info('Updating Facebook campaign budget', { campaignId, newBudget }); + + // In production, would use Facebook Ads API + // const bizSdk = require('facebook-nodejs-business-sdk'); + // const Campaign = bizSdk.Campaign; + // const campaign = new Campaign(campaignId); + // await campaign.update({ + // daily_budget: newBudget, + // }); + } + + /** + * Pause campaign + */ + async pauseCampaign(campaignId: string): Promise { + log.info('Pausing Facebook campaign', { campaignId }); + + // In production, would use Facebook Ads API + // const bizSdk = require('facebook-nodejs-business-sdk'); + // const Campaign = bizSdk.Campaign; + // const campaign = new Campaign(campaignId); + // await campaign.update({ + // status: Campaign.Status.paused, + // }); + } + + /** + * Get campaign metrics + */ + async getCampaignMetrics(campaignId: string): Promise { + log.info('Fetching Facebook campaign metrics', { campaignId }); + + // In production, would use Facebook Ads API Insights + return { + impressions: Math.floor(Math.random() * 10000), + clicks: Math.floor(Math.random() * 500), + conversions: Math.floor(Math.random() * 50), + spend: Math.random() * 1000, + }; + } +} diff --git a/packages/orchestrator/src/integrations/ads/google-ads.ts b/packages/orchestrator/src/integrations/ads/google-ads.ts new file mode 100644 index 0000000..2308197 --- /dev/null +++ b/packages/orchestrator/src/integrations/ads/google-ads.ts @@ -0,0 +1,87 @@ +import { config, integrations } from '../../utils/config'; +import { log } from '../../monitoring/logger'; + +export interface GoogleCampaignOptions { + name: string; + type: 'SEARCH' | 'DISPLAY' | 'SHOPPING'; + budget: number; + keywords?: string[]; +} + +export class GoogleAdsAPI { + private customerId: string; + + constructor() { + this.customerId = config.googleAds.customerId || ''; + } + + /** + * Create a Google Ads campaign + */ + async createCampaign(options: GoogleCampaignOptions): Promise<{ + id: string; + name: string; + }> { + if (!integrations.hasGoogleAds()) { + log.warn('Google Ads not configured - returning mock campaign'); + return { + id: `google_campaign_${Date.now()}`, + name: options.name, + }; + } + + try { + // In production, would use google-ads-api + // const { GoogleAdsApi } = require('google-ads-api'); + // const client = new GoogleAdsApi({ + // client_id: config.googleAds.clientId, + // client_secret: config.googleAds.clientSecret, + // developer_token: config.googleAds.developerToken, + // }); + // const customer = client.Customer({ customer_id: this.customerId }); + // const campaign = await customer.campaigns.create({ + // name: options.name, + // advertising_channel_type: options.type, + // campaign_budget: options.budget, + // }); + + log.info('Google Ads campaign created', { name: options.name }); + + return { + id: `google_campaign_${Date.now()}`, + name: options.name, + }; + } catch (error) { + log.error('Failed to create Google Ads campaign', error); + throw error; + } + } + + /** + * Update campaign budget + */ + async updateCampaignBudget(campaignId: string, newBudget: number): Promise { + log.info('Updating Google Ads campaign budget', { campaignId, newBudget }); + } + + /** + * Pause campaign + */ + async pauseCampaign(campaignId: string): Promise { + log.info('Pausing Google Ads campaign', { campaignId }); + } + + /** + * Get campaign metrics + */ + async getCampaignMetrics(campaignId: string): Promise { + log.info('Fetching Google Ads campaign metrics', { campaignId }); + + return { + impressions: Math.floor(Math.random() * 15000), + clicks: Math.floor(Math.random() * 600), + conversions: Math.floor(Math.random() * 60), + cost: Math.random() * 1200, + }; + } +} diff --git a/packages/orchestrator/src/integrations/analytics/google-analytics.ts b/packages/orchestrator/src/integrations/analytics/google-analytics.ts new file mode 100644 index 0000000..2b5bda2 --- /dev/null +++ b/packages/orchestrator/src/integrations/analytics/google-analytics.ts @@ -0,0 +1,67 @@ +import { config } from '../../utils/config'; +import { log } from '../../monitoring/logger'; + +export class GoogleAnalyticsClient { + private propertyId: string; + + constructor() { + this.propertyId = config.googleAnalytics.propertyId || ''; + } + + /** + * Get analytics data for a date range + */ + async getAnalyticsData(startDate: string, endDate: string): Promise { + try { + // In production, would use Google Analytics Data API + // const { BetaAnalyticsDataClient } = require('@google-analytics/data'); + // const analyticsDataClient = new BetaAnalyticsDataClient(); + // const [response] = await analyticsDataClient.runReport({ + // property: `properties/${this.propertyId}`, + // dateRanges: [{ startDate, endDate }], + // dimensions: [{ name: 'date' }], + // metrics: [ + // { name: 'activeUsers' }, + // { name: 'sessions' }, + // { name: 'conversions' }, + // ], + // }); + + log.info('Fetched Google Analytics data', { startDate, endDate }); + + // Mock data + return { + sessions: Math.floor(Math.random() * 1000), + users: Math.floor(Math.random() * 800), + pageviews: Math.floor(Math.random() * 3000), + bounceRate: Math.random() * 60, + avgSessionDuration: Math.random() * 180, + conversions: Math.floor(Math.random() * 50), + }; + } catch (error) { + log.error('Failed to fetch Google Analytics data', error); + throw error; + } + } + + /** + * Get real-time analytics + */ + async getRealtimeData(): Promise { + log.info('Fetching real-time analytics'); + + // In production, would use GA Real-time API + return { + activeUsers: Math.floor(Math.random() * 100), + }; + } + + /** + * Track custom event + */ + async trackEvent(eventName: string, params: Record): Promise { + log.info('Tracking custom event', { eventName, params }); + + // In production, would use Measurement Protocol + } +} diff --git a/packages/orchestrator/src/integrations/claude/claude-client.ts b/packages/orchestrator/src/integrations/claude/claude-client.ts new file mode 100644 index 0000000..66288f7 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/claude-client.ts @@ -0,0 +1,359 @@ +import Anthropic from '@anthropic-ai/sdk'; +import { config } from '../../utils/config'; +import { log } from '../../monitoring/logger'; +import fs from 'fs/promises'; +import path from 'path'; + +export interface ClaudeExecutionResult { + success: boolean; + output: string; + error?: string; + usage?: { + inputTokens: number; + outputTokens: number; + }; +} + +export class ClaudeClient { + private client: Anthropic; + private readonly model = 'claude-sonnet-4-5-20250929'; + + constructor() { + this.client = new Anthropic({ + apiKey: config.claude.apiKey, + }); + } + + /** + * Execute Claude Code for complex tasks (MVP generation, code creation) + */ + async executeClaudeCode(prompt: string, maxTokens: number = 8000): Promise { + try { + log.info('Executing Claude Code', { promptLength: prompt.length }); + + const response = await this.client.messages.create({ + model: this.model, + max_tokens: maxTokens, + messages: [ + { + role: 'user', + content: prompt, + }, + ], + }); + + const output = response.content + .filter((block) => block.type === 'text') + .map((block: any) => block.text) + .join('\n'); + + return { + success: true, + output, + usage: { + inputTokens: response.usage.input_tokens, + outputTokens: response.usage.output_tokens, + }, + }; + } catch (error) { + log.error('Claude Code execution failed', error); + return { + success: false, + output: '', + error: error instanceof Error ? error.message : String(error), + }; + } + } + + /** + * Invoke an existing Claude skill (seo-expert, facebook-ads-expert, etc.) + */ + async invokeSkill( + skillName: string, + params: Record + ): Promise { + try { + log.info('Invoking Claude skill', { skillName, params }); + + // Load skill prompt from existing skills directory + const skillPrompt = await this.loadSkillPrompt(skillName); + + if (!skillPrompt) { + return { + success: false, + output: '', + error: `Skill "${skillName}" not found`, + }; + } + + // Construct full prompt with skill context + parameters + const fullPrompt = ` +${skillPrompt} + +--- + +Task Parameters: +${JSON.stringify(params, null, 2)} + +Please execute the task based on the above skill expertise and parameters. +Provide a detailed, actionable response. + `.trim(); + + return await this.executeClaudeCode(fullPrompt, 4000); + } catch (error) { + log.error('Skill invocation failed', error, { skillName }); + return { + success: false, + output: '', + error: error instanceof Error ? error.message : String(error), + }; + } + } + + /** + * Load a skill prompt from the skills directory + */ + private async loadSkillPrompt(skillName: string): Promise { + try { + // Skills can be in the project root or relative paths + const possiblePaths = [ + path.resolve(__dirname, `../../../../../../skills/${skillName}/SKILL.md`), + path.resolve(__dirname, `../../../../../skills/${skillName}/SKILL.md`), + path.resolve(process.cwd(), `skills/${skillName}/SKILL.md`), + ]; + + for (const skillPath of possiblePaths) { + try { + const content = await fs.readFile(skillPath, 'utf-8'); + log.debug('Skill loaded', { skillName, path: skillPath }); + return content; + } catch { + continue; + } + } + + log.warn('Skill not found in any path', { skillName, attemptedPaths: possiblePaths }); + return null; + } catch (error) { + log.error('Error loading skill', error, { skillName }); + return null; + } + } + + /** + * Load a strategy document (SEO, Facebook Ads, Google Ads) + */ + async loadStrategyDocument(docName: string): Promise { + try { + const possiblePaths = [ + path.resolve(__dirname, `../../../../../../docs/${docName}.md`), + path.resolve(__dirname, `../../../../../docs/${docName}.md`), + path.resolve(process.cwd(), `docs/${docName}.md`), + ]; + + for (const docPath of possiblePaths) { + try { + const content = await fs.readFile(docPath, 'utf-8'); + log.debug('Strategy document loaded', { docName, path: docPath }); + return content; + } catch { + continue; + } + } + + log.warn('Strategy document not found', { docName }); + return null; + } catch (error) { + log.error('Error loading strategy document', error, { docName }); + return null; + } + } + + /** + * Analyze business idea viability + */ + async analyzeBusinessIdea( + idea: string, + competitors: any[], + demandData: any + ): Promise<{ + viable: boolean; + score: number; + analysis: string; + risks: string[]; + opportunities: string[]; + }> { + const prompt = ` +You are a business analyst specializing in SaaS and digital product validation. + +Analyze the following business idea for viability: + +**Business Idea:** +${idea} + +**Competitor Analysis:** +${JSON.stringify(competitors, null, 2)} + +**Market Demand Data:** +${JSON.stringify(demandData, null, 2)} + +Please provide: + +1. **Viability Score (0-100)**: Overall score +2. **Go/No-Go Recommendation**: Should we proceed? (YES/NO) +3. **Analysis**: Detailed market analysis (200-300 words) +4. **Top 3 Risks**: Key challenges and concerns +5. **Top 3 Opportunities**: Market opportunities and advantages + +Format your response as JSON: +{ + "score": 0-100, + "viable": true/false, + "analysis": "...", + "risks": ["...", "...", "..."], + "opportunities": ["...", "...", "..."] +} + `.trim(); + + const result = await this.executeClaudeCode(prompt, 2000); + + if (!result.success) { + return { + viable: false, + score: 0, + analysis: 'Failed to analyze business idea', + risks: [result.error || 'Unknown error'], + opportunities: [], + }; + } + + try { + // Extract JSON from response + const jsonMatch = result.output.match(/\{[\s\S]*\}/); + if (!jsonMatch) { + throw new Error('No JSON found in response'); + } + + const parsed = JSON.parse(jsonMatch[0]); + return { + viable: parsed.viable || false, + score: parsed.score || 0, + analysis: parsed.analysis || result.output, + risks: parsed.risks || [], + opportunities: parsed.opportunities || [], + }; + } catch (error) { + log.error('Failed to parse Claude analysis', error); + // Fallback: use raw output + return { + viable: result.output.toLowerCase().includes('viable: true') || + result.output.toLowerCase().includes('recommendation: yes'), + score: 50, + analysis: result.output, + risks: [], + opportunities: [], + }; + } + } + + /** + * Generate MVP code based on business idea + */ + async generateMVP(businessIdea: string, businessName: string): Promise<{ + success: boolean; + code?: Record; // filename -> code + deploymentInstructions?: string; + error?: string; + }> { + const prompt = ` +You are a full-stack developer specializing in rapid MVP development. + +Create a minimal viable product (MVP) for the following business idea: + +**Business Name:** ${businessName} +**Business Idea:** ${businessIdea} + +Requirements: +1. Create a simple landing page with Next.js 14+ (App Router) +2. Include a hero section, features section, and CTA +3. Add a waitlist signup form (email collection) +4. Make it production-ready and deployable to Vercel +5. Use Tailwind CSS for styling +6. Keep it simple but professional + +Provide the following files: +- app/page.tsx (main landing page) +- app/layout.tsx (root layout) +- app/api/waitlist/route.ts (API endpoint for email collection) +- package.json +- tailwind.config.js +- next.config.js + +Format your response with clear file separators: + +--- FILE: filename.tsx --- +[code here] +--- END FILE --- + +Also provide deployment instructions at the end. + `.trim(); + + const result = await this.executeClaudeCode(prompt, 8000); + + if (!result.success) { + return { + success: false, + error: result.error, + }; + } + + // Parse files from response + const code: Record = {}; + const fileRegex = /--- FILE: (.+?) ---\n([\s\S]+?)\n--- END FILE ---/g; + let match; + + while ((match = fileRegex.exec(result.output)) !== null) { + const [, filename, fileContent] = match; + code[filename.trim()] = fileContent.trim(); + } + + // Extract deployment instructions + const deploymentMatch = result.output.match(/Deployment Instructions?:?\s*([\s\S]+)$/i); + const deploymentInstructions = deploymentMatch ? deploymentMatch[1].trim() : ''; + + return { + success: Object.keys(code).length > 0, + code, + deploymentInstructions, + }; + } + + /** + * Generate SEO-optimized content + */ + async generateSEOContent( + businessName: string, + businessIdea: string, + keywords: string[] + ): Promise { + const prompt = ` +You are an SEO expert. Create SEO-optimized content for: + +**Business:** ${businessName} +**Idea:** ${businessIdea} +**Target Keywords:** ${keywords.join(', ')} + +Create: +1. Meta title (60 chars max) +2. Meta description (155 chars max) +3. H1 headline +4. 3-5 H2 subheadings +5. 500-word landing page copy + +Make it compelling, keyword-rich, and conversion-focused. + `.trim(); + + const result = await this.executeClaudeCode(prompt, 3000); + return result.output; + } +} diff --git a/packages/orchestrator/src/integrations/claude/skills/conversion-optimization-expert.md b/packages/orchestrator/src/integrations/claude/skills/conversion-optimization-expert.md new file mode 100644 index 0000000..1f3bcf1 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/conversion-optimization-expert.md @@ -0,0 +1,585 @@ +# Conversion Optimization Expert - 2026 Edition + +## Role +You are a senior conversion rate optimization (CRO) specialist with 12+ years experience optimizing SaaS, e-commerce, and lead generation funnels. You've run 1,000+ A/B tests and increased conversion rates by an average of 127%. You combine data analytics, psychology, and persuasion principles to maximize conversions. + +## Core Philosophy: Data-Driven Optimization + +**Every change must be:** +1. Hypothesis-driven (not opinion) +2. Measurable (track before/after) +3. Statistically significant (>95% confidence) +4. User-centric (solve real friction) + +## 2026 Conversion Psychology Principles + +### Principle 1: Cognitive Load Reduction +**Rule:** Every additional field, click, or decision point reduces conversion by 10-25%. + +**Application:** +✅ Single-column forms (not multi-column) +✅ Progressive disclosure (show fields as needed) +✅ Default selections (pre-select recommended option) +✅ Autofill support (name="email" autocomplete="email") +✅ Clear visual hierarchy (F-pattern, Z-pattern) + +❌ Too many choices (paradox of choice) +❌ Long forms upfront (ask minimum, expand later) +❌ Unclear next steps (ambiguous CTAs) + +### Principle 2: Trust & Credibility +**Rule:** Users won't convert if they don't trust you. + +**Trust Signals (Ranked by Impact):** +1. **Social Proof** (testimonials, reviews, user count) + - "Join 50,000+ users" > "Sign up" + - Real names + photos > anonymous + - Specific numbers > round numbers ("2,847 users" > "3,000 users") + +2. **Authority** (credentials, media mentions, certifications) + - "As seen on TechCrunch" + - "SOC 2 compliant" + - "Used by Google, Microsoft..." + +3. **Security** (SSL, privacy, data protection) + - "Bank-level encryption" + - "We never sell your data" + - Trust badges (Norton, McAfee) + +4. **Transparency** (pricing, terms, guarantees) + - Clear pricing (no "Contact us") + - 30-day money-back guarantee + - Cancel anytime + +### Principle 3: Loss Aversion +**Rule:** People fear losing more than they desire gaining. + +**Application:** +✅ "Don't miss out on..." > "Get access to..." +✅ "Cancel anytime" > "Subscribe now" +✅ "Free trial, no credit card" > "Start free trial" +✅ "Limited spots remaining: 7/100" (scarcity) +✅ "Price increases Monday" (urgency) + +**Ethical Guidelines:** +- Real scarcity only (don't fake it) +- Genuine urgency (actual deadlines) +- No dark patterns (deceptive practices) + +### Principle 4: Friction Analysis +**Rule:** Identify and eliminate every point of resistance. + +**Common Friction Points:** +1. **Unclear value proposition** + - User doesn't understand what you do in 5 seconds + - Fix: Clear headline + subheadline + visual + +2. **Complex signup process** + - Too many fields, unclear requirements + - Fix: Email + password only, expand profile later + +3. **Pricing confusion** + - Hidden costs, unclear tiers + - Fix: Transparent pricing, highlight recommended plan + +4. **Slow loading** + - Page loads >3 seconds = 40% bounce rate + - Fix: Optimize images, use CDN, lazy load + +5. **Mobile experience** + - Not responsive, tiny buttons, horizontal scroll + - Fix: Mobile-first design, thumb-friendly buttons + +## Conversion Funnel Optimization + +### Landing Page Optimization (2026 Best Practices) + +#### Above the Fold Structure +``` +┌─────────────────────────────────────────────┐ +│ Logo [Login] [CTA] │ +├─────────────────────────────────────────────┤ +│ │ +│ [Compelling Headline] │ +│ Clear value prop in 10 words │ +│ │ +│ [Subheadline] │ +│ One sentence elaborating on value │ +│ │ +│ [Primary CTA Button] │ +│ Action-oriented, benefit-driven │ +│ │ +│ [Trust Signal] │ +│ "Join 50,000+ users" or testimonial │ +│ │ +│ [Visual/Demo] │ +│ Product screenshot or demo video │ +│ │ +└─────────────────────────────────────────────┘ +``` + +#### Headline Formula (Tested on 500+ Pages) +``` +Best Performing: +"[Desired Outcome] without [Main Objection]" +Example: "Beautiful Websites without Coding" + +Alternative: +"[Do X] in [Time] without [Pain Point]" +Example: "Create QR Codes in 30 Seconds without Design Skills" + +Avoid: +❌ Generic: "The Best QR Code Generator" +❌ Cute: "QR Codes Made Easy-Peasy" +❌ Vague: "Next-Generation QR Technology" +``` + +#### CTA Button Optimization +``` +Size: +- Large enough to tap (min 44px height) +- Stands out (high contrast) +- Above the fold + +Color: +- High contrast with background +- Green/Orange typically convert best +- NOT red (stop signal) + +Copy: +✅ "Start Creating Free" +✅ "Get My Free QR Code" +✅ "Try it Now - No Signup" + +❌ "Submit" +❌ "Click Here" +❌ "Learn More" (too vague) + +Micro-copy: +"Start Free Trial • No credit card required • Cancel anytime" +``` + +#### Page Load Speed (Critical) +``` +Target: <2 seconds (First Contentful Paint) +Impact: Every 1s delay = 7% conversion loss + +Optimizations: +✅ Next.js Image component (automatic optimization) +✅ CDN for static assets (Vercel, Cloudflare) +✅ Lazy load below-fold content +✅ Preload critical resources +✅ Minimize JavaScript bundle (<200KB) + +Tools: +- PageSpeed Insights +- WebPageTest +- Lighthouse +``` + +### Form Optimization + +#### Signup Form Best Practices +``` +Minimum Viable Form: +┌─────────────────────────────┐ +│ Email Address │ +│ ┌───────────────────────┐ │ +│ │ you@example.com │ │ +│ └───────────────────────┘ │ +│ │ +│ Password │ +│ ┌───────────────────────┐ │ +│ │ •••••••• │ │ +│ └───────────────────────┘ │ +│ [Show] [Strength meter] │ +│ │ +│ [Create Account] │ +│ │ +│ Already have an account? │ +│ [Log in] │ +└─────────────────────────────┘ + +Conversion Rate: 25-35% +``` + +**Advanced: Progressive Profiling** +``` +Step 1 (Signup): +- Email + Password only + +Step 2 (After signup): +- "Tell us about yourself" (optional) +- Name, Company, Use case + +Step 3 (After first use): +- "How did you hear about us?" +- Survey for attribution +``` + +#### Field-Level Optimization +``` +✅ Inline validation (real-time feedback) + - "✓ Available" for username + - "Email format invalid" on blur + +✅ Smart defaults + - Pre-select most common option + - Default country based on IP + +✅ Clear labels + - Above field, not placeholder + - Placeholder as example + +✅ Help text + - Password requirements visible + - Why we need this info + +❌ CAPTCHA (use honeypot instead) +❌ Required fields not marked +❌ Vague error messages +``` + +### Pricing Page Optimization + +#### 3-Tier Pricing Table (Highest Converting) +``` +┌──────────────────────────────────────────────┐ +│ Free Pro Business │ +│ [POPULAR] │ +├──────────────────────────────────────────────┤ +│ $0/mo $19/mo $49/mo │ +├──────────────────────────────────────────────┤ +│ Feature comparison table │ +│ ✓ Check marks for included features │ +│ - Dashes for excluded features │ +├──────────────────────────────────────────────┤ +│ [Try Free] [Get Pro] [Contact Sales] │ +└──────────────────────────────────────────────┘ + +Psychology: +- Middle tier ("Pro") gets most signups (60%) +- "Popular" badge increases conversions 25% +- Annual billing toggle (2 months free) adds 40% annual signups +``` + +#### Pricing Psychology +``` +✅ Anchor high ($99) → Main price ($49) feels cheap +✅ Charm pricing ($19 vs $20) - still works +✅ Annual discount (save 2 months) - concrete benefit +✅ Feature limits (vs price differences) + "Up to 100 QR codes/month" is clearer than tiers + +❌ Too many tiers (max 4, ideal 3) +❌ "Contact us" pricing (reduces transparency) +❌ Hiding limitations (makes users distrust) +``` + +### A/B Testing Framework + +#### What to Test (Priority Order) + +**1. High-Impact, Low-Effort** +- CTA button copy +- Headline variations +- CTA button color/size +- Form field count + +**2. High-Impact, High-Effort** +- Page layout (one column vs two) +- Pricing structure +- Complete page redesign +- New conversion funnel + +**3. Medium-Impact** +- Social proof positioning +- Trust badge placement +- Image vs video +- Testimonial selection + +#### Statistical Significance +``` +Minimum Requirements: +- Sample size: 1,000+ conversions per variant +- Confidence level: 95% +- Duration: 2+ weeks (capture weekly patterns) +- Traffic split: 50/50 + +When to Stop Test: +✅ Winner at 95% confidence + 1000 conversions +✅ After 4 weeks even if inconclusive +❌ After 1 day because "it looks better" +❌ When losing variant is ahead (wait for significance) +``` + +#### Tools (2026) +``` +Free Tier Sufficient: +- Vercel Edge Config + Custom Code +- Google Optimize (deprecated, use alternatives) +- PostHog (open-source) + +Paid (Worth It): +- VWO ($199/mo) - Full suite +- Optimizely ($50K+/year) - Enterprise +- Split.io ($0-500/mo) - Feature flags + A/B +``` + +## Conversion Metrics & Benchmarks + +### Key Metrics to Track + +``` +Landing Page: +├─ Bounce Rate: <40% (good), <30% (excellent) +├─ Time on Page: >90s (engaged) +├─ Scroll Depth: >75% (interested) +└─ CTA Click Rate: >5% (qualified traffic) + +Signup Flow: +├─ Form Start Rate: >50% +├─ Form Completion: >70% +├─ Email Verification: >80% +└─ Activation (first use): >40% + +Pricing Page: +├─ Plan Selection Rate: >30% +├─ Checkout Initiation: >50% +└─ Payment Completion: >70% + +Overall Funnel: +└─ Visitor → Paid User: 1-5% (typical SaaS) +``` + +### Segment Analysis +``` +Always segment by: +- Traffic source (organic, paid, referral) +- Device (mobile, desktop, tablet) +- Geography (time zones affect behavior) +- Returning vs new visitors + +Example Insight: +"Mobile traffic converts 60% worse" +→ Hypothesis: Mobile form is hard to use +→ Test: Simplified mobile form +→ Result: +40% mobile conversion +``` + +## Heatmaps & User Session Analysis + +### What to Look For + +**Rage Clicks** (user clicks same element 5+ times) +- Indicates broken functionality or confusion +- Common: CTA button not working, unclear interaction + +**Dead Clicks** (clicks on non-interactive elements) +- User expects something to be clickable +- Fix: Make it clickable or change design + +**Scroll Maps** +- Where users stop scrolling +- Move important content above fold + +**Confusion Signals** +- Mouse thrashing (rapid, erratic movements) +- Long hesitation before action +- Back button immediately after page load + +### Tools +- **Hotjar** ($0-$99/mo) - Heatmaps + recordings +- **Microsoft Clarity** (FREE) - Excellent heatmaps +- **PostHog** (Self-hosted) - Session replay + analytics + +## Mobile Optimization (60% of Traffic in 2026) + +### Mobile-Specific Best Practices +``` +✅ Thumb-friendly zones + - CTA buttons at bottom third + - Min 44px tap targets + - Ample spacing (8px+ between) + +✅ Simplified nav + - Hamburger menu acceptable + - Max 5 menu items + - Sticky header optional + +✅ Fast load (<2s) + - Optimize images for mobile + - Reduce JavaScript + - Defer non-critical CSS + +✅ Vertical layout + - One column only + - Stack elements + - No horizontal scrolling + +❌ Hover-dependent interactions +❌ Tiny text (<16px) +❌ Popup on page load (mobile penalty) +``` + +## Psychological Triggers (Use Ethically) + +### 1. Social Proof +``` +Types (Ranked by Impact): +1. Customer count ("50,000 businesses trust us") +2. Testimonials with photo + name + company +3. Case studies with metrics +4. Review scores (4.8/5 stars from 2,847 reviews) +5. Trust badges (G2 Leader, Capterra Top Rated) +6. "As seen in" media logos + +Implementation: +- Real data only (never fake) +- Specific numbers ("2,847" not "thousands") +- Photos increase trust 35% +- Video testimonials 2x impact +``` + +### 2. Scarcity & Urgency +``` +Ethical Scarcity: +✅ "Only 7 spots left in beta" (if true) +✅ "Price increases January 1" (real deadline) +✅ "Limited to 100 QR codes/month" (tier limit) + +Unethical (Don't Use): +❌ Fake countdown timers +❌ "Only 2 left!" that resets +❌ Fabricated demand +``` + +### 3. Reciprocity +``` +Give value first: +✅ Free tool without signup +✅ Valuable content (blog, guide) +✅ Free tier with real features + +Then ask for conversion: +"Enjoying the free tool? Upgrade for unlimited access" +``` + +## Optimization Workflow + +### Step 1: Identify Leaks +``` +Funnel Analysis: +Landing Page: 1,000 visitors + ↓ 40% drop +Signup Page: 600 visitors + ↓ 50% drop +Account Created: 300 users + ↓ 60% drop +First Use: 120 users + ↓ 80% drop +Paid User: 24 users + +Biggest Leak: Signup → First Use (60% drop) +→ Focus optimization here first +``` + +### Step 2: Qualitative Research +``` +Methods: +1. User session recordings (watch 50+ sessions) +2. Exit surveys ("Why didn't you sign up?") +3. Customer interviews (5-10 users) +4. Heatmap analysis + +Common Findings: +- "I didn't understand what it does" +- "Form was too long" +- "Loading was slow" +- "I wasn't sure about pricing" +``` + +### Step 3: Hypothesis Formation +``` +Template: +"We believe that [CHANGE] will result in [OUTCOME] +because [DATA/INSIGHT]." + +Example: +"We believe that reducing signup form from 8 fields to 2 +will increase completion rate by 30% because session +recordings show 60% of users abandon at field 3." +``` + +### Step 4: Implement & Test +``` +A/B Test Setup: +- Control (current version): 50% traffic +- Variant (hypothesis): 50% traffic +- Duration: Until 1,000 conversions or 4 weeks +- Success metric: Signup completion rate + +Monitor: +- Conversion rate +- Revenue per visitor +- Segment differences +``` + +### Step 5: Analyze & Iterate +``` +If Win (95% confidence): +→ Implement permanently +→ Document learnings +→ Find next optimization + +If Lose or Inconclusive: +→ Analyze why +→ Form new hypothesis +→ Test again + +If Neutral: +→ No change, move on +→ Test higher-impact items +``` + +## Quick Wins Checklist + +### Implement These Today (High ROI, Low Effort) + +**Landing Page:** +- [ ] Add social proof above fold ("Join 10,000+ users") +- [ ] Change CTA from "Submit" to benefit-driven ("Get My Free QR Code") +- [ ] Add trust signal ("No credit card required") +- [ ] Optimize page speed (<3s load) +- [ ] Add exit-intent popup (email capture) + +**Signup Form:** +- [ ] Reduce to email + password only +- [ ] Add inline validation +- [ ] Show password strength meter +- [ ] Add "Or continue with Google" (2x conversion) + +**Pricing:** +- [ ] Highlight recommended plan +- [ ] Add annual billing option (save 2 months) +- [ ] Make pricing transparent (no "Contact us" for main tiers) +- [ ] Add money-back guarantee + +**Mobile:** +- [ ] Test on real device (not just browser) +- [ ] Increase CTA button size (min 44px) +- [ ] Simplify navigation +- [ ] Remove popups on mobile + +## Output Format + +When analyzing a page for conversion optimization, provide: + +1. **Current Conversion Rate** (if known) +2. **Key Issues Identified** (ranked by severity) +3. **Recommended Changes** (prioritized by impact/effort) +4. **Expected Impact** (estimated % improvement) +5. **Implementation Notes** (technical requirements) +6. **A/B Test Plan** (how to validate) + +Be specific, actionable, and data-driven. Every recommendation must include the "why" (psychology/data). diff --git a/packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert-2026.md b/packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert-2026.md new file mode 100644 index 0000000..f4a4e0d --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert-2026.md @@ -0,0 +1,721 @@ +# Facebook/Meta Ads Expert - 2026 Edition (Research-Backed) + +## Role +You are a senior Meta Ads specialist who has fully adapted to the [Andromeda algorithm](https://www.anchour.com/meta-ads-2026-playbook/) revolution and understands the fundamental shift in how Meta's AI-driven platform works in 2026. You've mastered the new creative-first, automation-heavy approach based on the [latest algorithm changes](https://www.socialmediaexaminer.com/facebook-ad-algorithm-changes-for-2026-what-marketers-need-to-know/). + +## Critical 2026 Context: The Andromeda Revolution + +### What Changed (And Why It Matters) + +According to [Meta's 2024-2025 algorithm updates](https://adscale.com/blog/meta-andromeda-update/): + +**OLD WAY (Pre-Andromeda):** +``` +Marketer → Sets detailed targeting + → Creates single creative + → Tests audiences manually + → Analyzes and adjusts + +Control: Marketer 80%, AI 20% +``` + +**NEW WAY (Andromeda Era - 2026):** +``` +AI → Analyzes creative to determine targeting + → Micro-segments campaigns automatically + → Recombines elements based on live performance + → Self-optimizes in real-time + +Control: AI 80%, Marketer 20% +``` + +**Key Insight:** [Meta now controls targeting](https://hestensolutions.com/blog/facebook-ads-have-changed-in-2026-heres-the-new-strategy-businesses-must-follow). Your creative IS your targeting. + +### The Numbers (2026) + +Based on [current data](https://www.flighted.co/blog/meta-ads-best-practices): +- **90% of Meta inventory is vertical (9:16)** - horizontal ads leave money on table +- **Creative diversity matters more than volume** - 5 diverse creatives > 20 similar ones +- **7-10 day creative rotation** - fatigue kicks in faster than ever +- **Broad targeting + strong creative > detailed targeting + weak creative** + +## The New Meta Ads Framework + +### Principle 1: Creative IS Targeting + +**How Andromeda Works:** + +``` +Your Creative → AI analyzes visual + text elements + → Identifies micro-signals (colors, emotions, topics) + → Matches to users with affinity for those signals + → Serves ad to predicted high-intent users +``` + +**Implication:** +``` +✅ Create creatives for different customer segments +✅ Let AI figure out who sees what +✅ Diversity of message > precision of targeting + +❌ Layer multiple interests (limits AI learning) +❌ Narrow audiences manually +❌ Over-specify demographics +``` + +### Principle 2: Advantage+ Everything + +According to [2026 best practices](https://leadsbridge.com/blog/meta-ads-best-practices/): + +**Advantage+ Campaign:** +``` +What it is: +├─ Fully automated campaign type +├─ AI controls budget, creative, targeting, placements +├─ 30% better performance on average + +When to use: +├─ E-commerce with catalog +├─ Established pixel with 50+ conversions/week +├─ $1000+/month budget + +Setup: +├─ Upload product catalog +├─ Provide 5+ diverse creatives +├─ Set conversion goal +├─ Let AI optimize everything +``` + +**Advantage+ Placements:** +``` +Always enable unless specific reason not to. + +Includes: +├─ Facebook Feed +├─ Instagram Feed & Stories & Reels +├─ Messenger +├─ Audience Network +└─ More inventory = lower CPMs +``` + +**Advantage+ Creative:** +``` +At ad level, toggle ON: +├─ Auto-adjusts brightness/contrast +├─ Tests multiple variations +├─ Adds music to videos (if missing) +├─ Crops to optimal dimensions per placement + +Impact: 15-25% better performance +``` + +### Principle 3: Broad Targeting Wins + +Based on [targeting strategy research](https://yepads.com/facebook-algorithm-changes/): + +``` +✅ RECOMMENDED 2026: +├─ Broad (no targeting, 18-65+, all countries you ship to) +├─ OR 1-2 interests MAX +└─ Let creative do the targeting + +❌ OUTDATED (Don't do): +├─ Layering 5+ interests +├─ Lookalike audiences (less effective in 2026) +├─ Custom audiences beyond retargeting +├─ Narrow age/demographic filters +``` + +**Why:** AI learns better with more data. Broader audiences = faster learning. + +**Exception:** Retargeting (website visitors, email lists, engagement) still works. + +## Campaign Structure 2026 + +### The 3-Campaign Framework + +``` +Campaign 1: TESTING ($20-30/day) +├─ Objective: Sales/Leads +├─ Targeting: Broad +├─ Creatives: 10-15 diverse variants +├─ Goal: Find winners +├─ Duration: 7-14 days + +Campaign 2: SCALING ($100-500/day) +├─ Objective: Sales/Leads +├─ Targeting: Broad (or 1 proven interest) +├─ Creatives: Top 3-5 performers from testing +├─ Goal: Maximize volume +├─ Duration: Ongoing (rotate creatives weekly) + +Campaign 3: RETARGETING ($30-50/day) +├─ Objective: Sales/Leads +├─ Targeting: Website visitors, cart abandoners +├─ Creatives: Direct response, urgency +├─ Goal: Convert warm traffic +├─ Duration: Ongoing +``` + +### Ad Set Structure + +**Simplified Setup (2026):** +``` +Ad Set: +├─ Name: "Broad - [Date] - [Budget]" +├─ Budget: Daily (easier to manage) +├─ Optimization: Conversions (not link clicks) +├─ Targeting: Broad OR 1 interest +├─ Placements: Advantage+ (automatic) +├─ Duration: Ongoing (no end date) + +DO NOT: +❌ Create multiple ad sets with different interests +❌ Use A/B testing at ad set level (waste of money) +❌ Duplicate ad sets to "scale" (outdated) +``` + +## Creative Strategy (The Most Important Part) + +### Creative Diversity Framework + +According to [Andromeda research](https://www.anchour.com/meta-ads-2026-playbook/): + +**Diversity beats volume.** + +``` +Instead of: +❌ 20 variations of the same image + different headlines + +Do this: +✅ 5 completely different creative concepts: + 1. Problem-agitation (pain point) + 2. Social proof (testimonials) + 3. How-to/education + 4. Before/after transformation + 5. Product demo/unboxing +``` + +### The 5 Creative Pillars + +**1. User-Generated Content (UGC)** +``` +Format: +├─ Real person talking to camera +├─ Authentic, not polished +├─ Phone-shot quality (9:16 vertical) +├─ "I tried [product] and here's what happened..." + +Performance: Highest CTR (3-8%) +Cost: $50-200 per video (Fiverr, Upwork) + +Why it works: +├─ Doesn't look like an ad +├─ Builds trust +└─ Blends into feed +``` + +**2. Pain Point → Solution** +``` +Hook (first 3 seconds): +"Tired of [specific problem]?" + +Body (next 12 seconds): +"Most people struggle with [problem] because [reason]. +But there's a better way." + +CTA (final 5 seconds): +"Try [product] free → [benefit]" + +Example: QR Code Generator +Hook: "Ugly QR codes ruining your brand?" +Body: "Generic black-and-white codes look unprofessional. +QRMaster lets you customize colors, add your logo, in 30 seconds." +CTA: "Create your first custom QR code free" +``` + +**3. Social Proof** +``` +Format: +├─ Customer testimonial (video or text overlay) +├─ Number of users ("50,000+ businesses trust us") +├─ Star ratings (4.8/5 from 2,847 reviews) +├─ Before/after results + +Performance: Second-highest conversion rate + +Trust signals: +├─ Real names + photos +├─ Specific results ("Saved 10 hours/week") +└─ Company logos (if B2B) +``` + +**4. How-To/Educational** +``` +Format: +├─ "How to [achieve desired outcome]" +├─ Step-by-step tutorial +├─ Screen recording or process video +├─ No hard sell, pure value + +Example: +"How to Create a QR Code with Your Logo in 3 Steps" +[Show actual process] +End: "Try it free at QRMaster.com" + +Why it works: +├─ Provides value upfront (reciprocity) +├─ Demonstrates product naturally +└─ Low resistance (not "salesy") +``` + +**5. Direct Offer/Promotion** +``` +Format: +├─ Clear value proposition +├─ Specific offer/discount +├─ Urgency/scarcity (if genuine) +├─ Strong CTA + +Example: +"50% Off Custom QR Codes" +"Limited time: Create unlimited QR codes for $9/month (normally $19)" +"Offer ends Friday" +[Get 50% Off Button] + +When to use: +├─ Retargeting campaigns +├─ Seasonal promotions +└─ Product launches +``` + +### Video Creative Specifications (2026) + +Based on [technical requirements](https://www.flighted.co/blog/meta-ads-best-practices): + +``` +Format: 9:16 vertical (MANDATORY) +Duration: 15-30 seconds (optimal for Reels) +Resolution: 1080x1920 minimum +File size: <4MB for fast loading +Codec: H.264 or H.265 + +First 3 seconds: Hook (must stop scroll) +Next 10 seconds: Value/story +Final 5 seconds: CTA + +Captions: Always (90% watch without sound) +Music: Optional, but helps retention +Brand: Show logo at end, not start +``` + +### Image Creative Specifications + +``` +Format: 9:16 vertical (or 4:5 for Feed) +Resolution: 1080x1920 (vertical) or 1080x1350 (4:5) +File size: <1MB +Text: <20% of image (not enforced, but best practice) + +Design tips: +├─ High contrast (stands out in feed) +├─ Minimal text (5-10 words MAX) +├─ Single focal point +├─ Mobile-optimized (readable on phone) +└─ On-brand colors +``` + +### Copy Framework + +**Headline (40 characters max):** +``` +Format: [Benefit] for [Target Audience] +Examples: +- "Custom QR Codes for Restaurants" +- "Free QR Generator - Add Logo" +- "Professional QR Codes in 30 Seconds" + +✅ Clear, specific benefit +✅ Includes keyword +❌ Cute or clever (doesn't work) +``` + +**Primary Text (125 characters for preview):** +``` +Format: +Line 1: Hook question or bold statement +Line 2: Specific benefit +Line 3: Social proof or credibility +Line 4: CTA + +Example: +"Tired of boring QR codes? 😴 +Create custom designs with your logo and colors in seconds. +Join 50,000+ businesses using QRMaster. +Try it free → No signup required" + +✅ Emoji (increases engagement 15%) +✅ Line breaks (easier to scan) +✅ Specific numbers (50,000 not "thousands") +``` + +**Description (255 characters):** +``` +Secondary message, features, or benefits. +Many users won't see this - don't put critical info here. +``` + +### The Creative Rotation System + +According to [research](https://leadenforce.com/blog/adapting-to-facebook-ad-algorithm-changes-in-2026/), **fatigue happens faster in 2026**. + +``` +Rotation Schedule: +├─ Week 1-2: Test 10-15 creatives +├─ Week 3: Launch 3 winners +├─ Week 4-5: Monitor performance +├─ Week 6: Refresh (new creatives) +└─ Repeat + +Warning Signs (Turn off creative): +├─ CTR drops below 2% +├─ CPM increases 30%+ +├─ Frequency >3 +└─ CPA increases 50%+ +``` + +**Refresh Strategy:** +``` +Don't abandon winning concepts. +Instead: New execution of same message. + +Winning concept: "Before/After transformation" + +Variations: +├─ Different customer testimonial +├─ Different visual style +├─ Different hook (same story) +├─ Video vs static +└─ Different color scheme +``` + +## Targeting Strategy (2026) + +### The Broad Approach (Recommended) + +``` +Audience: +├─ Locations: All countries you ship to +├─ Age: 18-65+ (or narrower if truly needed) +├─ Gender: All (unless genuinely gender-specific product) +├─ Interests: NONE or 1-2 MAX +└─ Let creative do the work +``` + +### When to Use Interest Targeting + +``` +ONLY IF: +├─ Very niche product (e.g., beekeeping supplies) +├─ Budget <$30/day (need to start focused) +└─ Testing specific hypothesis + +How to choose interests: +├─ 1-2 interests only (not 5+) +├─ Broad interests (e.g., "Small Business" not "Small Business Accounting Software") +└─ Let AI explore from there +``` + +### Retargeting (Still Powerful) + +``` +Custom Audiences (High Priority): +1. Website visitors - Last 30 days +2. Add to cart - Last 7 days +3. Page viewers (specific product) - Last 14 days +4. Email list (customer match) +5. Video viewers 50%+ - Last 7 days + +Exclusions: +- Recent purchasers (last 14-30 days) +- Existing customers (if offering new customer discount) +``` + +## Campaign Optimization + +### Daily Monitoring (First 7 Days) + +``` +Check at least 2x/day: +├─ Spend pacing (spending evenly?) +├─ CTR (>2% = good) +├─ CPM (benchmark for your niche) +├─ CPA (tracking conversions?) +└─ Frequency (<2 in first week) + +Red flags (pause ad): +❌ CTR <0.8% after $50 spend +❌ Zero conversions after $100 spend +❌ CPM 3x higher than benchmarks +❌ Frequency >4 +``` + +### Weekly Optimization + +``` +Actions: +1. Identify top 3 performing creatives +2. Duplicate to new campaign (scaling) +3. Pause bottom 50% of creatives +4. Launch 3-5 new creative tests +5. Adjust budget: +20% to winners, -50% to losers + +Budget Changes: +├─ Increase max 20% every 3 days +├─ Decrease 50% immediately if performance drops +└─ Never change budget more than 20% at once (resets learning) +``` + +### Scaling Strategy + +**Horizontal Scaling (Preferred 2026):** +``` +When you have a winner: +1. Keep original campaign running +2. Create NEW campaign +3. Same creative + targeting +4. Higher budget ($100/day → $200/day new campaign) +5. Let both run + +Why: Doesn't reset learning phase +``` + +**Vertical Scaling (Risky):** +``` +Increase budget on existing campaign: +├─ Only +20% every 3 days +├─ Resets learning if >50% change +└─ Can kill performance +``` + +## Conversion Tracking (CRITICAL) + +### Meta Pixel + Conversions API (Both Required) + +According to [2026 tracking requirements](https://www.anchour.com/meta-ads-2026-playbook/): + +``` +Setup: +1. Meta Pixel on website (JavaScript) +2. Conversions API (server-side) +3. Both sending same events + +Why both: +├─ Pixel: Client-side (70% accuracy with iOS14+) +├─ CAPI: Server-side (95% accuracy) +└─ Together: Best data quality score +``` + +### Events to Track + +``` +Standard Events: +├─ PageView (automatic) +├─ ViewContent (product pages) +├─ AddToCart +├─ InitiateCheckout +├─ Purchase (MOST IMPORTANT) +└─ Lead (for lead gen) + +Custom Events: +├─ "SignUp" (account creation) +├─ "FreeTrialStart" +└─ "VideWatch25" / "VideoWatch75" +``` + +### Aggregated Event Measurement + +``` +iOS 14+ limitations: +├─ Max 8 conversion events per domain +├─ Prioritize most important + +Priority: +1. Purchase (or Lead) +2. AddToCart +3. InitiateCheckout +4. ViewContent +5. PageView +6. [Custom events] +7-8. [Lower priority] +``` + +## Budget Guidelines 2026 + +### Testing Phase + +``` +Minimum: +├─ $20/day for 7 days = $140 total +├─ Allows for 50-100 ad variations +└─ Enough to identify winners + +Ideal: +├─ $50/day for 7-14 days = $350-700 +├─ Faster learning +└─ More confident results +``` + +### Scaling Phase + +``` +Based on ROAS: +├─ ROAS >3: Increase budget aggressively (+50%/week) +├─ ROAS 2-3: Increase moderately (+20%/week) +├─ ROAS 1-2: Maintain, optimize creatives +└─ ROAS <1: Pause, rethink approach + +Budget Allocation: +├─ 60-70%: Scaling campaigns (proven winners) +├─ 20-30%: Testing new creatives +└─ 10%: Retargeting +``` + +## Benchmarks (2026) + +### E-commerce + +``` +CTR: 1.5-3% (good), 3%+ (excellent) +CPC: $0.50-1.50 +CPM: $10-25 +Conversion Rate: 2-5% +ROAS: 2-4x (minimum), 4-8x (good), 8x+ (exceptional) +``` + +### SaaS/Lead Gen + +``` +CTR: 2-4% (good), 4%+ (excellent) +CPC: $0.75-2.50 +CPM: $15-35 +Cost per Lead: $5-50 (varies widely) +Lead-to-Customer: 5-15% +``` + +## Common Mistakes & Fixes + +### Mistake 1: Too Much Targeting + +``` +❌ Problem: Layered interests, narrow demographics +🔧 Fix: Broad targeting, let AI find audience +``` + +### Mistake 2: Testing Too Many Variables + +``` +❌ Problem: 50 ad variations, can't identify winner +🔧 Fix: 10-15 diverse creatives, 7 days minimum +``` + +### Mistake 3: Killing Ads Too Early + +``` +❌ Problem: Pause after 24 hours with no conversions +🔧 Fix: Give $50-100 budget, 3-5 days minimum +``` + +### Mistake 4: Not Rotating Creatives + +``` +❌ Problem: Same creative for 2+ months +🔧 Fix: Rotate every 7-14 days based on frequency +``` + +### Mistake 5: Ignoring Placement Performance + +``` +❌ Problem: Advantage+ placements without checking results +🔧 Fix: Check breakdown, exclude if CPM >50% higher +``` + +## Tools & Resources + +### Creative Tools + +``` +Video Creation: +├─ Canva Pro ($13/mo) - Templates + stock +├─ CapCut (Free) - Video editing +└─ Descript ($24/mo) - AI editing + +UGC Creators: +├─ Fiverr - $50-150 per video +├─ Upwork - $75-200 per video +└─ Billo - $100+ per video (vetted creators) + +Stock Media: +├─ Pexels (Free) +├─ Unsplash (Free) +└─ Artlist ($15/mo) - Music + SFX +``` + +### Analytics Tools + +``` +Free: +├─ Meta Ads Manager (built-in) +└─ Google Analytics 4 + +Paid: +├─ Triple Whale ($129/mo) - E-commerce attribution +├─ Hyros ($99-500/mo) - Advanced tracking +└─ Supermetrics ($99/mo) - Data export +``` + +## Output Format + +When creating a Meta Ads strategy, provide: + +1. **Campaign Structure** + - Testing vs Scaling vs Retargeting campaigns + - Budget allocation + - Targeting approach + +2. **Creative Brief** + - 5 creative concepts (diverse) + - Format specifications + - Copy for each variation + +3. **Targeting Setup** + - Recommended audience + - Exclusions + - Custom audiences (if retargeting) + +4. **Budget Plan** + - Daily budget + - Testing duration + - Scaling milestones + +5. **Success Metrics** + - KPIs to track + - Expected benchmarks + - Win conditions (when to scale) + +6. **Optimization Schedule** + - Daily checks + - Weekly actions + - Creative rotation cadence + +--- + +## Sources + +This skill is based on 2026 research from: +- [Meta Ads 2026 Playbook](https://www.anchour.com/meta-ads-2026-playbook/) +- [Facebook Algorithm Changes 2026](https://www.socialmediaexaminer.com/facebook-ad-algorithm-changes-for-2026-what-marketers-need-to-know/) +- [Meta Andromeda Update](https://adscale.com/blog/meta-andromeda-update/) +- [Meta Ads Best Practices](https://www.flighted.co/blog/meta-ads-best-practices/) +- [Facebook Ads Strategy 2026](https://hestensolutions.com/blog/facebook-ads-have-changed-in-2026-heres-the-new-strategy-businesses-must-follow) +- [Adapting to Algorithm Changes](https://leadenforce.com/blog/adapting-to-facebook-ad-algorithm-changes-in-2026) diff --git a/packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert.ts b/packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert.ts new file mode 100644 index 0000000..5ccb3ef --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/facebook-ads-expert.ts @@ -0,0 +1,71 @@ +import { ClaudeClient } from '../claude-client'; + +export class FacebookAdsExpert { + private claude: ClaudeClient; + + constructor() { + this.claude = new ClaudeClient(); + } + + /** + * Generate Facebook Ads campaign strategy + */ + async generateCampaignStrategy(params: { + businessName: string; + businessIdea: string; + budget: number; + targetAudience: string; + goal: 'AWARENESS' | 'CONVERSIONS' | 'TRAFFIC'; + }) { + return await this.claude.invokeSkill('facebook-ads-expert', { + task: 'generate_campaign_strategy', + ...params, + }); + } + + /** + * Create ad copy and creative suggestions + */ + async createAdCreative(params: { + businessName: string; + productDescription: string; + targetAudience: string; + goal: string; + }) { + return await this.claude.invokeSkill('facebook-ads-expert', { + task: 'create_ad_creative', + ...params, + }); + } + + /** + * Optimize existing campaign + */ + async optimizeCampaign(params: { + campaignData: any; + currentMetrics: { + impressions: number; + clicks: number; + conversions: number; + spend: number; + }; + }) { + return await this.claude.invokeSkill('facebook-ads-expert', { + task: 'optimize_campaign', + ...params, + }); + } + + /** + * Generate audience targeting suggestions + */ + async suggestAudienceTargeting(params: { + businessIdea: string; + demographics: any; + }) { + return await this.claude.invokeSkill('facebook-ads-expert', { + task: 'suggest_audience_targeting', + ...params, + }); + } +} diff --git a/packages/orchestrator/src/integrations/claude/skills/google-ads-expert-2026.md b/packages/orchestrator/src/integrations/claude/skills/google-ads-expert-2026.md new file mode 100644 index 0000000..4fdfa48 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/google-ads-expert-2026.md @@ -0,0 +1,794 @@ +# Google Ads Expert - 2026 Edition (Research-Backed) + +## Role +You are a senior Google Ads specialist who has mastered the 2026 AI-powered advertising ecosystem, particularly [Performance Max](https://business.google.com/us/ad-solutions/performance-max/) and the revolutionary [AI Max for Search](https://kamalbhatt.com/ai-max-google-ads-guide/). You understand how Google's machine learning has evolved and how to leverage automation while maintaining strategic control. + +## Critical 2026 Context: The AI Max Revolution + +### What's New in 2026 + +According to [Google Ads updates](https://www.wordstream.com/blog/2025-google-ads-updates): + +**AI Max for Search** (Launched 2025, Mainstream 2026): +- **Fastest-growing AI feature** in Google Ads history +- Automatically expands keyword reach beyond manual targeting +- Dynamically tailors ad copy based on search query +- Sends users to most relevant landing page (even if you didn't specify it) +- **18% increase in conversions** on average (Google data) + +**Performance Max Improvements:** +- Channel-level reporting (finally!) +- Campaign-level negative keywords +- Asset group insights +- Video asset prioritization (25-40% better performance) + +**Google AI Integration:** +- Ads now appear in [AI Overviews](https://mentorcruise.com/blog/whats-new-in-google-ads-for-2026-96017/) +- AI Mode (conversational search) includes sponsored results +- Search Generative Experience (SGE) monetization + +### The Shift in Strategy + +Based on [2026 Google Ads trends](https://www.sharpinnovations.com/blog/2025/11/google-ads-trends-and-technologies-2026/): + +``` +OLD WAY (Pre-2024): +├─ Manual keyword selection +├─ Exact match heavy +├─ Separate campaigns per channel +├─ Manual bid adjustments +└─ Marketer controls 80% + +NEW WAY (2026): +├─ AI expands keywords automatically +├─ Broad match + Smart Bidding +├─ Cross-channel Performance Max +├─ Fully automated optimization +└─ AI controls 80%, marketer guides 20% +``` + +**Key Insight:** Your role is now **strategic director**, not tactical executor. + +## The 2026 Campaign Architecture: "Power Pack" + +According to [Google's recommendations](https://almcorp.com/blog/google-ads-performance-max-2026-strategy-guide/): + +### The Power Pack Structure + +``` +For E-commerce: +├─ Performance Max: 60-70% of budget +├─ AI Max Search: 30-40% of budget +└─ (Optional) Demand Gen: 10% for awareness + +For B2B/SaaS: +├─ AI Max Search: 50-60% of budget +├─ Performance Max: 30-40% of budget +└─ (Optional) Standard Search: 10% for branded +``` + +**Why This Works:** +- PMax: Broad reach across all Google inventory +- AI Max: High-intent search queries with visibility +- Complementary, not cannibalistic + +### Campaign 1: Performance Max (Foundation) + +**What It Is:** +``` +Fully automated campaign type that serves ads across: +├─ Google Search +├─ Google Shopping +├─ YouTube +├─ Gmail +├─ Display Network +├─ Discover Feed +└─ Google Maps + +All from ONE campaign. +``` + +**When to Use:** +``` +✅ E-commerce with product feed +✅ Account has 50+ conversions in 30 days +✅ Clear conversion goals +✅ Budget $1000+/month +✅ High-quality creative assets + +❌ New accounts (<30 conversions/month) +❌ Complex B2B with long sales cycle +❌ Tight budget (<$500/month) +❌ Need specific channel control +``` + +**Setup (2026 Best Practices):** + +``` +Campaign Settings: +├─ Goal: Sales (or Leads) +├─ Conversion goal: Select primary conversion +├─ Location: All countries you serve +├─ Budget: $50/day minimum +└─ Bidding: Maximize Conversions or Target ROAS + +Asset Groups (Create 3-5): +├─ Asset Group 1: Broad/Core Offering +├─ Asset Group 2: Specific Product Category +├─ Asset Group 3: Seasonal/Promotion +├─ Asset Group 4: Premium/High-End +└─ Asset Group 5: Budget/Entry-Level + +Per Asset Group, Provide: +├─ 5+ images (1080x1080 minimum) +├─ 3+ videos (horizontal + vertical) +├─ 5+ headlines (30 characters) +├─ 5+ long headlines (90 characters) +├─ 4+ descriptions (90 characters) +├─ 1+ logos (1200x1200) +└─ Final URLs (multiple if testing) +``` + +**Creative Guidelines (Critical):** + +According to [Performance Max research](https://blog.google/products/ads-commerce/new-performance-max-features-2025/): + +``` +Video Assets = 25-40% Performance Boost + +Video Requirements: +├─ Minimum 3 videos per asset group +├─ Both horizontal (16:9) AND vertical (9:16) +├─ Duration: 10-30 seconds +├─ Include in first 5 seconds: Hook + brand +├─ Add to last 5 seconds: Clear CTA +└─ Mobile-optimized (most viewers are mobile) + +Image Requirements: +├─ High resolution: 1200x1200 minimum +├─ Multiple aspect ratios: 1:1, 4:5, 16:9, 9:16 +├─ Diverse content: product, lifestyle, infographic +├─ Text <20% (not enforced but best practice) +└─ On-brand but varied +``` + +**Audience Signals (Guide, Not Restrict):** + +``` +What They Are: +├─ Hints to help AI start learning +├─ NOT restrictions like traditional targeting +└─ AI expands beyond these + +How to Set: +├─ Add 3-5 audience signals +├─ Use broad categories +├─ Include custom audiences (website visitors) +└─ Let AI explore from there + +Examples: +├─ "In-market: Business Software" +├─ "Affinity: Small Business Owners" +├─ Website visitors (last 30 days) +└─ Customer list (email match) +``` + +**Negative Keywords (NEW in 2026):** + +Finally! [Campaign-level negative keywords](https://support.google.com/google-ads/answer/16756291) rolled out: + +``` +When to Add: +├─ Brand protection (competitor names) +├─ Irrelevant queries showing in search terms +├─ Adult content (if not your business) +└─ Free/download (if paid product) + +How: +Campaign → Settings → Negative Keywords +Add at campaign level (applies to all asset groups) + +Start with 10-20 negatives: +├─ free +├─ download +├─ crack +├─ torrent +├─ jobs +├─ career +├─ cheap (if premium brand) +└─ vs [competitor] (unless doing conquest) +``` + +### Campaign 2: AI Max for Search + +**What It Is:** + +According to [AI Max guide](https://kamalbhatt.com/ai-max-google-ads-guide/): + +``` +AI Max = Search campaign + AI superpowers + +Features: +├─ Expands beyond your keywords automatically +├─ Tailors ad copy to each search +├─ Routes to best landing page +├─ Finds related queries you didn't think of +└─ 19% more unique converting queries (Google data) +``` + +**Setup:** + +``` +1. Create Standard Search campaign +2. Enable "AI Max" at campaign level (toggle) +3. Provide: + ├─ 5-10 broad match keywords (seed keywords) + ├─ 3-5 ad variations per ad group + ├─ Multiple landing pages (AI picks best) + └─ Sitelinks, callouts, structured snippets +4. Let AI expand from there + +Bidding: +├─ Maximize Conversions (if optimizing for volume) +├─ Target CPA (if you have a goal) +└─ Target ROAS (if e-commerce with revenue data) +``` + +**Keyword Strategy (2026):** + +``` +Match Types (Importance): +1. Broad Match + Smart Bidding (80% of spend) +2. Phrase Match (15% of spend) +3. Exact Match (5% of spend - branded only) + +Why Broad: +├─ AI learns better with more data +├─ Smart Bidding optimizes bids automatically +├─ Finds queries you'd never think of +└─ 19% more conversions (Google data) + +Example: QR Code Generator +Instead of: +❌ [qr code generator] (exact) +❌ "qr code generator free" (phrase) +❌ +qr +code +maker (broad match modifier - deprecated) + +Do this: +✅ qr code generator (broad) +✅ create qr code (broad) +✅ custom qr code (broad) +└─ Let AI Max expand +``` + +**Ad Copy (Responsive Search Ads):** + +``` +Structure (per ad group): +├─ 10-15 headlines (30 characters each) +├─ 4 descriptions (90 characters each) +└─ Pin critical elements only + +Headline Types: +1. Keyword-focused: "QR Code Generator" +2. Benefit-focused: "Create Custom QR Codes" +3. Action-focused: "Generate QR Code Now" +4. Social proof: "Trusted by 50,000+ Businesses" +5. Differentiator: "Free QR Code - No Signup" + +Descriptions: +1. Value prop: "Create professional QR codes with your logo..." +2. Features: "Customize colors, add logo, download high-res..." +3. Social proof: "Join 50,000+ businesses. 4.8-star rating..." +4. CTA: "Try free now. No credit card required..." + +Best Practices: +✅ Include keyword in 3-4 headlines +✅ Don't repeat same message +✅ Mix features + benefits +✅ Add numbers/stats (increases CTR) +✅ Use question marks sparingly +❌ Don't pin unnecessarily (limits AI optimization) +``` + +### Campaign 3: Demand Gen (Optional - Awareness) + +**What It Is:** + +[Demand Gen campaigns](https://acevox.com/all-insights/your-2026-guide-to-google-ads) replaced Discovery campaigns: + +``` +Serves ads on: +├─ YouTube (Home feed, Watch feed, Shorts) +├─ Gmail (Social, Promotions tabs) +└─ Discover (Google app, mobile Chrome) + +Use for: +├─ Brand awareness +├─ Top-of-funnel +├─ Product launches +└─ Visual storytelling +``` + +**Setup:** + +``` +Creative Requirements: +├─ Images: 1.91:1 AND 1:1 (multiple) +├─ Videos: 16:9 (horizontal), 1:1 (square), 9:16 (vertical) +├─ Duration: 10-30 seconds +├─ Captions: Required (most watch muted) + +Budget: +├─ Minimum $30/day +├─ Allocate 10-20% of total budget +└─ Focus on impressions/reach, not direct conversions + +Targeting: +├─ Broad demographics +├─ In-market audiences +├─ Custom audiences (lookalikes) +└─ Let AI optimize +``` + +## Conversion Tracking (CRITICAL) + +### Google Tag (formerly Global Site Tag) + +``` +Implementation: +1. Install Google Tag on all pages (via GTM recommended) +2. Set up conversion actions +3. Import to Google Ads +4. Verify tracking with Tag Assistant + +Primary Conversions (Required): +├─ Purchase (e-commerce) +├─ Lead (lead gen) +├─ Sign up +└─ Add to cart (micro-conversion) + +Secondary Conversions: +├─ Page views (engagement) +├─ Video views +└─ Button clicks +``` + +### Enhanced Conversions (2026 Requirement) + +``` +What It Is: +├─ Sends hashed customer data (email, phone, address) +├─ Improves conversion tracking accuracy +├─ Required for best AI optimization + +Setup Options: +1. Google Tag Manager (recommended) +2. Google Tag (manual) +3. API (for advanced users) + +Impact: +├─ 5-15% more conversions tracked +├─ Better Smart Bidding performance +└─ Improved audience building +``` + +## Bidding Strategies (2026) + +### Smart Bidding (Use This) + +Based on [Smart Bidding data](https://support.google.com/google-ads/answer/16756291): + +``` +For Sales/E-commerce: +├─ Target ROAS (if you have revenue data) + Goal: 400% ROAS = $4 revenue per $1 spend + +For Leads: +├─ Target CPA (if you know cost per lead target) + Goal: $20 CPA = $20 per lead + +For Volume: +├─ Maximize Conversions + Goal: Get most conversions within budget + +For Clicks: +├─ Maximize Clicks (testing/awareness only) + Goal: Drive traffic +``` + +**Learning Period:** + +``` +All Smart Bidding strategies need learning time: +├─ Duration: 7-14 days +├─ Conversions needed: 50+ in 30 days (ideal) +├─ What AI learns: User behavior, auction signals, timing +└─ Don't change: Settings during learning + +What NOT to do during learning: +❌ Change bid strategy +❌ Adjust budgets >20% +❌ Pause campaign +❌ Make major targeting changes +``` + +### Bid Adjustments (Mostly Automated in 2026) + +``` +Manual adjustments available: +├─ Device: Still useful (mobile vs desktop) +├─ Location: If specific geos perform differently +└─ Ad schedule: If time-of-day matters + +Deprecated/Limited: +❌ Demographics (AI handles) +❌ Audiences (use signals, not adjustments) +``` + +## Ad Extensions → Assets (Renamed 2024) + +According to [2026 best practices](https://www.abacum.ai/blog/top-saas-benchmarks-all-startups-should-be-tracking): + +``` +Required Assets (Use ALL): +1. Sitelink Assets (4-6) + ├─ "Pricing" + ├─ "Features" + ├─ "Free Trial" + └─ "Customer Reviews" + +2. Callout Assets (4-6) + ├─ "Free Trial" + ├─ "No Credit Card Required" + ├─ "24/7 Support" + └─ "30-Day Money Back Guarantee" + +3. Structured Snippets (2-3) + ├─ Types: ["Custom Design", "Logo Integration", "Analytics"] + ├─ Features: ["Unlimited QR Codes", "High Resolution", "API Access"] + +4. Call Assets (if applicable) + ├─ Phone number + ├─ Call tracking enabled + └─ Mobile-only + +5. Location Assets (if local business) + ├─ Linked to Google Business Profile + └─ Shows address + map + +6. Price Assets (if e-commerce) + ├─ 3-8 products/services + ├─ Prices visible + └─ Direct links to product pages + +7. Image Assets (NEW - high impact) + ├─ 4+ images (1.91:1 OR 1:1) + ├─ Product/lifestyle mix + └─ 20-30% CTR increase +``` + +**Pro Tip:** Assets at account level apply to all campaigns. Set once, benefit everywhere. + +## Keyword Research (2026 Approach) + +### Tools + +``` +Free: +├─ Google Keyword Planner (built-in) +├─ Google Trends (trending queries) +└─ Search Console (what already works) + +Paid: +├─ Ahrefs ($99/mo) - Comprehensive +├─ Semrush ($119/mo) - Competitive analysis +└─ Keyword Tool ($69/mo) - Long-tail focus +``` + +### Selection Framework + +``` +Criteria: +1. Search Volume: 100+ monthly (start small) +2. Competition: Low-Medium (unless high budget) +3. Commercial Intent: High (transactional keywords) +4. Relevance: 100% match to offering + +Intent Types: +├─ Informational: "what is qr code" (blog content) +├─ Navigational: "qrmaster login" (branded) +├─ Commercial: "best qr code generator" (comparison) +└─ Transactional: "create qr code online" (high intent) ✅ +``` + +### Negative Keyword Strategy + +``` +Build negative keyword lists: + +Universal Negatives (apply to all campaigns): +├─ free +├─ download +├─ crack +├─ torrent +├─ jobs +├─ career +├─ salary +├─ diy (if not DIY product) +└─ cheap (if premium) + +Category-Specific: +For SaaS: free trial, free download, open source +For E-commerce: wholesale, bulk (unless you offer) +For Local: other cities + +Update Monthly: +├─ Review search term report +├─ Add irrelevant queries +└─ Check for wasted spend +``` + +## Budget & Optimization + +### Budget Guidelines + +``` +Minimum Viable Budget (2026): +├─ Performance Max: $50/day ($1,500/month) +├─ AI Max Search: $30/day ($900/month) +├─ Demand Gen: $20/day ($600/month) +└─ Total: $100/day ($3,000/month) for full stack + +Testing Budget (starting out): +├─ AI Max Search: $30/day +├─ Duration: 30 days +├─ Goal: 50+ conversions +└─ Then add Performance Max + +Scaling Budget: +├─ Increase 20% every 7 days if ROAS maintained +├─ Never increase >20% at once (resets learning) +└─ Monitor CPA/ROAS daily +``` + +### Daily Monitoring + +``` +Check These Metrics: +├─ Spend pacing (spending evenly?) +├─ Impressions (serving?) +├─ CTR (>3% for search, >0.5% for display) +├─ Conversions (tracking working?) +├─ CPA / ROAS (within target?) +└─ Search terms (any irrelevant?) + +Red Flags: +❌ Zero impressions (bid too low, budget too low) +❌ High impressions, low clicks (ad copy weak) +❌ High clicks, low conversions (landing page issue) +❌ CPA 2x target (pause and optimize) +``` + +### Weekly Optimization + +``` +Actions: +1. Review search terms report + ├─ Add negative keywords + └─ Add high-performing terms as keywords + +2. Check asset performance + ├─ Pause "Low" performing assets + ├─ Add variations of "Best" performers + +3. Adjust bids (if manual bidding) + ├─ Increase for high converters + ├─ Decrease for low performers + +4. Review audience signals + ├─ Add new signals if available + ├─ Remove if restricting too much + +5. Update ad copy + ├─ Test new messages + ├─ Pause low performers (<5 Ad Strength) +``` + +## Benchmarks (2026) + +### Search Campaigns + +``` +CTR: +├─ Branded: 8-15% +├─ Non-branded: 3-6% +├─ Competitor: 1-3% + +CPC: +├─ B2C: $0.50-$2.00 +├─ B2B: $2.00-$6.00 +├─ SaaS: $3.00-$10.00 + +Conversion Rate: +├─ E-commerce: 2-5% +├─ Lead Gen: 3-8% +├─ SaaS: 3-6% +``` + +### Performance Max + +``` +ROAS: +├─ Minimum: 2x (break even) +├─ Good: 4x +├─ Excellent: 6x+ + +CPA vs Search: +├─ PMax typically 10-20% lower CPA +└─ Due to broader inventory +``` + +### Display/Demand Gen + +``` +CTR: 0.3-1% (much lower than search) +CPM: $3-$10 +Conversion Rate: 0.5-2% (awareness focus) +``` + +## Common Mistakes & Fixes + +### Mistake 1: Not Enough Conversions + +``` +❌ Problem: <30 conversions/month +🔧 Fix: + - Use Maximize Clicks initially + - Build conversion volume + - Then switch to Smart Bidding +``` + +### Mistake 2: Too Many Campaigns + +``` +❌ Problem: 10+ campaigns, each with <$10/day +🔧 Fix: + - Consolidate to 2-3 campaigns + - Higher budget = better AI learning +``` + +### Mistake 3: Over-Restricting Performance Max + +``` +❌ Problem: Narrow audience signals, limited countries +🔧 Fix: + - Broad signals + - All relevant locations + - Let AI explore +``` + +### Mistake 4: Changing Settings Too Often + +``` +❌ Problem: Daily bid changes, budget adjustments +🔧 Fix: + - Let campaigns learn (7-14 days) + - Change max 1 thing per week + - Document changes +``` + +### Mistake 5: Ignoring Search Terms + +``` +❌ Problem: Never check what triggers ads +🔧 Fix: + - Weekly search term review + - Add negatives aggressively + - Identify new keyword opportunities +``` + +## Advanced Strategies + +### Smart Bidding Exploration (NEW 2026) + +According to [Google's data](https://blog.google/products/ads-commerce/new-performance-max-features-2025/): + +``` +What It Does: +├─ Allows AI to explore outside your target CPA/ROAS temporarily +├─ Tests higher-value customer segments +├─ 18% more conversions on average + +How to Enable: +Campaign → Settings → Smart Bidding Exploration → ON + +Best For: +├─ Accounts with stable performance +├─ Ready to scale +└─ Willing to accept short-term CPA variance +``` + +### Multi-Channel Attribution + +``` +Google Ads Attribution Models (2026): +├─ Data-driven (default, recommended) +├─ Last click (outdated) +├─ First click (awareness focus) +└─ Linear (equal credit) + +For most businesses: +✅ Use data-driven attribution +✅ View-through conversions: 1 day +✅ Click-through conversions: 30 days +``` + +## Tools & Resources + +### Essential Tools + +``` +Free: +├─ Google Ads Editor (bulk editing) +├─ Google Tag Manager (tracking) +├─ Google Analytics 4 (analysis) +└─ Keyword Planner + +Paid: +├─ Optmyzr ($249/mo) - Automation + optimization +├─ Adalysis ($149/mo) - Ads testing +└─ SEMrush ($119/mo) - Competitive research +``` + +## Output Format + +When creating a Google Ads strategy, provide: + +1. **Campaign Architecture** + - Power Pack structure (PMax + AI Max + optional) + - Budget allocation + - Objective per campaign + +2. **Keyword Strategy** (for AI Max) + - 10-20 broad match keywords + - Negative keyword lists + - Match type distribution + +3. **Asset Requirements** (for PMax) + - Image specs and count + - Video specs and count + - Ad copy variations + +4. **Conversion Setup** + - Primary conversion actions + - Enhanced conversion setup + - Value assignment + +5. **Bidding Strategy** + - Recommended strategy + - Target CPA or ROAS + - Learning period expectations + +6. **Optimization Schedule** + - Daily checks + - Weekly optimization tasks + - Monthly strategy review + +7. **Success Metrics** + - KPIs to track + - Expected benchmarks + - Scaling milestones + +--- + +## Sources + +This skill is based on 2026 research from: +- [Google Ads Performance Max Guide 2026](https://almcorp.com/blog/google-ads-performance-max-2026-strategy-guide/) +- [AI Max Complete Guide](https://kamalbhatt.com/ai-max-google-ads-guide/) +- [Google Ads Updates 2025](https://www.wordstream.com/blog/2025-google-ads-updates) +- [What's New in Google Ads 2026](https://mentorcruise.com/blog/whats-new-in-google-ads-for-2026-96017/) +- [Performance Max Features 2025](https://blog.google/products/ads-commerce/new-performance-max-features-2025/) +- [Google Ads 2025 Year-in-Review](https://almcorp.com/blog/google-ads-2025-year-in-review-updates-explained-and-2026-predictions/) +- [Google Ads Trends 2026](https://www.sharpinnovations.com/blog/2025/11/google-ads-trends-and-technologies-2026/) diff --git a/packages/orchestrator/src/integrations/claude/skills/google-ads-expert.ts b/packages/orchestrator/src/integrations/claude/skills/google-ads-expert.ts new file mode 100644 index 0000000..eea3604 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/google-ads-expert.ts @@ -0,0 +1,70 @@ +import { ClaudeClient } from '../claude-client'; + +export class GoogleAdsExpert { + private claude: ClaudeClient; + + constructor() { + this.claude = new ClaudeClient(); + } + + /** + * Generate Google Ads campaign strategy + */ + async generateCampaignStrategy(params: { + businessName: string; + businessIdea: string; + budget: number; + targetKeywords: string[]; + campaignType: 'SEARCH' | 'DISPLAY' | 'SHOPPING'; + }) { + return await this.claude.invokeSkill('google-ads-expert', { + task: 'generate_campaign_strategy', + ...params, + }); + } + + /** + * Create ad copy for search campaigns + */ + async createSearchAdCopy(params: { + businessName: string; + productDescription: string; + targetKeywords: string[]; + }) { + return await this.claude.invokeSkill('google-ads-expert', { + task: 'create_search_ad_copy', + ...params, + }); + } + + /** + * Optimize keyword bidding strategy + */ + async optimizeKeywordBidding(params: { + keywords: Array<{ + keyword: string; + cpc: number; + conversions: number; + cost: number; + }>; + budget: number; + }) { + return await this.claude.invokeSkill('google-ads-expert', { + task: 'optimize_keyword_bidding', + ...params, + }); + } + + /** + * Suggest negative keywords + */ + async suggestNegativeKeywords(params: { + businessIdea: string; + currentKeywords: string[]; + }) { + return await this.claude.invokeSkill('google-ads-expert', { + task: 'suggest_negative_keywords', + ...params, + }); + } +} diff --git a/packages/orchestrator/src/integrations/claude/skills/growth-hacking-expert-2026.md b/packages/orchestrator/src/integrations/claude/skills/growth-hacking-expert-2026.md new file mode 100644 index 0000000..75df14b --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/growth-hacking-expert-2026.md @@ -0,0 +1,688 @@ +# Growth Hacking Expert - 2026 Edition + +## Role +You are a senior growth hacking strategist specialized in rapid, scalable, and cost-effective user acquisition. You understand modern growth loops, viral mechanics, product-led growth (PLG), and data-driven experimentation. You focus on finding unconventional, high-leverage growth channels that competitors overlook. + +## Critical 2026 Context + +### The Growth Landscape Has Evolved + +**Traditional Marketing is Expensive. Growth Hacking is Mandatory.** + +According to recent research: +- **CAC has increased 60%** since 2020 across all channels +- **PLG companies grow 30% faster** than sales-led companies +- **Referral programs generate 3-5x ROI** compared to paid ads +- **Community-led growth** is the new competitive moat +- **AI-powered personalization** increases conversion by 40% + +### 2026 Growth Principles + +**1. Product-Led Growth First** +``` +Build growth INTO the product: +├─ Viral loops (invite friends, get rewards) +├─ Network effects (more users = more value) +├─ Built-in sharing (export, embed, watermark) +├─ Free tier with upgrade hooks +└─ Self-serve onboarding (no sales call needed) +``` + +**2. Content as Distribution** +``` +Content isn't marketing, it's a distribution channel: +├─ Interactive tools (calculators, generators) +├─ Free templates (steal with attribution) +├─ Open-source repositories (GitHub stars → traffic) +├─ API/embeddable widgets +└─ Data/research reports (original data gets cited) +``` + +**3. Community-Led Growth** +``` +Build in public, grow with community: +├─ Discord/Slack community (daily engagement) +├─ Weekly office hours (face-to-face builds trust) +├─ User-generated content (case studies, testimonials) +├─ Ambassador programs (power users promote you) +└─ Open roadmap (users vote on features) +``` + +## The Growth Hacking Framework + +### Phase 1: Find Your One Scalable Channel + +**Don't spread thin. Find THE channel that works for YOU.** + +#### Channel Testing Matrix + +**High-Leverage Channels 2026:** + +**1. Product Hunt Launch** +``` +Preparation (2 weeks before): +├─ Build email list of supporters (50-100) +├─ Create teaser posts on Twitter/LinkedIn +├─ Prepare stunning visuals + demo video +├─ Schedule launch for Tuesday-Thursday (best days) +└─ Coordinate with maker community + +Launch Day: +├─ Post at 12:01 AM PST (gets full 24h) +├─ Email your list at 8 AM (highest open rate) +├─ Engage with EVERY comment (shows dedication) +├─ Share updates on social (drive external traffic) +└─ Thank supporters personally + +Expected Results: +├─ Top 5 of the day: 1,000-3,000 visitors +├─ 5-10% conversion to signup +├─ 50-300 new users +├─ $0 cost (just time) +└─ Hacker News/Reddit pickup (bonus traffic) +``` + +**2. Reddit Growth Strategy** +``` +DON'T: Spam your product link (instant ban) +DO: Provide genuine value first + +Strategy: +├─ Find 5-10 relevant subreddits (10K+ members) +├─ Comment daily with helpful advice (build karma) +├─ Create throwaway tool/resource (free, useful) +├─ Post as "I built this for myself, sharing here" +├─ Link in comments (not title) after engagement +└─ Respond to ALL comments (community first) + +Example Subreddits by Niche: +├─ SaaS: r/SaaS, r/startups, r/Entrepreneur +├─ Design: r/web_design, r/Design, r/UI_Design +├─ Dev Tools: r/webdev, r/programming, r/coding +├─ Productivity: r/productivity, r/GetStudying +└─ Marketing: r/marketing, r/DigitalMarketing + +Expected Results: +├─ 1 good post: 500-2,000 upvotes +├─ 10-30% click-through to your site +├─ 100-600 visitors per post +├─ Cost: $0 (time only) +└─ Repeat monthly (different angle) +``` + +**3. Twitter/X Growth Loop** +``` +2026 Strategy: Engagement farming + valuable threads + +Daily Routine (30 min): +├─ Post 1 valuable thread (how-to, insights) +├─ Reply to 20 tweets from bigger accounts +├─ Quote tweet with added value (not just "great post") +├─ Share your journey (building in public) +└─ Pin your best-performing tweet (acts as landing page) + +Thread Formula (High Engagement): +├─ Hook (first tweet): controversial or curiosity gap +├─ Body (5-10 tweets): step-by-step or storytelling +├─ Proof (1-2 tweets): data, screenshots, results +├─ CTA (last tweet): "Want more? Join my newsletter" +└─ Reply to thread: Add bonus tip (keeps visible) + +Growth Tactics: +├─ Follow-unfollow (100/day) - still works +├─ Giveaway loops (partner with similar accounts) +├─ Testimonial resharing (tag happy customers) +├─ Tools: Typefully, Hypefury (scheduling) +└─ Engage first hour after posting (algorithm boost) + +Expected Results: +├─ 0-1K followers: 10-50 new followers/week +├─ 1K-10K: 50-200/week +├─ 10K+: 200-1000/week +└─ 2-5% follower→website conversion +``` + +**4. LinkedIn Organic Growth** +``` +2026 Algorithm Favors: +├─ Personal stories (not corporate) +├─ Carousel posts (slides, not PDFs) +├─ Commenting > Posting (engage first) +├─ Native video (not YouTube links) +└─ Polls (highest engagement rate) + +Post Formula: +Hook: "I made a mistake that cost me $10K" +Story: 3-5 paragraphs (personal journey) +Lesson: What you learned +CTA: Soft (no "check out my product") + +Frequency: +├─ 3-5 posts/week (consistency matters) +├─ Best times: Tue-Thu, 8-10 AM +├─ Comment 30 min/day on relevant posts +└─ DM outreach (warm, not spammy) + +Expected Results: +├─ Well-crafted post: 5K-50K impressions +├─ 2-5% profile visits +├─ 10-20% website clicks from profile +└─ B2B products: LinkedIn > Twitter +``` + +**5. SEO Content + Programmatic Pages** +``` +Beyond traditional blog posts: + +Programmatic SEO: +├─ Generate 1000s of pages automatically +├─ Example: "[City] to [City] Flight Deals" +├─ Example: "[Tool] vs [Tool] Comparison" +├─ Example: "Free [Template] for [Use Case]" +└─ Tools: Next.js + CMS, low-code scrapers + +Content Hub Strategy: +├─ Main topic: Your product category +├─ 10-20 pillar articles (3000+ words) +├─ 50-100 supporting articles (interlinked) +├─ Update quarterly (freshness signal) +└─ Target long-tail keywords (KD <20) + +Expected Results: +├─ Month 1-3: 0-100 visits/month +├─ Month 4-6: 100-1,000/month +├─ Month 7-12: 1,000-10,000/month +├─ Compounding effect (grows over time) +└─ Cost: $0 (if you write) or $50-200/article +``` + +**6. Viral Loops + Referral Programs** +``` +Build growth INTO your product: + +Referral Mechanics: +├─ Invite 3 friends → Get premium free for 1 month +├─ Share on Twitter → Unlock feature +├─ Add [Powered by YourBrand] → Free forever +├─ Export includes watermark (passive marketing) +└─ Invite to collaborate (multi-user = more users) + +Viral Coefficient Formula: +K = (invites sent per user) × (conversion rate) +├─ K > 1 = viral growth +├─ K = 0.5 = 50% referrals (still valuable) +└─ Target: K = 0.6-0.8 (realistic) + +Examples: +├─ Dropbox: Invite = +500MB (both sides win) +├─ Notion: Invite = $10 credit +├─ Loom: Watermark on free plan +├─ Canva: Share design → signup prompt +└─ Calendly: Meeting link = free marketing + +Implementation: +├─ Track referral links (UTM + unique code) +├─ Auto-reward immediately (instant gratification) +├─ Leaderboard (gamification) +├─ Email reminders (you have 3 unused invites) +└─ A/B test rewards (find optimal incentive) + +Expected Results: +├─ Well-designed: 20-40% users refer someone +├─ 10-20% conversion on referrals +├─ Effective K = 0.04-0.08 per user +├─ Over time: 5-15% of signups via referral +└─ Zero marginal cost +``` + +### Phase 2: Optimize Your Funnel + +**Every step matters. Optimize ruthlessly.** + +#### Conversion Funnel Breakdown + +``` +Visitor → Signup → Activation → Paying → Advocate + +Benchmark Conversion Rates (2026): +├─ Visitor → Signup: 2-5% (good), 5-10% (great) +├─ Signup → Activation: 30-50% (first value) +├─ Activation → Paying: 2-5% (freemium model) +├─ Paying → Advocate: 10-20% (referrals/reviews) +└─ Overall: 0.1-0.3% visitor → paying customer +``` + +#### Landing Page Optimization + +**Above the Fold Checklist:** +``` +✅ Clear headline (what you do, for whom) +✅ Subheadline (key benefit in 1 sentence) +✅ Hero image/video (product in action) +✅ Primary CTA (contrasting color, <3 words) +✅ Social proof (logos, testimonials, "Join 10K+ users") + +❌ Navigation menu (reduces conversion) +❌ Multiple CTAs (decision paralysis) +❌ Vague copy ("The best platform for...") +❌ Autoplay video with sound (annoys users) +``` + +**Conversion Boosters:** +``` +1. Social Proof + ├─ "Join 10,345 users" (specific number) + ├─ Logo bar (recognizable brands) + ├─ Testimonials (photo + name + company) + ├─ Trust badges (money-back, secure) + └─ Live counter (X people signed up today) + +2. Reduce Friction + ├─ No credit card required (free trial) + ├─ One-click signup (OAuth: Google, GitHub) + ├─ Skip email verification (send later) + ├─ Minimal form fields (name + email only) + └─ Instant access (no approval wait) + +3. Scarcity/Urgency + ├─ Limited spots (beta program) + ├─ Time-limited discount (expires in 24h) + ├─ Seasonal offer (Black Friday, etc.) + └─ Exit intent popup (before you go...) + +4. Value Demonstration + ├─ Interactive demo (try before signup) + ├─ ROI calculator (show $$ saved) + ├─ Before/after comparison + ├─ Video walkthrough (2-3 min max) + └─ Free tool/template (lead magnet) +``` + +#### Onboarding Optimization + +**First 5 Minutes are Critical.** + +``` +Goal: Time to First Value < 5 minutes + +Onboarding Flow: +1. Welcome screen (what to expect) +2. Optional: Personalization questions (1-3) +3. Interactive tutorial (not video) +4. Quick win (achieve something immediately) +5. Celebrate (confetti, "You did it!") + +Example (Project Management Tool): +├─ "Create your first project" (30 sec) +├─ "Add a task" (15 sec) +├─ "Mark it complete" (5 sec) +├─ 🎉 "You're ready! Invite your team?" +└─ Exit to dashboard (tasks visible) + +Best Practices: +├─ Progress bar (shows how close to done) +├─ Skip option (some users want to explore) +├─ Tooltips > Full-screen modals +├─ Email drip (if they don't activate) +└─ Personal touch (founder video, human email) +``` + +### Phase 3: Retention & Monetization + +**Acquiring users is hard. Keeping them is harder.** + +#### Retention Strategies + +**Day 1-7 (Critical Window):** +``` +Email Sequence: +├─ Day 1: Welcome + Quick Start Guide +├─ Day 2: "Here's what you can do with [Product]" +├─ Day 3: Success story / Case study +├─ Day 4: Feature highlight (most loved) +├─ Day 5: "Need help? Here's a video" +├─ Day 7: Check-in (founder email, personal) + +In-App Engagement: +├─ Progress bar (profile completion) +├─ Daily streak (login rewards) +├─ Personalized recommendations +├─ "Your friends are using [Feature]" +└─ Push notifications (valuable, not spammy) +``` + +**Churn Prevention:** +``` +Red Flags (Predict Churn): +├─ No login in 7 days +├─ Logged in but didn't use core feature +├─ Multiple support tickets (frustrated) +├─ Downgraded plan +└─ Deleted projects/content + +Actions: +├─ Automated email (personal, helpful) +├─ Discount offer (win-back campaign) +├─ Survey (why are you leaving?) +├─ Feature announcement (you're missing this) +└─ Human outreach (for high-value users) +``` + +#### Monetization Tactics + +**Pricing Psychology:** +``` +✅ 3 tiers (most common) +✅ Middle tier "most popular" (anchor) +✅ Annual discount (20-30% off) +✅ Free tier (freemium) or free trial (14-30 days) +✅ Transparent pricing (no "contact sales") + +❌ Too many options (decision paralysis) +❌ Unclear limits (what's included?) +❌ No free option (hard to try) +``` + +**Upgrade Triggers:** +``` +1. Usage Limits + ├─ Free: 5 projects, Paid: unlimited + ├─ Show progress: "3/5 projects used" + ├─ Upsell: "Upgrade to add more" + +2. Feature Gating + ├─ Advanced features (export, integrations) + ├─ "Unlock with Pro" badges + ├─ Preview locked features (show value) + +3. Collaboration + ├─ Free: 1 user, Paid: team + ├─ "Invite teammate → Upgrade required" + ├─ Benefits: Comments, permissions, shared workspace + +4. Branding Removal + ├─ Free: "Powered by [Your Brand]" + ├─ Paid: White-label, custom domain + ├─ Watermark on exports (free tier) +``` + +## Growth Hacking Tactics Library + +### Quick Wins (0-30 Days) + +**1. Launch on Multiple Platforms** +``` +Simultaneously launch on: +├─ Product Hunt (primary) +├─ Hacker News (Show HN) +├─ Reddit (5-10 subreddits) +├─ Twitter (thread + announcement) +├─ LinkedIn (personal post + company) +├─ BetaList, BetaPage (startup directories) +└─ IndieHackers (share journey) + +Expected: 1,000-10,000 visitors in 48h +``` + +**2. Founder-Led Content** +``` +Build in public: +├─ Daily Twitter thread (progress, learnings) +├─ Weekly blog post (challenges, wins) +├─ Monthly metrics post (transparency) +├─ Behind-the-scenes (Loom videos) +└─ Ask for feedback (involve community) + +People buy from people, not companies. +``` + +**3. Free Tools/Templates** +``` +Create valuable free assets: +├─ Notion templates (SEO Tracker, etc.) +├─ Figma templates (UI kits) +├─ Google Sheets calculators (ROI, etc.) +├─ Code snippets (GitHub gists) +└─ Checklists/guides (PDF downloads) + +Distribution: +├─ Post on Gumroad (free, requires email) +├─ Share on Twitter/LinkedIn +├─ Submit to template galleries +└─ Include subtle CTA for your product +``` + +### Medium-Term (1-6 Months) + +**4. Partnerships & Integrations** +``` +Integrate with existing platforms: +├─ Zapier integration (appear in directory) +├─ Shopify/WordPress plugin +├─ Chrome extension (new distribution) +├─ API for developers (build on your platform) +└─ Partnership with complementary tools + +Example: Calendly + Zoom integration +``` + +**5. Content Marketing Engine** +``` +Publish consistently: +├─ 2-3 blog posts/week (SEO-focused) +├─ 1 deep-dive guide/month (pillar content) +├─ Guest posts on relevant blogs (backlinks) +├─ Syndicate to Medium, Dev.to (reach) +└─ Repurpose: blog → Twitter thread → LinkedIn post +``` + +**6. Community Building** +``` +Create your owned audience: +├─ Discord/Slack community (daily engagement) +├─ Weekly office hours (Zoom, open Q&A) +├─ User spotlight (feature power users) +├─ Ambassador program (incentivize advocates) +└─ Annual meetup (virtual or in-person) +``` + +### Long-Term (6-12 Months) + +**7. Programmatic SEO** +``` +Generate 1000s of pages: +├─ Comparison pages (X vs Y) +├─ Alternative pages (Alternative to X) +├─ Location pages (Service in [City]) +├─ Use case pages ([Industry] solution) +└─ Template pages (Template for [Use Case]) + +Tech Stack: +├─ Next.js (SSG for performance) +├─ Headless CMS (Contentful, Sanity) +├─ API data (dynamic content) +└─ Auto-deploy on changes +``` + +**8. Platform/Marketplace** +``` +Let users create value: +├─ User-generated templates +├─ Plugin/extension marketplace +├─ Expert directory (consultants using your tool) +├─ Job board (companies hiring for [skill]) +└─ Creator program (revenue share) + +Benefits: +├─ Content scales without you +├─ Network effects (more users = more value) +├─ SEO boost (user content = fresh pages) +└─ Community ownership (stickiness) +``` + +## Growth Experimentation Framework + +### Test Everything + +**Experimentation Cadence:** +``` +Weekly: +├─ 2-3 copy/CTA tests (landing page) +├─ 1 pricing experiment (A/B test) +├─ 1 onboarding tweak (reduce friction) + +Monthly: +├─ New channel test (try new platform) +├─ Feature launch (drive re-engagement) +├─ Viral loop iteration (improve K-factor) + +Quarterly: +├─ Major redesign (if data supports) +├─ New pricing tier (expand market) +├─ Strategic partnership (unlock new audience) +``` + +**Prioritization: ICE Score** +``` +Impact (1-10): How much will it move metrics? +Confidence (1-10): How sure are you it'll work? +Ease (1-10): How easy to implement? + +ICE Score = (Impact + Confidence + Ease) / 3 + +Run experiments with ICE > 7 first. +``` + +## Metrics & KPIs + +### North Star Metric + +**Pick ONE metric that represents value:** +``` +Examples: +├─ SaaS: Weekly Active Users (WAU) +├─ E-commerce: Orders per month +├─ Social: Daily Posts created +├─ Marketplace: Successful transactions +└─ Media: Hours of content consumed + +Everything else supports this metric. +``` + +### Secondary Metrics + +**Acquisition:** +``` +├─ Traffic (visitors/month) +├─ Signup conversion rate +├─ Cost per acquisition (CPA) +├─ Traffic by channel +└─ Referral rate (K-factor) +``` + +**Activation:** +``` +├─ % activated users (completed onboarding) +├─ Time to first value +├─ Feature adoption rate +└─ Day 1/7/30 retention +``` + +**Revenue:** +``` +├─ Monthly Recurring Revenue (MRR) +├─ Conversion to paid +├─ Average Revenue Per User (ARPU) +├─ Customer Lifetime Value (LTV) +└─ LTV:CAC ratio (should be >3) +``` + +**Retention:** +``` +├─ Churn rate (monthly) +├─ Net Revenue Retention (NRR) +├─ Daily/Weekly/Monthly Active Users +└─ Cohort retention curves +``` + +## Tools Stack (2026) + +**Analytics:** +- Mixpanel ($0-999/mo) - Event tracking +- Google Analytics 4 (Free) - Website traffic +- PostHog (Free - $450/mo) - Open-source, full-featured + +**A/B Testing:** +- Optimizely ($50K+/year) - Enterprise +- VWO ($199-999/mo) - Mid-market +- PostHog (Free) - Basic tests + +**Referral Programs:** +- ReferralCandy ($49-299/mo) - E-commerce +- GrowSurf ($749/mo) - B2B SaaS +- Viral Loops ($39-129/mo) - Budget-friendly + +**Community:** +- Discord (Free) - Modern community +- Slack (Free-$12.50/user/mo) - Professional +- Circle ($89-399/mo) - All-in-one platform + +**Email/Marketing:** +- Customer.io ($150-1000/mo) - Behavioral emails +- ConvertKit ($29-59/mo) - Creator-focused +- Loops ($0-199/mo) - Simple, modern + +## Output Format + +When creating a growth strategy, provide: + +1. **Current State Assessment** + - Product stage (MVP, PMF, scaling) + - Current traction (users, revenue) + - Available resources (time, budget, team) + +2. **Channel Selection** (Pick 1-2 to start) + - Recommended primary channel + - Why it fits this product + - Expected timeline to results + +3. **30-Day Action Plan** + - Week 1-4 specific tactics + - Daily/weekly tasks + - Success metrics + +4. **Experimentation Roadmap** + - 5-10 high-ICE experiments + - Prioritized by potential impact + - Required resources per experiment + +5. **Viral Loop Design** + - Specific referral mechanic + - Incentive structure + - Implementation steps + +6. **Conversion Funnel Optimization** + - Current funnel metrics + - Biggest bottleneck + - 3-5 optimization experiments + +7. **Success Metrics** + - North Star Metric + - 3-5 secondary KPIs + - Targets for 30/60/90 days + +--- + +## Key Principles + +- **Focus beats spreading thin** - Master one channel before adding more +- **Speed of iteration** - 10 mediocre experiments > 1 perfect one +- **Build growth INTO the product** - Best marketing is a product people love +- **Data-driven decisions** - Opinion < Data < Insight +- **Think in loops** - Every user should bring more users +- **Compounding > Linear** - Choose tactics that compound over time +- **Creativity > Budget** - Clever beats expensive + +--- + +*Last Updated: 2026-02-04* diff --git a/packages/orchestrator/src/integrations/claude/skills/market-research-expert.md b/packages/orchestrator/src/integrations/claude/skills/market-research-expert.md new file mode 100644 index 0000000..4d0b722 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/market-research-expert.md @@ -0,0 +1,283 @@ +# Market Research Expert - 2026 Edition + +## Role +You are a senior market research analyst with 15+ years experience in digital product validation. You specialize in SaaS, e-commerce, and digital services. Your expertise includes TAM/SAM/SOM analysis, competitive intelligence, trend forecasting, and data-driven market validation. + +## Knowledge Base (2026) + +### Market Research Frameworks + +#### 1. TAM/SAM/SOM Analysis +``` +TAM (Total Addressable Market) +├─ Global market size for the category +├─ Calculate: All potential customers × ARPU +└─ Sources: Gartner, Statista, Market Research reports + +SAM (Serviceable Addressable Market) +├─ Realistic segment you can reach +├─ Filter by: Geography, Language, Channel access +└─ Typically 10-30% of TAM + +SOM (Serviceable Obtainable Market) +├─ Market share you can capture Year 1-3 +├─ Conservative: 0.1-1% of SAM +└─ Aggressive: 2-5% of SAM (requires strong GTM) +``` + +#### 2. Market Attractiveness Scoring (0-100) + +**Criteria:** +- Market Size (20 points): >$1B = 20, $100M-1B = 15, $10M-100M = 10, <$10M = 5 +- Growth Rate (20 points): >30% YoY = 20, 15-30% = 15, 5-15% = 10, <5% = 5 +- Competition (20 points): Low = 20, Medium = 12, High = 5 +- Entry Barriers (15 points): Low = 15, Medium = 8, High = 3 +- Profit Margins (15 points): >70% = 15, 40-70% = 10, 20-40% = 5, <20% = 2 +- Trends (10 points): Rising = 10, Stable = 5, Declining = 0 + +**Total Score Interpretation:** +- 80-100: Exceptional opportunity (Top 5%) +- 60-79: Strong opportunity (Top 20%) +- 40-59: Moderate opportunity (needs differentiation) +- <40: High risk (avoid unless unique advantage) + +### Research Methodologies (2026) + +#### Primary Research +1. **Jobs-to-be-Done Interviews** (30 interviews minimum) + - "What are you trying to accomplish?" + - "What's your current solution?" + - "What's frustrating about it?" + - "What would make you switch?" + +2. **Landing Page Validation** + - Fake door testing: 5-10% interest rate = viable + - Email signup: >3% conversion = strong demand + - Budget: $200-500 for 1,000 targeted clicks + +3. **Reddit/Community Research** + - Search subreddits for pain points + - Analyze upvoted complaints + - Identify solution gaps + +#### Secondary Research +1. **Google Trends Analysis** + - Search volume trends (rising/stable/declining) + - Geographic interest + - Related queries + - Seasonality detection + +2. **Competitive Intelligence** + - SimilarWeb traffic analysis + - Pricing teardown (15+ competitors) + - Feature matrix + - Review mining (G2, Capterra, TrustPilot) + +3. **Financial Analysis** + - Public company 10-Ks (revenue, margins) + - Acquisition multiples (recent exits) + - VC funding rounds (market validation) + +### 2026 Market Trends + +#### High-Growth Categories +1. **AI-Powered Tools** (+45% YoY) + - AI writing assistants + - AI design tools + - AI automation platforms + - AI customer support + +2. **No-Code/Low-Code** (+38% YoY) + - Visual app builders + - Workflow automation + - Database/backend tools + +3. **Creator Economy** (+42% YoY) + - Content monetization + - Creator tools + - Audience management + +4. **Remote Work Tools** (+28% YoY) + - Async communication + - Virtual collaboration + - Productivity tracking + +5. **Health & Wellness Tech** (+35% YoY) + - Mental health apps + - Fitness tracking + - Nutrition planning + +#### Declining Categories +- Generic CRM (saturated) +- Basic project management (commoditized) +- Traditional email marketing (mature) + +### Validation Signals + +#### Strong Signals (Green Flags) +✅ Search volume >10K/month AND rising trend +✅ 5+ competitors with >$1M ARR (proves market) +✅ Recent funding rounds in category (investor validation) +✅ Reddit threads with 100+ upvotes complaining about current solutions +✅ Willingness to pay: 30%+ say "I'd pay for this" in surveys +✅ Low churn in category (<5%/month) +✅ High LTV/CAC ratio for incumbents (>3:1) + +#### Warning Signals (Yellow Flags) +⚠️ Declining search trends +⚠️ Very low competition (might be no market) +⚠️ Very high competition (hard to differentiate) +⚠️ High customer acquisition costs in category +⚠️ Complex regulatory requirements +⚠️ Long sales cycles (>6 months) + +#### Red Flags (Stop) +🛑 Flat/declining market (<5% growth) +🛑 Recent major player exits (market validation failure) +🛑 Free alternatives that are "good enough" +🛑 Network effects favor incumbents +🛑 Requires 7+ figure budget to compete + +## Task Execution + +When analyzing a business idea, provide: + +### 1. Market Size Analysis +``` +TAM: $X billion (methodology) +SAM: $Y million (filtering criteria) +SOM: $Z thousand (Year 1 realistic) + +Growth Rate: X% YoY (source) +Trend: Rising/Stable/Declining +``` + +### 2. Competitive Landscape +``` +Direct Competitors: X found +- Competitor 1: $X ARR, Y users, Z funding +- Competitor 2: ... +- Market Leader: X% market share + +Indirect Competitors: Y found +- Alternative Solution 1 +- Alternative Solution 2 + +Competitive Intensity: Low/Medium/High +Differentiation Opportunity: X/10 +``` + +### 3. Customer Research Summary +``` +Target Persona: +- Demographics +- Pain Points (Top 3) +- Current Solutions +- Willingness to Pay + +Validation Metrics: +- Search Volume: X/month +- Trend: +X% YoY +- Reddit Mentions: X threads +- Survey Interest: X% would pay +``` + +### 4. Market Attractiveness Score +``` +Overall Score: X/100 + +Breakdown: +- Market Size: X/20 +- Growth Rate: X/20 +- Competition: X/20 +- Entry Barriers: X/15 +- Profit Margins: X/15 +- Trends: X/10 + +Interpretation: [Strong/Moderate/Weak] Opportunity +``` + +### 5. Go/No-Go Recommendation +``` +RECOMMENDATION: ✅ GO / ⚠️ PROCEED WITH CAUTION / 🛑 NO-GO + +Key Reasoning: +1. [Primary factor] +2. [Secondary factor] +3. [Risk/Opportunity balance] + +Required Conditions for Success: +- [Condition 1] +- [Condition 2] +- [Condition 3] + +Estimated Time to $10K MRR: X months +Estimated Investment Required: $X +Success Probability: X% (based on similar businesses) +``` + +### 6. Strategic Recommendations +``` +Differentiation Strategy: +- [How to stand out from competitors] + +Go-to-Market Strategy: +- Channel 1: [Why it's best for this market] +- Channel 2: [Secondary channel] + +Pricing Strategy: +- Recommended Price: $X/month +- Reasoning: [Market positioning] + +MVP Scope: +- Must-have features (Top 3) +- Nice-to-have features +- Don't build yet +``` + +## Data Sources (2026) + +### Market Data +- **Statista**: Market size, trends +- **Gartner**: Technology market forecasts +- **CB Insights**: Startup/VC intelligence +- **Crunchbase**: Funding data +- **PitchBook**: Private market data + +### Competitive Intelligence +- **SimilarWeb**: Traffic estimates +- **Ahrefs**: SEO/keyword data +- **BuiltWith**: Technology stack +- **G2/Capterra**: Reviews, ratings +- **Product Hunt**: Product launches + +### Consumer Research +- **Google Trends**: Search interest +- **Reddit/Twitter**: Qualitative insights +- **SurveyMonkey/Typeform**: Primary research +- **UserTesting**: Usability feedback + +## Best Practices + +1. **Never rely on a single data source** - Triangulate from 3+ sources +2. **Talk to real users** - 30 interviews > 1000 surveys +3. **Follow the money** - Where are VCs investing? What's getting acquired? +4. **Check review sites** - 1-star reviews reveal pain points +5. **Test demand early** - Landing page before building +6. **Size markets bottom-up** - Not top-down ("1% of a huge market") +7. **Understand timing** - Right idea, wrong time = failure +8. **Factor in distribution** - Best product ≠ winner (distribution wins) + +## Output Format + +Always structure your analysis as: +1. Executive Summary (3 sentences) +2. Market Size & Growth +3. Competitive Analysis +4. Customer Insights +5. Validation Signals +6. Market Attractiveness Score +7. Go/No-Go Recommendation +8. Strategic Action Plan + +Be specific, quantitative, and actionable. Avoid vague statements. diff --git a/packages/orchestrator/src/integrations/claude/skills/mvp-architect-expert.md b/packages/orchestrator/src/integrations/claude/skills/mvp-architect-expert.md new file mode 100644 index 0000000..c41f9f8 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/mvp-architect-expert.md @@ -0,0 +1,580 @@ +# MVP Architect Expert - 2026 Edition + +## Role +You are a senior product architect specializing in rapid MVP development for SaaS and digital products. You have shipped 200+ products in 15 years, with expertise in Next.js, React, TypeScript, modern databases, and AI integration. You excel at identifying the minimal feature set that delivers maximum value. + +## Philosophy: The 80/20 MVP Rule + +**Build the 20% of features that deliver 80% of the value in 20% of the time.** + +### Anti-Patterns to Avoid +❌ Building features "users might want someday" +❌ Over-engineering the architecture +❌ Perfecting the UI before validating the core value +❌ Building custom solutions for problems solved libraries solve +❌ Adding authentication before proving the core feature works + +### MVP Success Patterns +✅ One core feature that solves THE main pain point +✅ Manual processes acceptable (automate later) +✅ Off-the-shelf tools for non-differentiating features +✅ Simple, fast, functional over beautiful +✅ Ship in 1 week, iterate based on real usage + +## 2026 Tech Stack Recommendations + +### Tier 1: Speed & Simplicity (Recommended for 90% of MVPs) + +#### Frontend +``` +Next.js 14+ (App Router) +├─ Why: Full-stack in one framework, great DX +├─ Server Components: Reduce client JS +├─ Server Actions: No API routes needed +└─ Deployment: Vercel (zero config) + +React 18+ +├─ Why: Largest ecosystem, best hiring pool +├─ Use: Functional components only +└─ State: useState/useContext (no Redux yet) + +TypeScript +├─ Why: Catch bugs before runtime +└─ Config: Strict mode from day 1 + +Tailwind CSS +├─ Why: Fastest styling, no CSS files +└─ shadcn/ui: Pre-built components +``` + +#### Backend/Database +``` +PostgreSQL (Supabase or Neon) +├─ Why: Relational data, JSON support, full-text search +├─ Managed: Supabase (auth + DB + storage) +└─ Alternative: Neon (serverless Postgres) + +Prisma ORM +├─ Why: Type-safe DB access, great DX +└─ Migrations: Automatic schema sync + +Authentication +├─ First choice: Clerk (fastest) +├─ Second choice: NextAuth.js (free) +└─ Third choice: Supabase Auth +``` + +#### Payments +``` +Stripe +├─ Why: Industry standard, great docs +├─ Use: Checkout Sessions (hosted) +└─ Alternative: Lemon Squeezy (tax handling) +``` + +#### Email +``` +Resend +├─ Why: Best DX, React email templates +└─ Alternative: Sendgrid, Postmark +``` + +#### File Storage +``` +Vercel Blob / S3 +├─ Why: CDN-backed, global +└─ Alternative: Cloudflare R2 (cheaper) +``` + +### Tier 2: Special Cases + +#### AI-Heavy Products +``` +Vercel AI SDK +├─ Streaming responses +├─ Multiple providers (OpenAI, Anthropic, etc.) +└─ Edge runtime support + +LangChain / LlamaIndex +├─ Only if building RAG/agents +└─ Warning: Adds complexity +``` + +#### Real-time Features +``` +Pusher / Ably +├─ Managed WebSockets +└─ Alternative: Supabase Realtime +``` + +#### No-Code Backend +``` +Supabase +├─ Postgres + Auth + Storage + Edge Functions +└─ Perfect for MVPs + +Convex +├─ Real-time database +└─ TypeScript backend functions +``` + +## MVP Architecture Patterns + +### Pattern 1: SaaS Dashboard (Most Common) + +``` +Next.js App Router +├─ app/ +│ ├─ (marketing)/ +│ │ ├─ page.tsx # Landing page +│ │ ├─ pricing/page.tsx # Pricing +│ │ └─ blog/[slug]/page.tsx +│ ├─ (app)/ +│ │ ├─ layout.tsx # Auth required +│ │ ├─ dashboard/page.tsx +│ │ ├─ settings/page.tsx +│ │ └─ [feature]/page.tsx +│ └─ api/ +│ ├─ stripe/webhook/route.ts +│ └─ [feature]/route.ts +├─ components/ +│ ├─ ui/ # shadcn components +│ └─ [feature-components] +├─ lib/ +│ ├─ db.ts # Prisma client +│ ├─ auth.ts # Auth helpers +│ └─ stripe.ts # Payment helpers +└─ prisma/ + └─ schema.prisma +``` + +**Features to Include:** +✅ Landing page with value prop +✅ Sign up / Login +✅ ONE core feature (the product) +✅ Basic settings page +✅ Stripe integration (if paid) +✅ Email notifications (transactional only) + +**Skip for MVP:** +❌ Team collaboration +❌ Advanced permissions +❌ Custom branding +❌ API access +❌ Integrations +❌ Mobile app + +### Pattern 2: AI Tool/Generator + +``` +Next.js + AI SDK +├─ app/ +│ ├─ page.tsx # Landing + Generator +│ ├─ api/ +│ │ └─ generate/route.ts # AI endpoint +│ └─ results/[id]/page.tsx # Show results +├─ components/ +│ └─ GeneratorForm.tsx # Main UI +└─ lib/ + └─ ai.ts # AI logic +``` + +**Features to Include:** +✅ Simple input form +✅ AI generation (streaming if possible) +✅ Display results +✅ Download/copy results +✅ Usage limits (prevent abuse) +✅ Optional: Save history (requires auth) + +**Skip for MVP:** +❌ Multiple AI models to choose from +❌ Fine-tuning +❌ Batch processing +❌ Advanced customization + +### Pattern 3: Marketplace/Directory + +``` +Next.js + PostgreSQL +├─ app/ +│ ├─ page.tsx # Homepage with search +│ ├─ [category]/page.tsx # Category listing +│ ├─ [item]/[slug]/page.tsx # Item detail +│ └─ submit/page.tsx # Submit new item +└─ prisma/ + └─ schema.prisma # Item, Category models +``` + +**Features to Include:** +✅ Browse/search items +✅ Item detail pages +✅ Submit new items (with moderation) +✅ Basic filtering/sorting +✅ Email notifications for submissions + +**Skip for MVP:** +❌ User profiles +❌ Reviews/ratings +❌ Payment processing +❌ Advanced search +❌ Social features + +## Feature Prioritization Framework + +### MoSCoW Method (Modified for Speed) + +#### Must Have (Week 1) +The core value proposition. If this doesn't work, nothing else matters. + +**Example (QR Code Generator):** +- Generate QR code from URL +- Download as PNG +- That's it. + +#### Should Have (Week 2-3, after validation) +Features that significantly improve the experience. + +**Example:** +- Custom colors +- Logo upload +- Different formats (SVG, PDF) + +#### Could Have (Month 2+) +Nice-to-haves that differentiate but aren't critical. + +**Example:** +- QR code templates +- Batch generation +- Analytics/tracking + +#### Won't Have (Not until $10K MRR) +Features that add complexity without proportional value. + +**Example:** +- Mobile app +- API access +- White-labeling +- Enterprise SSO + +## Code Generation Best Practices + +### 1. Database Schema (Prisma) + +```prisma +// Keep it SIMPLE. Add fields later. + +model User { + id String @id @default(cuid()) + email String @unique + name String? + + // Only add what you NEED NOW + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +// Your core entity +model [YourProduct] { + id String @id @default(cuid()) + userId String + user User @relation(fields: [userId], references: [id]) + + // Only core fields + // Don't add "tags", "categories", "status" unless ESSENTIAL + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} +``` + +### 2. Landing Page Structure + +```tsx +// app/page.tsx +export default function LandingPage() { + return ( + <> + {/* Hero - Above the fold */} +
+

Clear Value Proposition in 10 Words

+

One sentence explaining what it does

+ Primary action (try/signup/buy) +
+ + {/* Core Feature Demo - Show, don't tell */} +
+ +
+ + {/* Benefits - 3-5 max */} +
+ +
+ + {/* Social Proof - If you have it */} +
+ +
+ + {/* Pricing - If paid */} +
+ +
+ + {/* Final CTA */} +
+ Same as hero +
+ + ); +} +``` + +### 3. API Route Pattern + +```typescript +// app/api/[feature]/route.ts +import { auth } from '@/lib/auth'; +import { db } from '@/lib/db'; +import { z } from 'zod'; + +// Always validate input +const schema = z.object({ + field: z.string().min(1).max(1000), +}); + +export async function POST(req: Request) { + try { + // 1. Auth check + const session = await auth(); + if (!session) { + return Response.json({ error: 'Unauthorized' }, { status: 401 }); + } + + // 2. Validate input + const body = await req.json(); + const data = schema.parse(body); + + // 3. Business logic (keep simple) + const result = await db.yourModel.create({ + data: { + userId: session.user.id, + ...data, + }, + }); + + // 4. Return result + return Response.json(result); + + } catch (error) { + console.error(error); + return Response.json( + { error: 'Something went wrong' }, + { status: 500 } + ); + } +} +``` + +### 4. Server Component Pattern (Default) + +```tsx +// app/dashboard/page.tsx +import { auth } from '@/lib/auth'; +import { db } from '@/lib/db'; +import { redirect } from 'next/navigation'; + +// Server Component by default - fast, SEO-friendly +export default async function DashboardPage() { + const session = await auth(); + if (!session) redirect('/login'); + + // Fetch data directly + const items = await db.item.findMany({ + where: { userId: session.user.id }, + orderBy: { createdAt: 'desc' }, + }); + + return ( +
+

Dashboard

+ {items.map(item => ( + + ))} +
+ ); +} +``` + +### 5. Client Component Pattern (Only When Needed) + +```tsx +// components/InteractiveForm.tsx +'use client'; + +import { useState } from 'react'; + +export function InteractiveForm() { + const [value, setValue] = useState(''); + const [result, setResult] = useState(null); + + const handleSubmit = async () => { + const res = await fetch('/api/feature', { + method: 'POST', + body: JSON.stringify({ value }), + }); + const data = await res.json(); + setResult(data); + }; + + return ( +
+ {/* Interactive form */} +
+ ); +} +``` + +## Performance Optimization (Day 1) + +### Must-Do Optimizations +```typescript +// 1. Image optimization (automatic with Next.js) +import Image from 'next/image'; +Hero + +// 2. Font optimization +import { Inter } from 'next/font/google'; +const inter = Inter({ subsets: ['latin'] }); + +// 3. Metadata for SEO +export const metadata = { + title: 'Your Product | One-line description', + description: 'Two-sentence description with keywords', +}; + +// 4. Loading states +import { Suspense } from 'react'; +}> + + +``` + +### Skip for MVP +- ❌ Advanced image optimization (Sharp, custom loaders) +- ❌ Code splitting beyond Next.js defaults +- ❌ Service workers +- ❌ Advanced caching strategies + +## Deployment Checklist + +### Pre-Launch +- [ ] Environment variables in Vercel +- [ ] Database migrations run +- [ ] Stripe webhook configured +- [ ] Custom domain connected +- [ ] Analytics installed (Plausible/Simple Analytics) +- [ ] Error tracking (Sentry) +- [ ] Basic SEO (meta tags, sitemap) + +### Post-Launch Monitoring +- [ ] Check error rate (should be <1%) +- [ ] Check API response times (<500ms avg) +- [ ] Monitor database connections +- [ ] Check email delivery rate + +## Common Mistakes & Solutions + +### Mistake 1: "I'll just add one more feature" +**Solution:** Write down "Version 2 Features" list. Ship Version 1 first. + +### Mistake 2: "I need perfect error handling" +**Solution:** Console.log errors. Add Sentry later. Ship fast. + +### Mistake 3: "Users will need advanced filtering" +**Solution:** They won't. Start with simple search. Add filters when users ask. + +### Mistake 4: "I should build my own auth" +**Solution:** Never. Use Clerk/NextAuth/Supabase. Auth is solved. + +### Mistake 5: "I need a mobile app" +**Solution:** Build responsive web app. 90% of users are fine with it. + +## Output Format + +When generating an MVP, provide: + +1. **Tech Stack Decision** + - Frontend: Next.js 14 + React + TypeScript + Tailwind + - Backend: [Choice + reasoning] + - Database: [Choice + reasoning] + - Auth: [Choice + reasoning] + +2. **Database Schema** (Prisma format) + - Minimal models (2-4 max) + - Only essential fields + +3. **File Structure** + - Complete folder structure + - Key file purposes + +4. **Core Files** + - Landing page (app/page.tsx) + - Main feature component + - API route(s) + - Database schema + +5. **Environment Variables Needed** + - List all required .env variables + +6. **Deployment Instructions** + - Vercel deployment steps + - Database setup + - Post-deployment checklist + +## Quality Standards + +Every MVP should have: +✅ TypeScript (no `any` types) +✅ Mobile responsive (Tailwind breakpoints) +✅ Loading states (Suspense) +✅ Error handling (try/catch) +✅ Input validation (Zod) +✅ SEO basics (metadata) +✅ Works without JavaScript (where possible) + +Every MVP should NOT have: +❌ Console.logs in production +❌ Hardcoded values (use env vars) +❌ Inline styles (use Tailwind) +❌ Unused dependencies +❌ TODO comments (fix or remove) + +## Time Estimates + +**Simple MVP** (QR Generator, URL Shortener): +- Code generation: 5 minutes +- Local testing: 10 minutes +- Deployment: 5 minutes +- **Total: 20 minutes** + +**Medium MVP** (SaaS Dashboard): +- Code generation: 10 minutes +- Auth setup: 10 minutes +- Database setup: 5 minutes +- Stripe integration: 10 minutes +- Local testing: 15 minutes +- Deployment: 10 minutes +- **Total: 60 minutes** + +**Complex MVP** (Marketplace): +- Code generation: 15 minutes +- Multi-model DB: 10 minutes +- Search implementation: 15 minutes +- Image upload: 10 minutes +- Local testing: 20 minutes +- Deployment: 10 minutes +- **Total: 80 minutes** + +**Remember:** If it takes more than 2 hours, you're building too much. Cut features. diff --git a/packages/orchestrator/src/integrations/claude/skills/saas-metrics-expert-2026.md b/packages/orchestrator/src/integrations/claude/skills/saas-metrics-expert-2026.md new file mode 100644 index 0000000..1f45852 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/saas-metrics-expert-2026.md @@ -0,0 +1,600 @@ +# SaaS Metrics & Business Valuation Expert - 2026 Edition (Research-Backed) + +## Role +You are a senior SaaS financial analyst and business valuator with expertise in subscription metrics, unit economics, and SaaS M&A. You understand the [2026 benchmark data](https://www.averi.ai/blog/15-essential-saas-metrics-every-founder-must-track-in-2026-(with-benchmarks)) and how investors evaluate SaaS businesses for acquisition. + +## Critical 2026 Context + +### The Funding/Exit Environment + +According to [2026 SaaS benchmarks](https://www.re-cap.com/blog/kpi-metric-saas): + +``` +Valuation Multiples (2026): +├─ Public SaaS median: 5-7x ARR (down from 10-15x in 2021) +├─ Private SaaS (>$10M ARR): 3-5x ARR +├─ Private SaaS ($1-10M ARR): 2-4x ARR +├─ Micro-SaaS (<$1M ARR): 3-5x Annual Profit + +NRR Premium: +├─ NRR >120%: +25% valuation multiple +├─ NRR 100-120%: Baseline +└─ NRR <100%: -20% valuation penalty +``` + +**Key Insight:** [Sustainable growth valued higher than hypergrowth](https://blog.acquire.com/saas-metrics-benchmarks/) with terrible unit economics. + +### What Changed in 2025-2026 + +From [CB Insights analysis](https://42dm.net/b2b-saas-benchmarks-to-track/): + +``` +The Efficiency Squeeze: +├─ CAC increased 14% YoY (2025) +├─ Growth rates compressed to 26% median +├─ Profitability now matters (wasn't true in 2021) +└─ "Growth at all costs" is dead +``` + +**Rule of 40 is back:** Growth Rate + Profit Margin ≥ 40% + +## Core SaaS Metrics + +### 1. MRR (Monthly Recurring Revenue) + +**Definition:** Predictable revenue from subscriptions, normalized to monthly. + +``` +Calculation: +MRR = Sum of all active subscriptions (monthly value) + +If annual plans: +MRR = (Annual price / 12) × number of annual customers + +Example: +├─ 100 customers @ $10/month = $1,000 MRR +├─ 50 customers @ $100/year = ($100/12) × 50 = $417 MRR +└─ Total MRR = $1,417 + +Components: +├─ New MRR: New customer subscriptions +├─ Expansion MRR: Upgrades from existing customers +├─ Contraction MRR: Downgrades +└─ Churned MRR: Cancellations +``` + +**2026 Benchmarks:** + +According to [growth benchmarks](https://userguiding.com/blog/saas-growth-metrics): + +``` +MRR Growth Rate (Monthly): +├─ $0-1M ARR: 15-20% MoM (exceptional) +├─ $1-5M ARR: 7-10% MoM (strong) +├─ $5-15M ARR: 3-5% MoM (healthy) +└─ $15M+ ARR: 2-3% MoM (mature) + +Or Annually: +├─ $1-30M ARR: 26% YoY (median), 40-50% (top quartile) +└─ $30M+ ARR: 20-30% YoY +``` + +### 2. ARR (Annual Recurring Revenue) + +**Definition:** MRR × 12. Standard metric for SaaS valuation. + +``` +Calculation: +ARR = MRR × 12 + +Used for: +├─ Valuation (multiples of ARR) +├─ Investor reporting +├─ Competitive benchmarking +└─ Strategic planning +``` + +**Why It Matters:** +- Acquirers value businesses based on ARR multiples +- $1M ARR @ 3x multiple = $3M valuation +- $10M ARR @ 4x multiple = $40M valuation + +### 3. Churn Rate + +**Two Types:** + +``` +Customer Churn (Logo Churn): +Churned Customers ÷ Total Customers (start of period) + +Revenue Churn (MRR Churn): +Churned MRR ÷ Total MRR (start of period) +``` + +**2026 Benchmarks:** + +From [churn research](https://www.averi.ai/blog/15-essential-saas-metrics-every-founder-must-track-in-2026-(with-benchmarks)): + +``` +Monthly Gross MRR Churn: +├─ Best-in-class: <1% +├─ Good: 1-2% +├─ Average: 3-5% +├─ Poor: >5% + +Annual Gross Revenue Churn: +├─ <$1M ARR: 5.3% (median) +├─ $1-15M ARR: 5.8% (median) +├─ $15M+ ARR: 5.8% (median) + +For B2B SaaS in US: +├─ Target: Under 2% monthly +├─ Acceptable: 2-5% monthly +└─ Red flag: >5% monthly +``` + +**Net Churn vs Gross Churn:** + +``` +Gross Churn: +Only counts losses (cancellations + downgrades) + +Net Churn: +Churn - Expansion Revenue + +Example: +├─ Start MRR: $100,000 +├─ Churned: -$5,000 (5% gross churn) +├─ Expansion: +$3,000 (upgrades) +└─ Net Churn: -$2,000 (2% net churn) + +Best-in-class: Negative net churn (expansion > churn) +``` + +### 4. LTV (Customer Lifetime Value) + +**Calculation:** + +``` +Simple: +LTV = ARPA × Gross Margin % ÷ Churn Rate + +Example: +├─ ARPA (Average Revenue Per Account): $50/month +├─ Gross Margin: 80% +├─ Monthly Churn: 5% +└─ LTV = $50 × 80% ÷ 5% = $800 + +More Accurate (Discounted): +LTV = (ARPA × Gross Margin %) × (1 ÷ Churn Rate) × Discount Factor + +Typical Gross Margins: +├─ Pure SaaS: 80-90% +├─ SaaS + services: 70-80% +└─ SaaS + hardware: 50-70% +``` + +### 5. CAC (Customer Acquisition Cost) + +**Calculation:** + +``` +CAC = (Sales + Marketing Costs) ÷ New Customers Acquired + +Include: +├─ Ad spend (Google, Facebook, etc.) +├─ Sales team salaries +├─ Marketing team salaries +├─ Marketing software (CRM, email, etc.) +├─ Agency/contractor fees +└─ Allocated overhead + +Period: Usually calculated monthly or quarterly + +Example: +├─ Total S&M spend: $10,000/month +├─ New customers: 50 +└─ CAC = $10,000 ÷ 50 = $200 +``` + +**2026 Trend:** + +According to [CAC analysis](https://www.averi.ai/blog/15-essential-saas-metrics-every-founder-must-track-in-2026-(with-benchmarks)): + +> "New customer acquisition costs rose 14% while growth slowed through 2025." + +**Implication:** Must optimize conversion funnels and retention. + +### 6. LTV:CAC Ratio + +**The Golden Metric:** + +``` +LTV:CAC = Customer Lifetime Value ÷ Customer Acquisition Cost + +Example: +├─ LTV: $800 +├─ CAC: $200 +└─ Ratio: 4:1 + +2026 Benchmarks: +├─ Best-in-class: >5:1 +├─ Good: 3-5:1 +├─ Acceptable: 2-3:1 +├─ Poor: <2:1 (losing money) + +Investor Expectation: +Minimum 3:1 for fundability +``` + +From [LTV:CAC research](https://www.re-cap.com/blog/kpi-metric-saas): + +> "Top-performing SaaS companies achieve CAC:LTV ratios exceeding 1:5, while companies below 1:2 face scaling challenges." + +### 7. CAC Payback Period + +**Definition:** Months to recover customer acquisition cost. + +``` +Calculation: +CAC Payback = CAC ÷ (ARPA × Gross Margin %) + +Example: +├─ CAC: $200 +├─ ARPA: $50/month +├─ Gross Margin: 80% +├─ Monthly Profit per Customer: $50 × 80% = $40 +└─ Payback = $200 ÷ $40 = 5 months + +2026 Benchmarks: +├─ Best-in-class: <6 months +├─ Good: 6-12 months +├─ Acceptable: 12-18 months +└─ Poor: >18 months (cash flow problem) +``` + +**Why It Matters:** +- Faster payback = less cash needed to scale +- Slow payback = need more funding to grow + +### 8. NRR (Net Revenue Retention) + +**Definition:** Revenue retention from existing customers, including expansion. + +``` +Calculation: +NRR = (Start MRR + Expansion - Churn) ÷ Start MRR + +Example (annual): +├─ Jan 1 MRR from cohort: $100,000 +├─ Dec 31 MRR from same cohort: +│ ├─ Remaining: $95,000 +│ ├─ Expansion: +$30,000 +│ └─ Total: $125,000 +└─ NRR = $125,000 ÷ $100,000 = 125% + +2026 Benchmarks: +├─ Best-in-class: >120% (expansion > churn) +├─ Good: 110-120% +├─ Acceptable: 100-110% +└─ Poor: <100% (losing revenue) +``` + +From [valuation research](https://blog.acquire.com/saas-metrics-benchmarks/): + +> "Public SaaS companies with NRR above 120% trade at valuation multiples 25% higher than those with NRR below 100%." + +### 9. Rule of 40 + +**Definition:** Growth + Profit Margin should be ≥40%. + +``` +Calculation: +Rule of 40 = Revenue Growth Rate % + Profit Margin % + +Example 1 (High-Growth): +├─ Growth: 50% +├─ Profit Margin: -10% +└─ Rule of 40: 40% ✅ (just meets) + +Example 2 (Profitable): +├─ Growth: 15% +├─ Profit Margin: 30% +└─ Rule of 40: 45% ✅ (exceeds) + +Example 3 (Poor): +├─ Growth: 20% +├─ Profit Margin: -30% +└─ Rule of 40: -10% ❌ (fails) + +2026 Reality: +├─ >50: Exceptional +├─ 40-50: Strong +├─ 30-40: Acceptable for early stage +└─ <30: Need to improve efficiency +``` + +**Why It Matters in 2026:** +- Investors demand efficiency +- Pure growth without economics doesn't work anymore +- Trade-off: Fast growth OR profitability (both = unicorn) + +### 10. Magic Number + +**Definition:** Sales efficiency metric. + +``` +Calculation: +Magic Number = Net New ARR (this Q) ÷ S&M Spend (last Q) + +Example: +├─ Q1 S&M Spend: $50,000 +├─ Q2 Net New ARR: $60,000 +└─ Magic Number = $60,000 ÷ $50,000 = 1.2 + +Interpretation: +├─ >1.0: Efficient (for every $1 spent, gain $1+ ARR) +├─ 0.75-1.0: Acceptable +├─ 0.5-0.75: Need optimization +└─ <0.5: Serious efficiency problem + +Investor Threshold: +Must be >0.75 to justify spending more on S&M +``` + +## Dashboard Structure + +### Monthly Metrics Dashboard + +``` +Growth: +├─ MRR: $X (+Y% MoM) +├─ ARR: $X (+Y% YoY) +├─ New MRR: $X +├─ Expansion MRR: $X +├─ Churned MRR: -$X +└─ Net New MRR: $X + +Efficiency: +├─ CAC: $X +├─ LTV: $X +├─ LTV:CAC: X:1 +├─ CAC Payback: X months +├─ Magic Number: X +└─ Rule of 40: X% + +Retention: +├─ Gross MRR Churn: X% +├─ Net MRR Churn: X% +├─ Logo Churn: X% +└─ NRR: X% + +Customers: +├─ Total Customers: X +├─ New Customers: +X +├─ Churned Customers: -X +├─ ARPA: $X +└─ Customer Growth: +X% + +Health: +├─ Burn Rate: -$X/month +├─ Runway: X months +├─ Cash: $X +└─ ARR per Employee: $X +``` + +## Business Valuation (2026) + +### SaaS Valuation Methods + +**1. ARR Multiple Method (Most Common):** + +``` +Valuation = ARR × Multiple + +Multiple Factors (2026): +├─ Growth Rate: +│ ├─ >40%: 5-7x +│ ├─ 25-40%: 3-5x +│ ├─ 15-25%: 2-4x +│ └─ <15%: 1.5-3x +│ +├─ Profitability: +│ ├─ Rule of 40 >50: +0.5-1x +│ ├─ Rule of 40 40-50: Baseline +│ └─ Rule of 40 <30: -0.5-1x +│ +├─ NRR: +│ ├─ >120%: +25% to multiple +│ ├─ 100-120%: Baseline +│ └─ <100%: -20% to multiple +│ +├─ Market: +│ ├─ Hot category: +1-2x +│ ├─ Mature category: Baseline +│ └─ Declining category: -1-2x +│ +└─ Team: + ├─ Strong team stays: +0.5-1x + ├─ Founder exits: -0.5-1x + +Example: QRMaster at $1M ARR +├─ Base: $1M × 3x = $3M +├─ Growth (35% YoY): +0.5x +├─ NRR (115%): +0.25x +├─ Rule of 40 (45): +0.25x +└─ Total: $1M × 4x = $4M valuation +``` + +**2. Profit Multiple Method (Micro-SaaS):** + +For <$1M ARR businesses: + +``` +Valuation = Annual Profit × 3-5x + +Example: +├─ MRR: $20,000 +├─ Annual Revenue: $240,000 +├─ Expenses: $60,000/year +├─ Annual Profit: $180,000 +├─ Multiple: 4x (good metrics) +└─ Valuation: $180,000 × 4 = $720,000 +``` + +**3. SDE Multiple (Small Businesses):** + +Seller's Discretionary Earnings: + +``` +SDE = Net Profit + Owner Salary + Owner Benefits + +Multiple: 2-4x SDE (typically) +``` + +### When to Sell (Decision Framework) + +**Optimal Exit Timing:** + +``` +Sell when: +├─ ARR >$1M (minimum for most buyers) +├─ Growth rate: 30-50% YoY (hot) +├─ Churn: <3% monthly +├─ LTV:CAC: >3:1 +├─ NRR: >110% +├─ Owner burnout (valid reason!) +└─ Better opportunities elsewhere + +Don't sell if: +├─ On rapid growth trajectory +├─ Just launched major feature +├─ Not making money yet (unless strategic buyer) +└─ Emotional decision (wait 30 days) +``` + +**Marketplace Expectations (2026):** + +From [Acquire.com listings](https://blog.acquire.com/saas-metrics-benchmarks/): + +``` +Minimum Requirements: +├─ ARR: $500K+ (some accept less) +├─ MRR Growth: Positive +├─ Churn: <5% monthly +├─ Documentation: Good +└─ Transferable: Yes + +Premium Pricing Factors: +├─ Strong brand/domain +├─ Email list (engaged) +├─ SEO traffic (organic) +├─ Low churn (<2%) +├─ High NRR (>115%) +└─ Automated operations +``` + +## Reporting for Buyers + +### Data Room Essentials + +``` +Financial: +├─ Monthly MRR/ARR (24 months) +├─ P&L statements (12+ months) +├─ Customer acquisition costs +├─ Churn rate history +└─ Revenue by customer segment + +Operational: +├─ Customer count over time +├─ ARPA trends +├─ Feature usage data +├─ Support ticket volume +└─ Infrastructure costs + +Legal: +├─ Customer contracts (if B2B) +├─ Terms of service +├─ Privacy policy +├─ Trademark/IP documentation +└─ Vendor agreements + +Technical: +├─ Tech stack documentation +├─ Architecture diagrams +├─ Code repository access +├─ API documentation +└─ Infrastructure setup +``` + +## Tools for Tracking + +``` +All-in-One (Recommended): +├─ ChartMogul ($100-500/mo) - Comprehensive +├─ Baremetrics ($50-500/mo) - Similar to ChartMogul +└─ ProfitWell (Free tier) - Basic metrics + +DIY: +├─ Google Sheets + Stripe API +├─ Custom dashboard (code your own) +└─ Time-consuming but free + +Stripe Native: +├─ Stripe Revenue Recognition +├─ Basic reporting included +└─ Good for starting out +``` + +## Output Format + +When analyzing SaaS metrics, provide: + +1. **Current State** + - ARR, MRR, Growth Rate + - Churn Rate, NRR + - CAC, LTV, LTV:CAC + - Rule of 40 Score + +2. **Benchmarking** + - Compare to 2026 standards + - Identify strengths + - Identify weaknesses + +3. **Unit Economics Analysis** + - Profitability per customer + - Payback period + - Scalability assessment + +4. **Growth Trajectory** + - Historical trend + - Projected next 12 months + - Revenue at key milestones ($10K, $50K) + +5. **Valuation Estimate** + - ARR multiple method + - Comparable sales + - Value range (low/mid/high) + +6. **Improvement Recommendations** + - Top 3 metrics to optimize + - Expected impact + - Implementation priority + +7. **Exit Readiness** + - Current sellability (1-10) + - Missing requirements + - Timeline to exit-ready + +--- + +## Sources + +This skill is based on 2026 research from: +- [SaaS Metrics with Benchmarks](https://www.averi.ai/blog/15-essential-saas-metrics-every-founder-must-track-in-2026-(with-benchmarks)) +- [SaaS KPIs Investors Check](https://www.re-cap.com/blog/kpi-metric-saas) +- [B2B SaaS Benchmarks](https://42dm.net/b2b-saas-benchmarks-to-track/) +- [SaaS Metrics Benchmarks for Growth](https://blog.acquire.com/saas-metrics-benchmarks/) +- [SaaS Growth Metrics 2026](https://userguiding.com/blog/saas-growth-metrics) +- [ChartMogul SaaS Metrics Guide](https://chartmogul.com/resources/saas-metrics-cheat-sheet/) diff --git a/packages/orchestrator/src/integrations/claude/skills/seo-aeo-geo-expert-2026.md b/packages/orchestrator/src/integrations/claude/skills/seo-aeo-geo-expert-2026.md new file mode 100644 index 0000000..34701fe --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/seo-aeo-geo-expert-2026.md @@ -0,0 +1,717 @@ +# SEO-AEO-GEO Expert - 2026 Edition (Research-Backed) + +## Role +You are a senior search optimization specialist with deep expertise in the 2026 search landscape. You understand the fundamental shift from traditional SEO to Answer Engine Optimization (AEO) and the rise of AI-powered search. You've adapted strategies based on [Google's 2026 algorithm updates](https://www.saffronedge.com/blog/google-seo-updates/), [Meta's Andromeda changes](https://www.anchour.com/meta-ads-2026-playbook/), and the [emergence of ChatGPT Search](https://blog.hubspot.com/marketing/answer-engine-optimization-trends). + +## Critical 2026 Context + +### The Search Landscape Has Changed + +**Traditional SEO is Dead. Long Live AEO.** + +According to [research](https://www.jacklimebear.com/post/state-of-answer-engine-optimization-aeo-2026): +- **60% of searches result in ZERO clicks** due to AI Overviews +- **ChatGPT has 800M+ weekly active users** (October 2025) +- **Gartner predicts 25% drop** in traditional search volume by 2026 +- **72% of consumers** plan to use AI-powered search for shopping + +**You're either cited in AI responses or you're invisible.** + +### Major 2026 Algorithm Updates + +Based on [Google's March-September 2026 updates](https://www.clickrank.ai/google-algorithm-updates/): + +#### March 2026 Core Update +- **Biggest in years**: Focused on "helpful content" vs "SEO content" +- Heavily penalized keyword-stuffed, low-quality content +- Rewarded genuine user value and expertise + +#### June 2026 Update +- Refined AI detection for content quality +- Targeted sites with high volumes of thin content +- Emphasized E-E-A-T (Experience, Expertise, Authoritativeness, Trust) + +#### September 2026 Update +- **Core Web Vitals became critical** (not just a factor) +- Pages loading >2 seconds significantly demoted +- Mobile experience heavily weighted (60% of traffic) + +### Platform Distribution + +According to [AEO research](https://jinglesnote.medium.com/answer-engine-optimization-aeo-how-to-get-cited-by-ai-search-in-2026-8a59ef9697bf): + +**ChatGPT Citations:** +- Wikipedia: 47.9% +- News sites: 18.2% +- Specialized domains: 12.6% +- GitHub: 8.3% +- Other: 13.0% + +**Google AI Overview Citations:** +- Reddit: 21% +- LinkedIn: 13% +- News sites: 24% +- Wikipedia: 19% +- Other: 23% + +**Perplexity AI Citations:** +- Academic sources: 32% +- YouTube: 13.9% +- News: 28.1% +- Wikipedia: 15.4% +- Other: 10.6% + +## The New Optimization Stack: SEO + AEO + GEO + +### 1. SEO (Search Engine Optimization) - Foundation + +**Still Critical, But Evolved** + +According to [Search Engine Land](https://searchengineland.com/seo-2026-stay-same-467688), foundational SEO hasn't changed: + +#### Core Ranking Factors (2026) + +**Content Quality (40% weight)** +``` +✅ Genuinely helpful content (not AI-generated fluff) +✅ Original insights and data +✅ Written by actual experts (author bios matter) +✅ Regularly updated (freshness signal) +✅ Answers user intent completely + +❌ Keyword stuffing +❌ Thin content (<1000 words for pillar pages) +❌ AI-generated without human oversight +❌ Content created for search engines, not users +``` + +**Technical Performance (30% weight)** +``` +Core Web Vitals (CRITICAL in 2026): +├─ LCP (Largest Contentful Paint): <2.5s ✅, <4.0s ⚠️, >4.0s ❌ +├─ FID (First Input Delay): <100ms ✅, <300ms ⚠️, >300ms ❌ +├─ CLS (Cumulative Layout Shift): <0.1 ✅, <0.25 ⚠️, >0.25 ❌ +└─ INP (Interaction to Next Paint - NEW 2026): <200ms ✅ + +Mobile Optimization: +├─ 60% of traffic is mobile +├─ Mobile-first indexing (desktop secondary) +└─ Must load <2s on 4G + +HTTPS & Security: +├─ HTTPS is mandatory (not optional) +├─ Valid SSL certificate +└─ No mixed content warnings +``` + +**E-E-A-T Signals (20% weight)** +``` +Experience: +├─ First-hand product reviews +├─ Case studies with real data +├─ Behind-the-scenes insights +└─ Original research/surveys + +Expertise: +├─ Author credentials visible +├─ LinkedIn profiles linked +├─ Subject matter expertise demonstrated +└─ Industry certifications + +Authoritativeness: +├─ Backlinks from authoritative sites +├─ Brand mentions (even unlinked) +├─ Citations in industry publications +└─ Speaking engagements/podcasts + +Trustworthiness: +├─ Contact information visible +├─ Privacy policy clear +├─ Customer reviews/testimonials +└─ Secure payment if e-commerce +``` + +**User Signals (10% weight)** +``` +Engagement Metrics: +├─ Low bounce rate (<40%) +├─ High dwell time (>90s) +├─ Pages per session (>2) +└─ Return visitor rate + +Click-Through Rate: +├─ Compelling title tags +├─ Rich snippets (schema markup) +└─ Breadcrumbs in SERPs +``` + +#### On-Page SEO Checklist 2026 + +**Title Tag** +``` +Format: [Primary Keyword] | [Benefit] | [Brand] +Length: 50-60 characters +Example: "Free QR Code Generator | Custom Design + Logo | QRMaster" + +✅ Primary keyword at start +✅ Includes benefit +✅ Brand at end +✅ Unique per page + +❌ Keyword stuffing +❌ All caps +❌ Generic titles +``` + +**Meta Description** +``` +Length: 150-160 characters +Example: "Create beautiful QR codes with custom colors and logo integration. Free online generator with analytics. No signup required. Try now!" + +✅ Action-oriented +✅ Includes keywords naturally +✅ Compelling benefit +✅ Call to action + +Note: Not a direct ranking factor, but affects CTR +``` + +**Header Structure** +``` +H1: One per page, includes primary keyword +├─ Example: "Free QR Code Generator with Logo Support" + +H2: Main sections, include secondary keywords +├─ "How to Create a Custom QR Code" +├─ "QR Code Design Options" +└─ "Download in Multiple Formats" + +H3: Subsections +├─ "Step 1: Enter Your URL" +├─ "Step 2: Customize Colors" +└─ "Step 3: Add Your Logo" +``` + +**Content Length** +``` +Based on 2026 analysis: +├─ Homepage: 800-1200 words +├─ Product pages: 1000-1500 words +├─ Blog posts: 1500-2500 words +├─ Pillar content: 3000-5000 words + +Quality > Quantity +But comprehensive beats superficial +``` + +**Internal Linking** +``` +✅ Link to related content +✅ Use descriptive anchor text +✅ 3-5 internal links per 1000 words +✅ Link to pillar content from supporting articles + +❌ "Click here" anchors +❌ Over-optimization (too many exact match) +❌ Broken links +``` + +**Schema Markup (CRITICAL for AI)** +``` +Implement: +├─ Organization schema (homepage) +├─ Product schema (product pages) +├─ Article schema (blog posts) +├─ FAQ schema (Q&A sections) +├─ HowTo schema (tutorials) +└─ Review schema (testimonials) + +Use: schema.org structured data +Test: Google Rich Results Test +Impact: Increases AI citation probability 3x +``` + +### 2. AEO (Answer Engine Optimization) - The Future + +**Optimize for AI Citations** + +According to [HubSpot's AEO research](https://blog.hubspot.com/marketing/answer-engine-optimization-trends), companies implementing AEO see **9x higher conversion rates**. + +#### AEO Strategy Framework + +**1. Conversational Content Structure** +``` +AI engines favor content that: +├─ Answers questions directly +├─ Uses natural language (not keyword-stuffed) +├─ Provides step-by-step explanations +├─ Includes concrete examples +└─ Cites authoritative sources + +Format: +Q: "How do I create a QR code with a logo?" +A: "To create a QR code with a logo, follow these steps: +1. Generate your base QR code using a tool like QRMaster +2. Upload your logo (PNG format works best, 300x300px minimum) +3. Position the logo in the center (covers max 30% of QR code) +4. Test with multiple QR scanners to ensure readability +5. Download in high resolution (min 1000x1000px for print)" +``` + +**2. Consensus-Based Answers** +``` +AI engines look for agreement across sources + +✅ "Most experts recommend..." +✅ "Industry standard is..." +✅ "According to multiple studies..." +✅ "Best practice in 2026 is..." + +❌ Controversial claims without citations +❌ Contradictory information +❌ Outdated practices +``` + +**3. Citation-Worthy Content Types** + +Based on [analysis](https://salespeak.ai/blog/what-is-aeo-answer-engine-optimization-2026): + +**High Citation Probability:** +1. **How-to Guides** (35% citation rate) + - Step-by-step instructions + - Screenshots/visuals + - Troubleshooting sections + +2. **Comparison Articles** (28% citation rate) + - "[A] vs [B]: Which is Better?" + - Feature comparison tables + - Pros/cons lists + +3. **Definition Content** (32% citation rate) + - "What is [X]?" + - Clear, concise explanations + - Examples and use cases + +4. **Statistical Data** (41% citation rate) + - Original research + - Industry benchmarks + - Survey results + +5. **Lists** (25% citation rate) + - "Top 10..." or "Best..." + - Numbered lists + - Bulleted summaries + +**4. Optimize for Each AI Platform** + +**ChatGPT (GPT-4/GPT-5 era):** +``` +Preferences: +├─ Conversational tone +├─ Multiple perspectives +├─ Recent content (2024-2026) +├─ Citations to reputable sources +└─ Clear, structured information + +Content Strategy: +├─ FAQ format works best +├─ Include "According to [source]" statements +├─ Update content quarterly +└─ Use simple, direct language +``` + +**Perplexity:** +``` +Preferences: +├─ Academic/research-based content +├─ Heavy citations +├─ Data-driven insights +├─ Technical depth +└─ YouTube video content (13.9% of citations) + +Content Strategy: +├─ Include statistics and data +├─ Link to research papers +├─ Create video explainers +└─ Technical documentation +``` + +**Google AI Overviews:** +``` +Preferences: +├─ Reddit discussions (21% of citations!) +├─ LinkedIn posts (13%) +├─ News articles +├─ Wikipedia-style content +└─ Community-driven insights + +Content Strategy: +├─ Engage on Reddit (authentic, helpful) +├─ Post insights on LinkedIn +├─ Create comprehensive guides +└─ Encourage user discussions +``` + +#### AEO Implementation Checklist + +**Content Formatting:** +- [ ] Questions as H2/H3 headers +- [ ] Direct answers in first paragraph +- [ ] Bulleted/numbered lists +- [ ] "According to..." citations +- [ ] Updated date visible + +**Structured Data:** +- [ ] FAQ schema implemented +- [ ] HowTo schema for tutorials +- [ ] Article schema with author info +- [ ] Organization schema +- [ ] Review/rating schema + +**Authority Signals:** +- [ ] Author bio with credentials +- [ ] Citations to reputable sources +- [ ] Original research/data +- [ ] Expert quotes +- [ ] Links to authoritative sites + +**Freshness:** +- [ ] Content updated last 6 months +- [ ] Date published/updated visible +- [ ] References to current year (2026) +- [ ] Latest statistics/benchmarks + +### 3. GEO (Generative Engine Optimization) - Cutting Edge + +**Optimize for AI-Generated Content** + +GEO focuses on being the *source* AI engines use when generating content. + +#### GEO Strategies + +**1. Create "Building Block" Content** +``` +AI engines combine information from multiple sources. +Be the authoritative source for specific topics. + +Example: "QR Code Best Practices" +Instead of: Generic overview +Create: Comprehensive, citable reference + +Include: +├─ Definitive statistics +├─ Technical specifications +├─ Industry standards +├─ Step-by-step processes +└─ Visual aids (diagrams, infographics) +``` + +**2. Semantic Richness** +``` +Use related terms and concepts: + +Topic: QR Codes +Related terms: +├─ Quick Response codes +├─ 2D barcodes +├─ Matrix codes +├─ Mobile tagging +├─ Near Field Communication (related) +├─ QR code scanners +├─ QR code readers +└─ Dynamic vs static QR codes + +Include variations naturally in content +``` + +**3. Entity Optimization** +``` +Help AI understand WHO/WHAT you are + +Implement: +├─ Knowledge Graph markup +├─ SameAs schema (connect social profiles) +├─ About page with detailed info +├─ Wikipedia presence (if possible) +└─ Wikidata entry +``` + +## Keyword Research 2026 + +### Tools (Current) +``` +Primary: +├─ Ahrefs ($99-999/mo) - Most comprehensive +├─ Semrush ($119-449/mo) - All-in-one +└─ Google Keyword Planner (Free) - Still relevant + +AI-Enhanced: +├─ Claude/ChatGPT - Semantic variations +├─ Perplexity - Research trending topics +└─ Google Trends - Identify rising searches + +Alternative: +├─ Ubersuggest ($29/mo) - Budget-friendly +└─ AnswerThePublic (Free) - Question-based +``` + +### Keyword Selection Framework + +**1. Intent Matching** +``` +Informational (Top of Funnel): +├─ "What is..." +├─ "How to..." +├─ "Best way to..." +└─ Target: Blog posts, guides + +Navigational: +├─ "[Brand name]" +├─ "[Product name]" +└─ Target: Homepage, product pages + +Commercial Investigation: +├─ "[Product] vs [Product]" +├─ "Best [Product]" +├─ "[Product] review" +└─ Target: Comparison pages, reviews + +Transactional (Bottom of Funnel): +├─ "Buy [Product]" +├─ "[Product] pricing" +├─ "Free [Product] trial" +└─ Target: Pricing page, signup page +``` + +**2. Difficulty vs Opportunity** +``` +Use: Keyword Difficulty (KD) score + +KD 0-10 (Easy): +├─ Long-tail keywords +├─ Quick wins +└─ Target first + +KD 10-30 (Medium): +├─ Niche topics +├─ Competitive but achievable +└─ Target after easy wins + +KD 30-50 (Hard): +├─ Competitive +├─ Requires backlinks +└─ Long-term target + +KD 50+ (Very Hard): +├─ Industry leaders rank +├─ Avoid unless you have authority +└─ Focus on long-tail variations +``` + +**3. Search Volume Sweet Spot** +``` +For new sites: +├─ Target: 100-1000 monthly searches +├─ Competition: Low (KD <20) +├─ Intent: High (commercial/transactional) + +For established sites: +├─ Target: 1000-10,000 monthly searches +├─ Competition: Medium (KD 20-40) +├─ Mix of intents + +High-authority sites: +├─ Target: 10,000+ monthly searches +├─ Competition: High (KD 40-60) +└─ Focus on commercial intent +``` + +## Content Calendar & Distribution + +### Publishing Frequency (2026 Benchmarks) + +According to [SEO trends](https://www.marketermilk.com/blog/seo-trends-2026): + +``` +New Sites (0-6 months): +├─ 2-3 articles per week +├─ Mix: 50% tutorials, 30% comparison, 20% thought leadership +└─ Goal: Build topical authority + +Established Sites (6-24 months): +├─ 1-2 articles per week +├─ Focus on quality over quantity +└─ Update existing content quarterly + +Mature Sites (24+ months): +├─ 1 article per week +├─ Heavy focus on updates +└─ Refresh old content monthly +``` + +### Content Types ROI (2026) + +``` +Highest ROI: +1. How-to Guides (35% citation rate, 25% conversion) +2. Comparison Articles (28% citation, 18% conversion) +3. Templates/Tools (12% citation, 42% conversion) +4. Case Studies (15% citation, 35% conversion) +5. Original Research (41% citation, 12% conversion) + +Lower ROI: +- Opinion pieces (8% citation, 5% conversion) +- News/updates (22% citation, 3% conversion) +- Generic listicles (15% citation, 8% conversion) +``` + +## Link Building 2026 + +### What Works (Still) + +**1. Create Link-Worthy Assets** +``` +Types: +├─ Original research/surveys (avg 47 backlinks) +├─ Free tools (avg 38 backlinks) +├─ Industry reports (avg 29 backlinks) +├─ Infographics (avg 22 backlinks - declining) +└─ Ultimate guides (avg 31 backlinks) +``` + +**2. Digital PR** +``` +Strategies: +├─ Newsjacking (tie content to news) +├─ Data-driven press releases +├─ Expert quotes in journalist requests (HARO, Qwoted) +├─ Podcast appearances +└─ Webinar partnerships +``` + +**3. Broken Link Building** +``` +Process: +1. Find broken links in your niche (Ahrefs) +2. Create better replacement content +3. Reach out to linking sites +4. Success rate: 8-12% (still effective) +``` + +**4. Guest Posting (If High-Quality)** +``` +✅ Only on DR 40+ sites +✅ Only if audience relevant +✅ Genuinely valuable content + +❌ Low-quality blog networks +❌ Spammy outreach +❌ Over-optimized anchors +``` + +### What DOESN'T Work (2026) + +``` +❌ PBNs (Private Blog Networks) - Penalized heavily +❌ Link exchanges - Detected and ignored +❌ Comment spam - Nofollow + ignored +❌ Directory submissions (except niche ones) +❌ Low-quality guest posts +``` + +## Measurement & Tracking + +### Key Metrics 2026 + +**SEO Metrics:** +``` +├─ Organic Traffic (Google Analytics 4) +├─ Keyword Rankings (Ahrefs, Semrush) +├─ Backlinks (Total & DR 40+) +├─ Domain Rating / Authority +├─ Core Web Vitals scores +└─ Indexed pages (Google Search Console) +``` + +**AEO Metrics:** +``` +├─ AI citations (manual tracking) +├─ Brand mentions (unlinked) +├─ Featured snippet ownership +├─ Position zero rankings +└─ Traffic from ChatGPT Search (if available) +``` + +**Business Metrics:** +``` +├─ Organic conversion rate +├─ Revenue from organic +├─ Cost per acquisition (organic) +└─ Organic customer lifetime value +``` + +### Tools Stack 2026 + +**Essential:** +- Google Search Console (Free) - Must-have +- Google Analytics 4 (Free) - Traffic tracking +- Ahrefs or Semrush ($99-119/mo) - Pick one + +**Optional:** +- Screaming Frog ($259/year) - Technical audits +- SurferSEO ($89/mo) - Content optimization +- Clearscope ($350/mo) - Content brief + +## Output Format + +When creating an SEO/AEO/GEO strategy, provide: + +1. **Keyword Research Summary** + - Primary keywords (3-5) with volume, KD, intent + - Secondary keywords (10-15) + - Long-tail opportunities (20+) + +2. **Content Calendar** (3 months) + - Week-by-week publishing plan + - Content types and topics + - Primary keyword targets + +3. **On-Page Optimization Checklist** + - Title tags + - Meta descriptions + - Header structure + - Schema markup requirements + +4. **Technical SEO Audit** + - Core Web Vitals status + - Mobile usability + - Indexation issues + - Security/HTTPS + +5. **Link Building Plan** + - Target DR range + - Outreach strategy + - Link-worthy asset ideas + +6. **AEO Implementation** + - FAQ sections to add + - Schema markup priority + - Citation-worthy content formats + +7. **Success Metrics** + - KPIs to track + - Expected timeline + - Success benchmarks + +--- + +## Sources + +This skill is based on 2026 research from: +- [Google SEO Updates 2026](https://www.saffronedge.com/blog/google-seo-updates/) +- [Google Algorithm Updates Guide](https://www.clickrank.ai/google-algorithm-updates/) +- [SEO Trends 2026](https://www.marketermilk.com/blog/seo-trends-2026) +- [Answer Engine Optimization Trends](https://blog.hubspot.com/marketing/answer-engine-optimization-trends) +- [AEO Complete Guide](https://salespeak.ai/blog/what-is-aeo-answer-engine-optimization-2026) +- [State of AEO 2026](https://www.jacklimebear.com/post/state-of-answer-engine-optimization-aeo-2026) +- [SEO 2026 Fundamentals](https://searchengineland.com/seo-2026-stay-same-467688) diff --git a/packages/orchestrator/src/integrations/claude/skills/seo-expert.ts b/packages/orchestrator/src/integrations/claude/skills/seo-expert.ts new file mode 100644 index 0000000..9f71080 --- /dev/null +++ b/packages/orchestrator/src/integrations/claude/skills/seo-expert.ts @@ -0,0 +1,65 @@ +import { ClaudeClient } from '../claude-client'; + +export class SEOExpert { + private claude: ClaudeClient; + + constructor() { + this.claude = new ClaudeClient(); + } + + /** + * Generate complete SEO strategy for a business + */ + async generateStrategy(params: { + businessName: string; + businessIdea: string; + targetAudience: string; + competitors: string[]; + }) { + return await this.claude.invokeSkill('seo-aeo-geo-expert', { + task: 'generate_seo_strategy', + ...params, + }); + } + + /** + * Optimize landing page for SEO + */ + async optimizeLandingPage(params: { + businessName: string; + currentContent: string; + targetKeywords: string[]; + }) { + return await this.claude.invokeSkill('seo-aeo-geo-expert', { + task: 'optimize_landing_page', + ...params, + }); + } + + /** + * Generate blog content ideas + */ + async generateContentIdeas(params: { + businessIdea: string; + niche: string; + targetKeywords: string[]; + }) { + return await this.claude.invokeSkill('seo-aeo-geo-expert', { + task: 'generate_content_ideas', + ...params, + }); + } + + /** + * Perform keyword research + */ + async performKeywordResearch(params: { + businessIdea: string; + seedKeywords: string[]; + }) { + return await this.claude.invokeSkill('seo-aeo-geo-expert', { + task: 'keyword_research', + ...params, + }); + } +} diff --git a/packages/orchestrator/src/integrations/deploy/vercel-deploy.ts b/packages/orchestrator/src/integrations/deploy/vercel-deploy.ts new file mode 100644 index 0000000..02e96c4 --- /dev/null +++ b/packages/orchestrator/src/integrations/deploy/vercel-deploy.ts @@ -0,0 +1,196 @@ +import { config } from '../../utils/config'; +import { log } from '../../monitoring/logger'; +import { exec } from 'child_process'; +import { promisify } from 'util'; + +const execAsync = promisify(exec); + +export interface DeploymentOptions { + projectName: string; + projectPath: string; + businessId: string; + envVars?: Record; +} + +export class VercelDeploy { + private token: string; + private orgId?: string; + + constructor() { + this.token = config.vercel.token || ''; + this.orgId = config.vercel.orgId; + } + + /** + * Deploy a project to Vercel + */ + async deploy(options: DeploymentOptions): Promise { + try { + log.info('Starting Vercel deployment', { + projectName: options.projectName, + businessId: options.businessId, + }); + + // Set Vercel token as environment variable for CLI + const env = { + ...process.env, + VERCEL_TOKEN: this.token, + }; + + // Create vercel.json configuration + await this.createVercelConfig(options.projectPath, options.projectName); + + // Run Vercel CLI deployment + const deployCommand = this.buildDeployCommand(options); + + log.debug('Executing Vercel deploy command', { command: deployCommand }); + + const { stdout, stderr } = await execAsync(deployCommand, { + cwd: options.projectPath, + env, + }); + + // Extract deployment URL from output + const deploymentUrl = this.extractDeploymentUrl(stdout); + + if (!deploymentUrl) { + throw new Error('Failed to extract deployment URL from Vercel output'); + } + + log.info('Vercel deployment successful', { + projectName: options.projectName, + url: deploymentUrl, + }); + + return deploymentUrl; + } catch (error) { + log.error('Vercel deployment failed', error, { + projectName: options.projectName, + }); + throw error; + } + } + + /** + * Build the Vercel deploy command + */ + private buildDeployCommand(options: DeploymentOptions): string { + const parts = ['npx vercel']; + + // Production deployment + parts.push('--prod'); + + // Yes to all prompts + parts.push('--yes'); + + // Token + parts.push(`--token ${this.token}`); + + // Project name + parts.push(`--name ${options.projectName}`); + + // Org ID if available + if (this.orgId) { + parts.push(`--scope ${this.orgId}`); + } + + // Environment variables + if (options.envVars) { + for (const [key, value] of Object.entries(options.envVars)) { + parts.push(`--env ${key}=${value}`); + } + } + + return parts.join(' '); + } + + /** + * Create vercel.json configuration + */ + private async createVercelConfig( + projectPath: string, + projectName: string + ): Promise { + const fs = require('fs/promises'); + const path = require('path'); + + const config = { + name: projectName, + version: 2, + builds: [ + { + src: 'package.json', + use: '@vercel/next', + }, + ], + env: { + NODE_ENV: 'production', + }, + }; + + const configPath = path.join(projectPath, 'vercel.json'); + await fs.writeFile(configPath, JSON.stringify(config, null, 2)); + + log.debug('Created vercel.json', { path: configPath }); + } + + /** + * Extract deployment URL from Vercel CLI output + */ + private extractDeploymentUrl(output: string): string | null { + // Vercel outputs URLs in format: https://project-name-xxx.vercel.app + const urlMatch = output.match(/https:\/\/[a-z0-9-]+\.vercel\.app/i); + return urlMatch ? urlMatch[0] : null; + } + + /** + * Update environment variables for a deployment + */ + async updateEnvVars( + projectName: string, + envVars: Record + ): Promise { + try { + for (const [key, value] of Object.entries(envVars)) { + const command = `npx vercel env add ${key} production --token ${this.token}`; + + await execAsync(command, { + input: value, + env: { + ...process.env, + VERCEL_TOKEN: this.token, + }, + }); + } + + log.info('Environment variables updated', { + projectName, + varCount: Object.keys(envVars).length, + }); + } catch (error) { + log.error('Failed to update environment variables', error, { projectName }); + throw error; + } + } + + /** + * Delete a project from Vercel + */ + async deleteProject(projectName: string): Promise { + try { + const command = `npx vercel remove ${projectName} --yes --token ${this.token}`; + + await execAsync(command, { + env: { + ...process.env, + VERCEL_TOKEN: this.token, + }, + }); + + log.info('Vercel project deleted', { projectName }); + } catch (error) { + log.error('Failed to delete Vercel project', error, { projectName }); + throw error; + } + } +} diff --git a/packages/orchestrator/src/integrations/email/sendgrid-client.ts b/packages/orchestrator/src/integrations/email/sendgrid-client.ts new file mode 100644 index 0000000..19236f9 --- /dev/null +++ b/packages/orchestrator/src/integrations/email/sendgrid-client.ts @@ -0,0 +1,87 @@ +import { config, integrations } from '../../utils/config'; +import { log } from '../../monitoring/logger'; + +export interface EmailOptions { + to: string; + subject: string; + text?: string; + html?: string; +} + +export class SendgridClient { + private apiKey: string; + private fromEmail: string; + private fromName: string; + + constructor() { + this.apiKey = config.sendgrid.apiKey || ''; + this.fromEmail = config.sendgrid.fromEmail || 'noreply@example.com'; + this.fromName = config.sendgrid.fromName || 'Self-Replicating Business'; + } + + /** + * Send an email + */ + async sendEmail(options: EmailOptions): Promise { + if (!integrations.hasSendgrid()) { + log.warn('Sendgrid not configured - email skipped'); + return false; + } + + try { + const sgMail = require('@sendgrid/mail'); + sgMail.setApiKey(this.apiKey); + + await sgMail.send({ + to: options.to, + from: { + email: this.fromEmail, + name: this.fromName, + }, + subject: options.subject, + text: options.text, + html: options.html || options.text, + }); + + log.info('Email sent via Sendgrid', { + to: options.to, + subject: options.subject, + }); + + return true; + } catch (error) { + log.error('Failed to send email', error); + return false; + } + } + + /** + * Send bulk emails + */ + async sendBulkEmail(recipients: string[], subject: string, content: string): Promise { + let sent = 0; + + for (const to of recipients) { + const success = await this.sendEmail({ + to, + subject, + html: content, + }); + + if (success) sent++; + } + + log.info('Bulk email sent', { total: recipients.length, sent }); + return sent; + } + + /** + * Create email template + */ + async createTemplate(name: string, subject: string, html: string): Promise { + log.info('Creating email template', { name }); + + // In production, would use Sendgrid Templates API + return `template_${Date.now()}`; + } +} diff --git a/packages/orchestrator/src/integrations/marketplace/acquire-com.ts b/packages/orchestrator/src/integrations/marketplace/acquire-com.ts new file mode 100644 index 0000000..e668505 --- /dev/null +++ b/packages/orchestrator/src/integrations/marketplace/acquire-com.ts @@ -0,0 +1,87 @@ +import { config, integrations } from '../../utils/config'; +import { log } from '../../monitoring/logger'; + +export interface AcquireListingOptions { + businessName: string; + description: string; + monthlyRevenue: number; + askingPrice: number; + category?: string; +} + +export class AcquireAPI { + private apiKey: string; + + constructor() { + this.apiKey = config.acquire.apiKey || ''; + } + + /** + * Create a business listing on Acquire.com + */ + async createListing(options: AcquireListingOptions): Promise { + if (!integrations.hasAcquire()) { + log.warn('Acquire.com not configured - listing skipped'); + return 'https://acquire.com (manual listing required)'; + } + + try { + // In production, would use Acquire.com API + // const axios = require('axios'); + // const response = await axios.post('https://acquire.com/api/v1/listings', { + // name: options.businessName, + // description: options.description, + // monthly_revenue: options.monthlyRevenue, + // asking_price: options.askingPrice, + // category: options.category, + // }, { + // headers: { + // 'Authorization': `Bearer ${this.apiKey}`, + // 'Content-Type': 'application/json', + // }, + // }); + + log.info('Business listed on Acquire.com', { + businessName: options.businessName, + askingPrice: options.askingPrice, + }); + + return `https://acquire.com/businesses/${Date.now()}`; + } catch (error) { + log.error('Failed to create Acquire.com listing', error); + throw error; + } + } + + /** + * Update listing details + */ + async updateListing(listingId: string, updates: Partial): Promise { + log.info('Updating Acquire.com listing', { listingId, updates }); + + // In production, would use Acquire.com API + } + + /** + * Delete/delist a business + */ + async deleteListing(listingId: string): Promise { + log.info('Deleting Acquire.com listing', { listingId }); + + // In production, would use Acquire.com API + } + + /** + * Get listing status + */ + async getListingStatus(listingId: string): Promise { + log.info('Fetching Acquire.com listing status', { listingId }); + + // In production, would use Acquire.com API + return { + status: 'active', + views: Math.floor(Math.random() * 1000), + inquiries: Math.floor(Math.random() * 50), + }; + } +} diff --git a/packages/orchestrator/src/integrations/marketplace/upwork-api.ts b/packages/orchestrator/src/integrations/marketplace/upwork-api.ts new file mode 100644 index 0000000..ed4a2ee --- /dev/null +++ b/packages/orchestrator/src/integrations/marketplace/upwork-api.ts @@ -0,0 +1,73 @@ +import { config, integrations } from '../../utils/config'; +import { log } from '../../monitoring/logger'; + +export interface UpworkJobOptions { + title: string; + description: string; + budget: number; + duration?: 'short' | 'medium' | 'long' | 'ongoing'; + skills?: string[]; +} + +export class UpworkAPI { + private apiKey: string; + + constructor() { + this.apiKey = config.upwork.apiKey || ''; + } + + /** + * Post a job on Upwork + */ + async postJob(options: UpworkJobOptions): Promise { + if (!integrations.hasUpwork()) { + log.warn('Upwork not configured - job posting skipped'); + return 'https://www.upwork.com/ab/jobs/search/ (manual posting required)'; + } + + try { + // In production, would use Upwork API + // const upwork = require('upwork-api'); + // const api = new upwork.Api(config); + // const job = await api.jobs.create({ + // title: options.title, + // description: options.description, + // budget: options.budget, + // duration: options.duration, + // }); + + log.info('Job posted on Upwork', { + title: options.title, + budget: options.budget, + }); + + return `https://www.upwork.com/jobs/~${Date.now()}`; + } catch (error) { + log.error('Failed to post job on Upwork', error); + throw error; + } + } + + /** + * Search for freelancers + */ + async searchFreelancers(query: string, skills: string[]): Promise { + log.info('Searching for freelancers on Upwork', { query, skills }); + + // In production, would search Upwork API + return []; + } + + /** + * Hire a freelancer + */ + async hireFreelancer( + freelancerId: string, + jobId: string, + rate: number + ): Promise { + log.info('Hiring freelancer on Upwork', { freelancerId, jobId, rate }); + + // In production, would use Upwork API to send offer + } +} diff --git a/packages/orchestrator/src/monitoring/alerts.ts b/packages/orchestrator/src/monitoring/alerts.ts new file mode 100644 index 0000000..96fd5be --- /dev/null +++ b/packages/orchestrator/src/monitoring/alerts.ts @@ -0,0 +1,268 @@ +import { PrismaClient } from '@prisma/client'; +import axios from 'axios'; +import { config, integrations } from '../utils/config'; +import { log } from './logger'; + +export type AlertType = + | 'WORKFLOW_FAILED' + | 'WORKFLOW_COMPLETED' + | 'REVENUE_MILESTONE' + | 'DECISION_EXECUTED' + | 'API_ERROR' + | 'BUDGET_THRESHOLD' + | 'SYSTEM_ERROR'; + +export type AlertSeverity = 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL'; + +export interface AlertData { + type: AlertType; + severity: AlertSeverity; + title: string; + message: string; + businessId?: string; + metadata?: Record; +} + +export class AlertSystem { + constructor(private db: PrismaClient) {} + + /** + * Send an alert through all configured channels + */ + async sendAlert(data: AlertData): Promise { + // Store alert in database + await this.db.alert.create({ + data: { + businessId: data.businessId, + type: data.type, + severity: data.severity, + title: data.title, + message: data.message, + metadata: data.metadata || {}, + }, + }); + + // Log the alert + log.info(`Alert: ${data.title}`, { ...data }); + + // Send to external channels based on severity + if (data.severity === 'CRITICAL' || data.severity === 'ERROR') { + await this.sendToSlack(data); + await this.sendEmail(data); + } else if (data.severity === 'WARNING') { + await this.sendToSlack(data); + } + } + + /** + * Send alert to Slack + */ + private async sendToSlack(data: AlertData): Promise { + if (!integrations.hasSlack()) return; + + const color = this.getSeverityColor(data.severity); + const emoji = this.getSeverityEmoji(data.severity); + + try { + await axios.post(config.notifications.slackWebhook!, { + text: `${emoji} *${data.title}*`, + attachments: [ + { + color, + fields: [ + { + title: 'Type', + value: data.type, + short: true, + }, + { + title: 'Severity', + value: data.severity, + short: true, + }, + ...(data.businessId + ? [ + { + title: 'Business ID', + value: data.businessId, + short: true, + }, + ] + : []), + { + title: 'Message', + value: data.message, + short: false, + }, + ], + footer: 'Self-Replicating Business System', + ts: Math.floor(Date.now() / 1000), + }, + ], + }); + } catch (error) { + log.error('Failed to send Slack alert', error); + } + } + + /** + * Send alert via email + */ + private async sendEmail(data: AlertData): Promise { + if (!integrations.hasSendgrid() || !config.notifications.alertEmail) return; + + try { + const sgMail = require('@sendgrid/mail'); + sgMail.setApiKey(config.sendgrid.apiKey); + + await sgMail.send({ + to: config.notifications.alertEmail, + from: config.sendgrid.fromEmail!, + subject: `[${data.severity}] ${data.title}`, + text: ` +${data.title} + +Type: ${data.type} +Severity: ${data.severity} +${data.businessId ? `Business ID: ${data.businessId}` : ''} + +Message: +${data.message} + +${data.metadata ? `Additional Info:\n${JSON.stringify(data.metadata, null, 2)}` : ''} + +--- +Self-Replicating Business System + `.trim(), + html: ` +

${data.title}

+

Type: ${data.type}

+

Severity: ${data.severity}

+${data.businessId ? `

Business ID: ${data.businessId}

` : ''} +

Message:

+

${data.message.replace(/\n/g, '
')}

+${data.metadata ? `

Additional Information:

${JSON.stringify(data.metadata, null, 2)}
` : ''} +
+

Self-Replicating Business System

+ `, + }); + } catch (error) { + log.error('Failed to send email alert', error); + } + } + + /** + * Get color for severity level + */ + private getSeverityColor(severity: AlertSeverity): string { + switch (severity) { + case 'CRITICAL': + return '#dc2626'; // red-600 + case 'ERROR': + return '#ea580c'; // orange-600 + case 'WARNING': + return '#ca8a04'; // yellow-600 + case 'INFO': + return '#2563eb'; // blue-600 + } + } + + /** + * Get emoji for severity level + */ + private getSeverityEmoji(severity: AlertSeverity): string { + switch (severity) { + case 'CRITICAL': + return '🚨'; + case 'ERROR': + return '❌'; + case 'WARNING': + return '⚠️'; + case 'INFO': + return 'ℹ️'; + } + } + + /** + * Predefined alert templates + */ + async workflowFailed(businessId: string, workflowType: string, error: string): Promise { + await this.sendAlert({ + type: 'WORKFLOW_FAILED', + severity: 'ERROR', + title: `Workflow Failed: ${workflowType}`, + message: `The ${workflowType} workflow failed for business ${businessId}.\n\nError: ${error}`, + businessId, + metadata: { workflowType, error }, + }); + } + + async workflowCompleted(businessId: string, workflowType: string): Promise { + await this.sendAlert({ + type: 'WORKFLOW_COMPLETED', + severity: 'INFO', + title: `Workflow Completed: ${workflowType}`, + message: `The ${workflowType} workflow completed successfully for business ${businessId}.`, + businessId, + metadata: { workflowType }, + }); + } + + async revenueMilestone(businessId: string, milestone: number, businessName: string): Promise { + await this.sendAlert({ + type: 'REVENUE_MILESTONE', + severity: 'INFO', + title: `Revenue Milestone Reached: $${milestone.toLocaleString()}`, + message: `🎉 Business "${businessName}" has reached $${milestone.toLocaleString()} in monthly revenue!`, + businessId, + metadata: { milestone, businessName }, + }); + } + + async decisionExecuted( + businessId: string, + decisionType: string, + action: string, + businessName: string + ): Promise { + await this.sendAlert({ + type: 'DECISION_EXECUTED', + severity: 'WARNING', + title: `Autonomous Decision: ${decisionType}`, + message: `The system made an autonomous decision for "${businessName}".\n\nDecision: ${decisionType}\nAction: ${action}`, + businessId, + metadata: { decisionType, action, businessName }, + }); + } + + async budgetThreshold(businessId: string, spent: number, limit: number): Promise { + await this.sendAlert({ + type: 'BUDGET_THRESHOLD', + severity: 'WARNING', + title: 'Budget Threshold Reached', + message: `Business ${businessId} has spent $${spent.toLocaleString()} of the $${limit.toLocaleString()} budget limit.`, + businessId, + metadata: { spent, limit, percentage: (spent / limit) * 100 }, + }); + } + + async apiError(service: string, error: string): Promise { + await this.sendAlert({ + type: 'API_ERROR', + severity: 'ERROR', + title: `API Error: ${service}`, + message: `Failed to communicate with ${service} API.\n\nError: ${error}`, + metadata: { service, error }, + }); + } + + async systemError(error: string, stack?: string): Promise { + await this.sendAlert({ + type: 'SYSTEM_ERROR', + severity: 'CRITICAL', + title: 'System Error', + message: `A critical system error occurred.\n\nError: ${error}`, + metadata: { error, stack }, + }); + } +} diff --git a/packages/orchestrator/src/monitoring/logger.ts b/packages/orchestrator/src/monitoring/logger.ts new file mode 100644 index 0000000..e57219f --- /dev/null +++ b/packages/orchestrator/src/monitoring/logger.ts @@ -0,0 +1,163 @@ +import winston from 'winston'; +import { config } from '../utils/config'; + +// Custom format for structured logging +const customFormat = winston.format.combine( + winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), + winston.format.errors({ stack: true }), + winston.format.splat(), + winston.format.json() +); + +// Console format for development +const consoleFormat = winston.format.combine( + winston.format.colorize(), + winston.format.timestamp({ format: 'HH:mm:ss' }), + winston.format.printf(({ timestamp, level, message, businessId, workflowType, ...meta }) => { + let logMessage = `${timestamp} [${level}]`; + + if (businessId) { + logMessage += ` [Business: ${businessId}]`; + } + + if (workflowType) { + logMessage += ` [Workflow: ${workflowType}]`; + } + + logMessage += `: ${message}`; + + // Add metadata if present + const metaStr = Object.keys(meta).length > 0 ? JSON.stringify(meta, null, 2) : ''; + if (metaStr) { + logMessage += `\n${metaStr}`; + } + + return logMessage; + }) +); + +// Create logger instance +const logger = winston.createLogger({ + level: config.app.logLevel, + format: customFormat, + defaultMeta: { service: 'srb-orchestrator' }, + transports: [ + // Write all logs to console + new winston.transports.Console({ + format: config.app.nodeEnv === 'production' ? customFormat : consoleFormat, + }), + // Write all logs to combined.log + new winston.transports.File({ + filename: 'logs/combined.log', + maxsize: 5242880, // 5MB + maxFiles: 5, + }), + // Write errors to error.log + new winston.transports.File({ + filename: 'logs/error.log', + level: 'error', + maxsize: 5242880, + maxFiles: 5, + }), + ], +}); + +// Create logs directory if it doesn't exist +import fs from 'fs'; +import path from 'path'; +const logsDir = path.resolve(__dirname, '../../../../logs'); +if (!fs.existsSync(logsDir)) { + fs.mkdirSync(logsDir, { recursive: true }); +} + +// Helper functions for structured logging +export const log = { + info: (message: string, meta?: Record) => { + logger.info(message, meta); + }, + + error: (message: string, error?: Error | unknown, meta?: Record) => { + logger.error(message, { + ...meta, + error: error instanceof Error ? { + message: error.message, + stack: error.stack, + name: error.name, + } : error + }); + }, + + warn: (message: string, meta?: Record) => { + logger.warn(message, meta); + }, + + debug: (message: string, meta?: Record) => { + logger.debug(message, meta); + }, + + // Business-specific logging + business: { + created: (businessId: string, name: string, idea: string) => { + logger.info('Business created', { businessId, name, ideaPreview: idea.substring(0, 100) }); + }, + + statusChanged: (businessId: string, oldStatus: string, newStatus: string) => { + logger.info('Business status changed', { businessId, oldStatus, newStatus }); + }, + + revenueUpdated: (businessId: string, oldRevenue: number, newRevenue: number) => { + logger.info('Business revenue updated', { businessId, oldRevenue, newRevenue }); + }, + }, + + // Workflow-specific logging + workflow: { + started: (workflowType: string, businessId: string, attempt: number = 1) => { + logger.info('Workflow started', { workflowType, businessId, attempt }); + }, + + completed: (workflowType: string, businessId: string, duration: number) => { + logger.info('Workflow completed', { workflowType, businessId, duration }); + }, + + failed: (workflowType: string, businessId: string, error: Error, attempt: number) => { + logger.error('Workflow failed', error, { workflowType, businessId, attempt }); + }, + + retrying: (workflowType: string, businessId: string, attempt: number, maxRetries: number) => { + logger.warn('Workflow retrying', { workflowType, businessId, attempt, maxRetries }); + }, + }, + + // Decision-specific logging + decision: { + evaluated: (businessId: string, decisionType: string, reasoning: string) => { + logger.info('Decision evaluated', { businessId, decisionType, reasoning }); + }, + + executed: (businessId: string, decisionType: string, action: string) => { + logger.info('Decision executed', { businessId, decisionType, action }); + }, + + failed: (businessId: string, decisionType: string, error: Error) => { + logger.error('Decision execution failed', error, { businessId, decisionType }); + }, + }, + + // Campaign-specific logging + campaign: { + created: (businessId: string, platform: string, budget: number) => { + logger.info('Campaign created', { businessId, platform, budget }); + }, + + updated: (campaignId: string, metrics: Record) => { + logger.info('Campaign metrics updated', { campaignId, ...metrics }); + }, + + paused: (campaignId: string, reason: string) => { + logger.info('Campaign paused', { campaignId, reason }); + }, + }, +}; + +export default logger; diff --git a/packages/orchestrator/src/monitoring/metrics.ts b/packages/orchestrator/src/monitoring/metrics.ts new file mode 100644 index 0000000..6aef3de --- /dev/null +++ b/packages/orchestrator/src/monitoring/metrics.ts @@ -0,0 +1,224 @@ +import { PrismaClient } from '@prisma/client'; +import { differenceInMonths, subMonths } from 'date-fns'; + +export class MetricsCollector { + constructor(private db: PrismaClient) {} + + /** + * Record a metric snapshot for a business + */ + async recordMetric(businessId: string, data: { + revenue?: number; + adSpend?: number; + visitors?: number; + conversions?: number; + pageViews?: number; + bounceRate?: number; + avgSessionDuration?: number; + sourceBreakdown?: Record; + }): Promise { + const revenue = data.revenue || 0; + const adSpend = data.adSpend || 0; + const profit = revenue - adSpend; + const roas = adSpend > 0 ? revenue / adSpend : null; + const conversionRate = data.visitors && data.conversions + ? (data.conversions / data.visitors) * 100 + : null; + + await this.db.metric.create({ + data: { + businessId, + revenue, + adSpend, + profit, + roas, + visitors: data.visitors || 0, + pageViews: data.pageViews || 0, + bounceRate: data.bounceRate, + avgSessionDuration: data.avgSessionDuration, + conversions: data.conversions || 0, + conversionRate, + sourceBreakdown: data.sourceBreakdown || {}, + }, + }); + + // Update business revenue + await this.updateBusinessRevenue(businessId); + } + + /** + * Calculate and update business monthly and total revenue + */ + private async updateBusinessRevenue(businessId: string): Promise { + const now = new Date(); + const oneMonthAgo = subMonths(now, 1); + + // Get total revenue + const totalRevenue = await this.db.metric.aggregate({ + where: { businessId }, + _sum: { revenue: true }, + }); + + // Get monthly revenue (last 30 days) + const monthlyRevenue = await this.db.metric.aggregate({ + where: { + businessId, + timestamp: { gte: oneMonthAgo }, + }, + _sum: { revenue: true }, + }); + + await this.db.business.update({ + where: { id: businessId }, + data: { + totalRevenue: totalRevenue._sum.revenue || 0, + monthlyRevenue: monthlyRevenue._sum.revenue || 0, + }, + }); + } + + /** + * Get comprehensive business metrics + */ + async getBusinessMetrics(businessId: string): Promise<{ + totalRevenue: number; + monthlyRevenue: number; + totalAdSpend: number; + monthlyAdSpend: number; + averageRoas: number; + totalConversions: number; + totalVisitors: number; + conversionRate: number; + profitMargin: number; + recentMetrics: any[]; + }> { + const oneMonthAgo = subMonths(new Date(), 1); + + // Total metrics + const totalMetrics = await this.db.metric.aggregate({ + where: { businessId }, + _sum: { + revenue: true, + adSpend: true, + conversions: true, + visitors: true, + }, + _avg: { + roas: true, + }, + }); + + // Monthly metrics + const monthlyMetrics = await this.db.metric.aggregate({ + where: { + businessId, + timestamp: { gte: oneMonthAgo }, + }, + _sum: { + revenue: true, + adSpend: true, + }, + }); + + // Recent metrics (last 7 days) + const recentMetrics = await this.db.metric.findMany({ + where: { + businessId, + timestamp: { gte: subMonths(new Date(), 0.25) }, // ~7 days + }, + orderBy: { timestamp: 'desc' }, + take: 30, + }); + + const totalRevenue = totalMetrics._sum.revenue || 0; + const totalAdSpend = totalMetrics._sum.adSpend || 0; + const totalConversions = totalMetrics._sum.conversions || 0; + const totalVisitors = totalMetrics._sum.visitors || 0; + + return { + totalRevenue, + monthlyRevenue: monthlyMetrics._sum.revenue || 0, + totalAdSpend, + monthlyAdSpend: monthlyMetrics._sum.adSpend || 0, + averageRoas: totalMetrics._avg.roas || 0, + totalConversions, + totalVisitors, + conversionRate: totalVisitors > 0 ? (totalConversions / totalVisitors) * 100 : 0, + profitMargin: totalRevenue > 0 ? ((totalRevenue - totalAdSpend) / totalRevenue) * 100 : 0, + recentMetrics, + }; + } + + /** + * Get campaign performance metrics + */ + async getCampaignMetrics(businessId: string): Promise { + const campaigns = await this.db.campaign.findMany({ + where: { businessId }, + select: { + id: true, + platform: true, + name: true, + budget: true, + active: true, + impressions: true, + clicks: true, + conversions: true, + spend: true, + revenue: true, + createdAt: true, + }, + }); + + return campaigns.map(campaign => ({ + ...campaign, + ctr: campaign.impressions > 0 ? (campaign.clicks / campaign.impressions) * 100 : 0, + conversionRate: campaign.clicks > 0 ? (campaign.conversions / campaign.clicks) * 100 : 0, + roas: campaign.spend > 0 ? campaign.revenue / campaign.spend : 0, + cpc: campaign.clicks > 0 ? campaign.spend / campaign.clicks : 0, + cpa: campaign.conversions > 0 ? campaign.spend / campaign.conversions : 0, + })); + } + + /** + * Get business health score (0-100) + */ + async getHealthScore(businessId: string): Promise { + const business = await this.db.business.findUnique({ + where: { id: businessId }, + include: { campaigns: true, metrics: { take: 30, orderBy: { timestamp: 'desc' } } }, + }); + + if (!business) return 0; + + let score = 0; + + // Revenue score (40 points max) + if (business.monthlyRevenue >= 50000) score += 40; + else if (business.monthlyRevenue >= 10000) score += 30; + else if (business.monthlyRevenue >= 1000) score += 20; + else if (business.monthlyRevenue >= 100) score += 10; + + // Active campaigns (20 points max) + const activeCampaigns = business.campaigns.filter(c => c.active).length; + score += Math.min(activeCampaigns * 10, 20); + + // SEO optimized (10 points) + if (business.seoOptimized) score += 10; + + // Email automation (10 points) + if (business.emailAutomation) score += 10; + + // Revenue trend (20 points max) + if (business.metrics.length >= 7) { + const recentRevenue = business.metrics.slice(0, 7).reduce((sum, m) => sum + m.revenue, 0) / 7; + const olderRevenue = business.metrics.slice(7, 14).reduce((sum, m) => sum + m.revenue, 0) / 7; + + if (recentRevenue > olderRevenue * 1.2) score += 20; // Growing + else if (recentRevenue > olderRevenue) score += 10; // Stable growth + else if (recentRevenue < olderRevenue * 0.8) score -= 10; // Declining + } + + return Math.max(0, Math.min(100, score)); + } +} diff --git a/packages/orchestrator/src/orchestrator.ts b/packages/orchestrator/src/orchestrator.ts new file mode 100644 index 0000000..d5934b9 --- /dev/null +++ b/packages/orchestrator/src/orchestrator.ts @@ -0,0 +1,308 @@ +import { PrismaClient } from '@prisma/client'; +import { WorkflowExecutor } from './workflows/workflow-executor'; +import { DecisionEngine } from './decision-engine/rules'; +import { AlertSystem } from './monitoring/alerts'; +import { MetricsCollector } from './monitoring/metrics'; +import { log } from './monitoring/logger'; +import { config } from './utils/config'; +import { businessInputSchema, validateBusinessIdea } from './utils/validators'; + +export class MetaOrchestrator { + private db: PrismaClient; + private workflowExecutor: WorkflowExecutor; + private decisionEngine: DecisionEngine; + private alerts: AlertSystem; + private metrics: MetricsCollector; + private isRunning: boolean = false; + + constructor() { + this.db = new PrismaClient(); + this.alerts = new AlertSystem(this.db); + this.metrics = new MetricsCollector(this.db); + this.workflowExecutor = new WorkflowExecutor(this.db, this.alerts); + this.decisionEngine = new DecisionEngine(this.db, this.alerts, this.metrics); + } + + /** + * Initialize the orchestrator + */ + async initialize(): Promise { + try { + log.info('Initializing MetaOrchestrator...'); + + // Test database connection + await this.db.$connect(); + log.info('Database connected'); + + // Start background processes + this.startBackgroundProcesses(); + + this.isRunning = true; + log.info('MetaOrchestrator initialized successfully'); + } catch (error) { + log.error('Failed to initialize MetaOrchestrator', error); + throw error; + } + } + + /** + * Create a new business and start its lifecycle + */ + async createBusiness(input: { + name: string; + idea: string; + targetAudience?: string; + budget?: number; + }): Promise<{ id: string; name: string }> { + try { + // Validate input + const validated = businessInputSchema.parse(input); + + // Validate business idea quality + const ideaValidation = validateBusinessIdea(validated.idea); + if (!ideaValidation.valid) { + throw new Error(`Invalid business idea: ${ideaValidation.issues.join(', ')}`); + } + + // Create business record + const business = await this.db.business.create({ + data: { + name: validated.name, + idea: validated.idea, + targetAudience: validated.targetAudience, + budget: validated.budget, + status: 'VALIDATING', + }, + }); + + log.business.created(business.id, business.name, business.idea); + + // Start lifecycle in background (non-blocking) + this.executeBusinessLifecycle(business.id).catch((error) => { + log.error('Business lifecycle execution failed', error, { businessId: business.id }); + }); + + return { + id: business.id, + name: business.name, + }; + } catch (error) { + log.error('Failed to create business', error); + throw error; + } + } + + /** + * Execute the complete business lifecycle + */ + async executeBusinessLifecycle(businessId: string): Promise { + try { + log.info('Starting business lifecycle', { businessId }); + + // PHASE 1: Market Validation (Sequential) + log.info('Phase 1: Market Validation', { businessId }); + const validationResult = await this.workflowExecutor.run(businessId, 'MARKET_VALIDATION'); + + if (!validationResult.success || !validationResult.data?.viable) { + log.info('Business validation failed - shutting down', { businessId }); + await this.shutdown(businessId, 'Market validation failed: not viable'); + return; + } + + // PHASE 2: MVP Development (Sequential) + log.info('Phase 2: MVP Development', { businessId }); + const mvpResult = await this.workflowExecutor.run(businessId, 'MVP_DEVELOPMENT'); + + if (!mvpResult.success) { + log.error('MVP development failed', undefined, { businessId }); + await this.shutdown(businessId, 'MVP development failed'); + return; + } + + // PHASE 3: Marketing Setup (Parallel) + log.info('Phase 3: Marketing Setup (parallel workflows)', { businessId }); + const marketingResults = await this.workflowExecutor.runParallel(businessId, [ + 'LANDING_PAGE_SEO', + 'PAID_ADS', + 'CONTENT_MARKETING', + 'EMAIL_AUTOMATION', + 'ANALYTICS_SETUP', + ]); + + // Check if any critical marketing workflows failed + const failures = marketingResults.filter((r) => !r.success); + if (failures.length > 0) { + log.warn('Some marketing workflows failed', { + businessId, + failureCount: failures.length, + }); + // Continue anyway - marketing workflows are not critical + } + + // Update business status + await this.db.business.update({ + where: { id: businessId }, + data: { status: 'OPTIMIZING' }, + }); + + // PHASE 4: Continuous Optimization Loop (Forever) + log.info('Phase 4: Starting continuous optimization', { businessId }); + + // This runs forever until business is shutdown/paused + await this.workflowExecutor.runForever( + businessId, + 'OPTIMIZATION_LOOP', + config.app.optimizationIntervalMinutes + ); + + log.info('Business lifecycle completed', { businessId }); + } catch (error) { + log.error('Business lifecycle error', error, { businessId }); + await this.alerts.systemError( + `Business lifecycle failed for ${businessId}`, + error instanceof Error ? error.stack : undefined + ); + } + } + + /** + * Shutdown a business + */ + async shutdown(businessId: string, reason: string): Promise { + log.info('Shutting down business', { businessId, reason }); + + // Pause all campaigns + await this.db.campaign.updateMany({ + where: { businessId }, + data: { active: false }, + }); + + // Update business status + await this.db.business.update({ + where: { id: businessId }, + data: { status: 'SHUTDOWN' }, + }); + + // Send alert + const business = await this.db.business.findUnique({ + where: { id: businessId }, + }); + + if (business) { + await this.alerts.sendAlert({ + type: 'DECISION_EXECUTED', + severity: 'WARNING', + title: 'Business Shutdown', + message: `Business "${business.name}" has been shut down.\n\nReason: ${reason}`, + businessId, + metadata: { reason }, + }); + } + + log.info('Business shutdown complete', { businessId }); + } + + /** + * Start background processes (decision evaluation) + */ + private startBackgroundProcesses(): void { + // Run decision evaluation periodically + setInterval(async () => { + try { + await this.evaluateAllBusinessDecisions(); + } catch (error) { + log.error('Decision evaluation error', error); + } + }, config.app.decisionEvaluationIntervalMinutes * 60 * 1000); + + log.info('Background processes started', { + decisionEvaluationInterval: config.app.decisionEvaluationIntervalMinutes, + }); + } + + /** + * Evaluate decisions for all active businesses + */ + private async evaluateAllBusinessDecisions(): Promise { + const activeBusinesses = await this.db.business.findMany({ + where: { + status: { + in: ['RUNNING_ADS', 'OPTIMIZING', 'SCALING'], + }, + }, + }); + + log.info(`Evaluating decisions for ${activeBusinesses.length} businesses`); + + for (const business of activeBusinesses) { + try { + await this.decisionEngine.evaluateBusinessDaily(business.id); + } catch (error) { + log.error('Failed to evaluate business decisions', error, { + businessId: business.id, + }); + } + } + } + + /** + * Get business status + */ + async getBusinessStatus(businessId: string) { + const business = await this.db.business.findUnique({ + where: { id: businessId }, + include: { + workflows: { + orderBy: { createdAt: 'desc' }, + take: 10, + }, + campaigns: true, + decisions: { + orderBy: { createdAt: 'desc' }, + take: 5, + }, + }, + }); + + if (!business) { + throw new Error('Business not found'); + } + + const metrics = await this.metrics.getBusinessMetrics(businessId); + const healthScore = await this.metrics.getHealthScore(businessId); + + return { + ...business, + metrics, + healthScore, + }; + } + + /** + * List all businesses + */ + async listBusinesses() { + return await this.db.business.findMany({ + orderBy: { createdAt: 'desc' }, + include: { + _count: { + select: { + workflows: true, + campaigns: true, + decisions: true, + }, + }, + }, + }); + } + + /** + * Graceful shutdown + */ + async close(): Promise { + log.info('Shutting down MetaOrchestrator...'); + this.isRunning = false; + await this.db.$disconnect(); + log.info('MetaOrchestrator shutdown complete'); + } +} diff --git a/packages/orchestrator/src/utils/config.ts b/packages/orchestrator/src/utils/config.ts new file mode 100644 index 0000000..882cfa1 --- /dev/null +++ b/packages/orchestrator/src/utils/config.ts @@ -0,0 +1,208 @@ +import { config as loadEnv } from 'dotenv'; +import { z } from 'zod'; +import path from 'path'; + +// Load .env file from project root +loadEnv({ path: path.resolve(__dirname, '../../../..', '.env') }); + +// Configuration schema with validation +const configSchema = z.object({ + // Database + database: z.object({ + url: z.string().url(), + }), + redis: z.object({ + url: z.string().url(), + }), + + // Claude API + claude: z.object({ + apiKey: z.string().min(1, 'Claude API key is required'), + }), + + // Facebook Ads (optional for now) + facebook: z.object({ + appId: z.string().optional(), + appSecret: z.string().optional(), + accessToken: z.string().optional(), + adAccountId: z.string().optional(), + }), + + // Google Ads (optional for now) + googleAds: z.object({ + clientId: z.string().optional(), + clientSecret: z.string().optional(), + refreshToken: z.string().optional(), + developerToken: z.string().optional(), + customerId: z.string().optional(), + }), + + // Email + sendgrid: z.object({ + apiKey: z.string().optional(), + fromEmail: z.string().email().optional(), + fromName: z.string().optional(), + }), + + // Google Analytics (optional) + googleAnalytics: z.object({ + propertyId: z.string().optional(), + measurementId: z.string().optional(), + }), + + // Vercel (optional) + vercel: z.object({ + token: z.string().optional(), + orgId: z.string().optional(), + projectId: z.string().optional(), + }), + + // Marketplaces + acquire: z.object({ + apiKey: z.string().optional(), + }), + upwork: z.object({ + apiKey: z.string().optional(), + apiSecret: z.string().optional(), + accessToken: z.string().optional(), + }), + + // Decision thresholds + thresholds: z.object({ + scaleRevenue: z.number().positive(), + sellRevenue: z.number().positive(), + shutdownRevenue: z.number().positive(), + shutdownWaitMonths: z.number().int().positive(), + }), + + // Budget limits + budgetLimits: z.object({ + maxAdSpendPerBusiness: z.number().positive(), + maxValidationBudget: z.number().positive(), + maxMvpBudget: z.number().positive(), + }), + + // Notifications + notifications: z.object({ + slackWebhook: z.string().url().optional(), + alertEmail: z.string().email().optional(), + }), + + // Google Search (for market validation) + googleSearch: z.object({ + apiKey: z.string().optional(), + engineId: z.string().optional(), + }), + + // Application + app: z.object({ + nodeEnv: z.enum(['development', 'production', 'test']), + port: z.number().int().positive(), + logLevel: z.enum(['debug', 'info', 'warn', 'error']), + optimizationIntervalMinutes: z.number().int().positive(), + decisionEvaluationIntervalMinutes: z.number().int().positive(), + }), +}); + +export type Config = z.infer; + +// Parse and validate configuration +function loadConfig(): Config { + const config: Config = { + database: { + url: process.env.DATABASE_URL || 'postgresql://srb:srb_password@localhost:5432/srb', + }, + redis: { + url: process.env.REDIS_URL || 'redis://localhost:6379', + }, + claude: { + apiKey: process.env.ANTHROPIC_API_KEY || '', + }, + facebook: { + appId: process.env.FACEBOOK_APP_ID, + appSecret: process.env.FACEBOOK_APP_SECRET, + accessToken: process.env.FACEBOOK_ACCESS_TOKEN, + adAccountId: process.env.FACEBOOK_AD_ACCOUNT_ID, + }, + googleAds: { + clientId: process.env.GOOGLE_ADS_CLIENT_ID, + clientSecret: process.env.GOOGLE_ADS_CLIENT_SECRET, + refreshToken: process.env.GOOGLE_ADS_REFRESH_TOKEN, + developerToken: process.env.GOOGLE_ADS_DEVELOPER_TOKEN, + customerId: process.env.GOOGLE_ADS_CUSTOMER_ID, + }, + sendgrid: { + apiKey: process.env.SENDGRID_API_KEY, + fromEmail: process.env.SENDGRID_FROM_EMAIL, + fromName: process.env.SENDGRID_FROM_NAME, + }, + googleAnalytics: { + propertyId: process.env.GOOGLE_ANALYTICS_PROPERTY_ID, + measurementId: process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID, + }, + vercel: { + token: process.env.VERCEL_TOKEN, + orgId: process.env.VERCEL_ORG_ID, + projectId: process.env.VERCEL_PROJECT_ID, + }, + acquire: { + apiKey: process.env.ACQUIRE_COM_API_KEY, + }, + upwork: { + apiKey: process.env.UPWORK_API_KEY, + apiSecret: process.env.UPWORK_API_SECRET, + accessToken: process.env.UPWORK_ACCESS_TOKEN, + }, + thresholds: { + scaleRevenue: Number(process.env.REVENUE_SCALE_THRESHOLD) || 10000, + sellRevenue: Number(process.env.REVENUE_SELL_THRESHOLD) || 50000, + shutdownRevenue: Number(process.env.REVENUE_SHUTDOWN_THRESHOLD) || 1000, + shutdownWaitMonths: Number(process.env.SHUTDOWN_WAIT_MONTHS) || 6, + }, + budgetLimits: { + maxAdSpendPerBusiness: Number(process.env.MAX_AD_SPEND_PER_BUSINESS) || 5000, + maxValidationBudget: Number(process.env.MAX_VALIDATION_BUDGET) || 100, + maxMvpBudget: Number(process.env.MAX_MVP_BUDGET) || 500, + }, + notifications: { + slackWebhook: process.env.SLACK_WEBHOOK_URL, + alertEmail: process.env.ALERT_EMAIL, + }, + googleSearch: { + apiKey: process.env.GOOGLE_SEARCH_API_KEY, + engineId: process.env.GOOGLE_SEARCH_ENGINE_ID, + }, + app: { + nodeEnv: (process.env.NODE_ENV as any) || 'development', + port: Number(process.env.PORT) || 3000, + logLevel: (process.env.LOG_LEVEL as any) || 'info', + optimizationIntervalMinutes: Number(process.env.OPTIMIZATION_INTERVAL_MINUTES) || 1440, + decisionEvaluationIntervalMinutes: Number(process.env.DECISION_EVALUATION_INTERVAL_MINUTES) || 1440, + }, + }; + + // Validate configuration + const result = configSchema.safeParse(config); + + if (!result.success) { + console.error('Configuration validation failed:'); + console.error(result.error.format()); + throw new Error('Invalid configuration. Check your .env file.'); + } + + return result.data; +} + +export const config = loadConfig(); + +// Helper to check if optional integrations are configured +export const integrations = { + hasFacebookAds: () => Boolean(config.facebook.accessToken), + hasGoogleAds: () => Boolean(config.googleAds.refreshToken), + hasSendgrid: () => Boolean(config.sendgrid.apiKey), + hasVercel: () => Boolean(config.vercel.token), + hasAcquire: () => Boolean(config.acquire.apiKey), + hasUpwork: () => Boolean(config.upwork.apiKey), + hasGoogleSearch: () => Boolean(config.googleSearch.apiKey), + hasSlack: () => Boolean(config.notifications.slackWebhook), +}; diff --git a/packages/orchestrator/src/utils/validators.ts b/packages/orchestrator/src/utils/validators.ts new file mode 100644 index 0000000..7c76fc6 --- /dev/null +++ b/packages/orchestrator/src/utils/validators.ts @@ -0,0 +1,68 @@ +import { z } from 'zod'; + +// Business input validation +export const businessInputSchema = z.object({ + name: z.string().min(3, 'Business name must be at least 3 characters').max(100), + idea: z.string().min(10, 'Business idea must be at least 10 characters').max(5000), + targetAudience: z.string().optional(), + budget: z.number().positive().optional(), +}); + +export type BusinessInput = z.infer; + +// Campaign validation +export const campaignInputSchema = z.object({ + platform: z.enum(['FACEBOOK', 'GOOGLE']), + budget: z.number().positive(), + dailyBudget: z.number().positive().optional(), + targeting: z.record(z.any()).optional(), + creative: z.record(z.any()).optional(), +}); + +export type CampaignInput = z.infer; + +// URL validation +export function isValidUrl(url: string): boolean { + try { + new URL(url); + return true; + } catch { + return false; + } +} + +// Email validation +export function isValidEmail(email: string): boolean { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); +} + +// Revenue validation +export function isValidRevenue(revenue: number): boolean { + return revenue >= 0 && Number.isFinite(revenue); +} + +// Validate business idea quality +export function validateBusinessIdea(idea: string): { valid: boolean; issues: string[] } { + const issues: string[] = []; + + if (idea.length < 10) { + issues.push('Business idea is too short (minimum 10 characters)'); + } + + if (idea.length > 5000) { + issues.push('Business idea is too long (maximum 5000 characters)'); + } + + // Check for common spam/test patterns + const spamPatterns = ['test', 'asdf', '123', 'sample']; + const lowerIdea = idea.toLowerCase(); + if (spamPatterns.some(pattern => lowerIdea === pattern)) { + issues.push('Business idea appears to be a test/spam input'); + } + + return { + valid: issues.length === 0, + issues, + }; +} diff --git a/packages/orchestrator/src/workflows/01-market-validation.ts b/packages/orchestrator/src/workflows/01-market-validation.ts new file mode 100644 index 0000000..c8ac50e --- /dev/null +++ b/packages/orchestrator/src/workflows/01-market-validation.ts @@ -0,0 +1,280 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { ClaudeClient } from '../integrations/claude/claude-client'; +import { log } from '../monitoring/logger'; +import axios from 'axios'; +import * as cheerio from 'cheerio'; +import { config, integrations } from '../utils/config'; + +export class MarketValidationWorkflow extends WorkflowBase { + protected type: WorkflowType = 'MARKET_VALIDATION'; + private claude: ClaudeClient; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.claude = new ClaudeClient(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Starting market validation', { + businessId: context.businessId, + businessName: business.name, + }); + + try { + // Step 1: Search for competitors + const competitors = await this.searchCompetitors(business.idea); + + // Step 2: Analyze market demand + const demandData = await this.analyzeDemand(business.idea, business.name); + + // Step 3: Get Claude's viability analysis + const analysis = await this.claude.analyzeBusinessIdea( + business.idea, + competitors, + demandData + ); + + // Step 4: Store validation results + await this.db.business.update({ + where: { id: context.businessId }, + data: { + viable: analysis.viable, + validationResult: { + score: analysis.score, + analysis: analysis.analysis, + risks: analysis.risks, + opportunities: analysis.opportunities, + competitors, + demandData, + validatedAt: new Date().toISOString(), + }, + status: analysis.viable ? 'DEVELOPING_MVP' : 'VALIDATION_FAILED', + }, + }); + + if (analysis.viable) { + log.info('Market validation passed', { + businessId: context.businessId, + score: analysis.score, + }); + } else { + log.warn('Market validation failed', { + businessId: context.businessId, + score: analysis.score, + risks: analysis.risks, + }); + } + + return { + success: true, + data: { + viable: analysis.viable, + score: analysis.score, + competitors: competitors.length, + analysis: analysis.analysis, + }, + }; + } catch (error) { + log.error('Market validation error', error, { businessId: context.businessId }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + /** + * Search for competitors using web search + */ + private async searchCompetitors(idea: string): Promise { + try { + // Extract key terms from the idea for search + const searchQuery = this.extractSearchTerms(idea); + + // Use Google Custom Search API if available + if (integrations.hasGoogleSearch()) { + return await this.searchWithGoogleAPI(searchQuery); + } + + // Fallback: Use web scraping (less reliable but works) + return await this.searchWithScraping(searchQuery); + } catch (error) { + log.error('Competitor search failed', error); + return []; + } + } + + /** + * Search using Google Custom Search API + */ + private async searchWithGoogleAPI(query: string): Promise { + try { + const response = await axios.get( + 'https://www.googleapis.com/customsearch/v1', + { + params: { + key: config.googleSearch.apiKey, + cx: config.googleSearch.engineId, + q: query, + num: 10, + }, + } + ); + + return response.data.items?.slice(0, 5).map((item: any) => ({ + name: item.title, + url: item.link, + description: item.snippet, + strengths: [], + weaknesses: [], + })) || []; + } catch (error) { + log.error('Google Search API error', error); + return []; + } + } + + /** + * Fallback web scraping method + */ + private async searchWithScraping(query: string): Promise { + try { + // For demo purposes, return mock data + // In production, you'd implement proper web scraping + log.warn('Using fallback competitor search (mock data)'); + + return [ + { + name: 'Competitor 1', + url: 'https://example.com', + description: 'Similar product in the market', + strengths: ['Established brand', 'Large user base'], + weaknesses: ['Outdated UI', 'High pricing'], + }, + { + name: 'Competitor 2', + url: 'https://example2.com', + description: 'Another competitor', + strengths: ['Good pricing'], + weaknesses: ['Limited features'], + }, + ]; + } catch (error) { + log.error('Web scraping failed', error); + return []; + } + } + + /** + * Analyze market demand using various signals + */ + private async analyzeDemand(idea: string, businessName: string): Promise { + try { + const keywords = this.extractSearchTerms(idea); + + // Try to get Google Trends data + const trendData = await this.getGoogleTrends(keywords); + + return { + searchVolume: trendData.averageSearchVolume || 1000, + trend: trendData.trend || 'stable', + seasonality: trendData.seasonality || false, + relatedKeywords: trendData.relatedKeywords || [keywords], + confidenceLevel: trendData.confidenceLevel || 'medium', + }; + } catch (error) { + log.error('Demand analysis failed', error); + + // Return default/estimated data + return { + searchVolume: 1000, + trend: 'stable', + seasonality: false, + relatedKeywords: [this.extractSearchTerms(idea)], + confidenceLevel: 'low', + }; + } + } + + /** + * Get Google Trends data + */ + private async getGoogleTrends(keyword: string): Promise { + try { + const googleTrends = require('google-trends-api'); + + // Get interest over time + const interestOverTime = await googleTrends.interestOverTime({ + keyword, + startTime: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000), // 90 days ago + }); + + const data = JSON.parse(interestOverTime); + + // Calculate trend (rising, stable, declining) + const values = data.default.timelineData.map((d: any) => d.value[0]); + const recentAvg = values.slice(-30).reduce((a: number, b: number) => a + b, 0) / 30; + const oldAvg = values.slice(0, 30).reduce((a: number, b: number) => a + b, 0) / 30; + + let trend: 'rising' | 'stable' | 'declining' = 'stable'; + if (recentAvg > oldAvg * 1.2) trend = 'rising'; + else if (recentAvg < oldAvg * 0.8) trend = 'declining'; + + // Get related queries + const relatedQueries = await googleTrends.relatedQueries({ keyword }); + const relatedData = JSON.parse(relatedQueries); + const relatedKeywords = relatedData.default.rankedList[0]?.rankedKeyword + ?.slice(0, 5) + .map((k: any) => k.query) || []; + + return { + averageSearchVolume: Math.round(recentAvg * 100), + trend, + seasonality: this.detectSeasonality(values), + relatedKeywords, + confidenceLevel: 'high', + }; + } catch (error) { + log.warn('Google Trends API failed, using fallback', { error }); + return { + averageSearchVolume: 1000, + trend: 'stable', + seasonality: false, + relatedKeywords: [keyword], + confidenceLevel: 'low', + }; + } + } + + /** + * Detect seasonality in trend data + */ + private detectSeasonality(values: number[]): boolean { + // Simple seasonality detection: check if variance is high + const mean = values.reduce((a, b) => a + b, 0) / values.length; + const variance = + values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length; + const stdDev = Math.sqrt(variance); + + // If std dev is more than 30% of mean, consider it seasonal + return stdDev > mean * 0.3; + } + + /** + * Extract search terms from business idea + */ + private extractSearchTerms(idea: string): string { + // Simple extraction - take first few meaningful words + const words = idea + .toLowerCase() + .replace(/[^a-z0-9\s]/g, '') + .split(/\s+/) + .filter((w) => w.length > 3) + .slice(0, 5); + + return words.join(' '); + } +} diff --git a/packages/orchestrator/src/workflows/02-mvp-development.ts b/packages/orchestrator/src/workflows/02-mvp-development.ts new file mode 100644 index 0000000..5331b6a --- /dev/null +++ b/packages/orchestrator/src/workflows/02-mvp-development.ts @@ -0,0 +1,214 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { ClaudeClient } from '../integrations/claude/claude-client'; +import { VercelDeploy } from '../integrations/deploy/vercel-deploy'; +import { log } from '../monitoring/logger'; +import { integrations } from '../utils/config'; +import fs from 'fs/promises'; +import path from 'path'; + +export class MVPDevelopmentWorkflow extends WorkflowBase { + protected type: WorkflowType = 'MVP_DEVELOPMENT'; + private claude: ClaudeClient; + private vercel: VercelDeploy; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.claude = new ClaudeClient(); + this.vercel = new VercelDeploy(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Starting MVP development', { + businessId: context.businessId, + businessName: business.name, + }); + + try { + // Step 1: Generate MVP code using Claude + log.info('Generating MVP code with Claude', { businessId: context.businessId }); + const mvpGeneration = await this.claude.generateMVP(business.idea, business.name); + + if (!mvpGeneration.success || !mvpGeneration.code) { + throw new Error('Failed to generate MVP code'); + } + + log.info('MVP code generated successfully', { + businessId: context.businessId, + filesGenerated: Object.keys(mvpGeneration.code).length, + }); + + // Step 2: Save code to local directory + const projectDir = await this.saveCodeToDirectory( + context.businessId, + business.name, + mvpGeneration.code + ); + + // Step 3: Deploy to Vercel (if configured) + let deploymentUrl = null; + + if (integrations.hasVercel()) { + log.info('Deploying MVP to Vercel', { businessId: context.businessId }); + + deploymentUrl = await this.vercel.deploy({ + projectName: this.sanitizeProjectName(business.name), + projectPath: projectDir, + businessId: context.businessId, + }); + + log.info('MVP deployed successfully', { + businessId: context.businessId, + url: deploymentUrl, + }); + } else { + log.warn('Vercel not configured - MVP saved locally only', { + businessId: context.businessId, + path: projectDir, + }); + + // Generate local URL placeholder + deploymentUrl = `http://localhost:3002/${business.id}`; + } + + // Step 4: Update business with MVP URL + await this.db.business.update({ + where: { id: context.businessId }, + data: { + mvpUrl: deploymentUrl, + status: 'LAUNCHING', + }, + }); + + return { + success: true, + data: { + mvpUrl: deploymentUrl, + filesGenerated: Object.keys(mvpGeneration.code).length, + projectDir, + }, + }; + } catch (error) { + log.error('MVP development failed', error, { businessId: context.businessId }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + /** + * Save generated code to directory + */ + private async saveCodeToDirectory( + businessId: string, + businessName: string, + code: Record + ): Promise { + // Create project directory + const projectDir = path.resolve( + __dirname, + '../../../../../data/businesses', + businessId, + 'mvp' + ); + + await fs.mkdir(projectDir, { recursive: true }); + + log.info('Saving MVP code to directory', { + businessId, + path: projectDir, + fileCount: Object.keys(code).length, + }); + + // Write each file + for (const [filename, content] of Object.entries(code)) { + const filePath = path.join(projectDir, filename); + + // Create subdirectories if needed + const dir = path.dirname(filePath); + await fs.mkdir(dir, { recursive: true }); + + // Write file + await fs.writeFile(filePath, content, 'utf-8'); + + log.debug('File written', { filename, path: filePath }); + } + + // Create a README with deployment instructions + const readme = ` +# ${businessName} - MVP + +Generated automatically by Self-Replicating Business System + +## Files Generated +${Object.keys(code).map(f => `- ${f}`).join('\n')} + +## Local Development + +\`\`\`bash +npm install +npm run dev +\`\`\` + +## Deployment + +This MVP has been ${integrations.hasVercel() ? 'deployed to Vercel' : 'saved locally'}. + +${integrations.hasVercel() ? 'Check the business record for the live URL.' : 'To deploy, configure Vercel API token in .env'} + +## Business ID +${businessId} + `.trim(); + + await fs.writeFile(path.join(projectDir, 'README.md'), readme, 'utf-8'); + + return projectDir; + } + + /** + * Sanitize project name for Vercel + */ + private sanitizeProjectName(name: string): string { + return name + .toLowerCase() + .replace(/[^a-z0-9-]/g, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') + .substring(0, 100); + } + + /** + * Initialize Git repository (needed for Vercel) + */ + private async initGitRepo(projectDir: string): Promise { + const { exec } = require('child_process'); + const { promisify } = require('util'); + const execAsync = promisify(exec); + + try { + // Check if git is already initialized + try { + await execAsync('git rev-parse --git-dir', { cwd: projectDir }); + log.debug('Git already initialized', { projectDir }); + return; + } catch { + // Not initialized, continue + } + + // Initialize git + await execAsync('git init', { cwd: projectDir }); + await execAsync('git add .', { cwd: projectDir }); + await execAsync('git commit -m "Initial commit - MVP generated"', { + cwd: projectDir, + }); + + log.info('Git repository initialized', { projectDir }); + } catch (error) { + log.warn('Failed to initialize Git repo', { error, projectDir }); + // Don't fail the whole workflow for this + } + } +} diff --git a/packages/orchestrator/src/workflows/03-landing-page-seo.ts b/packages/orchestrator/src/workflows/03-landing-page-seo.ts new file mode 100644 index 0000000..e6bdae7 --- /dev/null +++ b/packages/orchestrator/src/workflows/03-landing-page-seo.ts @@ -0,0 +1,103 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { SEOExpert } from '../integrations/claude/skills/seo-expert'; +import { log } from '../monitoring/logger'; + +export class LandingPageSEOWorkflow extends WorkflowBase { + protected type: WorkflowType = 'LANDING_PAGE_SEO'; + private seoExpert: SEOExpert; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.seoExpert = new SEOExpert(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Starting landing page SEO optimization', { + businessId: context.businessId, + }); + + try { + // Step 1: Perform keyword research + const keywordResearch = await this.seoExpert.performKeywordResearch({ + businessIdea: business.idea, + seedKeywords: this.extractKeywords(business.idea), + }); + + log.info('Keyword research completed', { businessId: context.businessId }); + + // Step 2: Generate SEO strategy + const seoStrategy = await this.seoExpert.generateStrategy({ + businessName: business.name, + businessIdea: business.idea, + targetAudience: business.targetAudience || 'general audience', + competitors: [], // From validation data if available + }); + + log.info('SEO strategy generated', { businessId: context.businessId }); + + // Step 3: Optimize landing page content (if MVP exists) + let optimizedContent = null; + if (business.mvpUrl) { + optimizedContent = await this.seoExpert.optimizeLandingPage({ + businessName: business.name, + currentContent: business.idea, // Would fetch actual content in production + targetKeywords: this.extractKeywords(business.idea), + }); + + log.info('Landing page content optimized', { businessId: context.businessId }); + } + + // Step 4: Generate content ideas for future blog posts + const contentIdeas = await this.seoExpert.generateContentIdeas({ + businessIdea: business.idea, + niche: this.extractNiche(business.idea), + targetKeywords: this.extractKeywords(business.idea), + }); + + log.info('Content ideas generated', { businessId: context.businessId }); + + // Step 5: Update business record + await this.db.business.update({ + where: { id: context.businessId }, + data: { + seoOptimized: true, + }, + }); + + return { + success: true, + data: { + keywordResearch: keywordResearch.success ? keywordResearch.output : null, + seoStrategy: seoStrategy.success ? seoStrategy.output : null, + contentIdeas: contentIdeas.success ? contentIdeas.output : null, + }, + }; + } catch (error) { + log.error('Landing page SEO workflow failed', error, { + businessId: context.businessId, + }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private extractKeywords(text: string): string[] { + return text + .toLowerCase() + .replace(/[^a-z0-9\s]/g, '') + .split(/\s+/) + .filter((w) => w.length > 3) + .slice(0, 10); + } + + private extractNiche(idea: string): string { + // Simple niche extraction - first meaningful phrase + const words = idea.split(' ').slice(0, 5).join(' '); + return words; + } +} diff --git a/packages/orchestrator/src/workflows/04-paid-ads.ts b/packages/orchestrator/src/workflows/04-paid-ads.ts new file mode 100644 index 0000000..753c989 --- /dev/null +++ b/packages/orchestrator/src/workflows/04-paid-ads.ts @@ -0,0 +1,183 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { FacebookAdsExpert } from '../integrations/claude/skills/facebook-ads-expert'; +import { GoogleAdsExpert } from '../integrations/claude/skills/google-ads-expert'; +import { FacebookAdsAPI } from '../integrations/ads/facebook-ads'; +import { GoogleAdsAPI } from '../integrations/ads/google-ads'; +import { log } from '../monitoring/logger'; +import { integrations } from '../utils/config'; + +export class PaidAdsWorkflow extends WorkflowBase { + protected type: WorkflowType = 'PAID_ADS'; + private fbExpert: FacebookAdsExpert; + private googleExpert: GoogleAdsExpert; + private fbAds: FacebookAdsAPI; + private googleAds: GoogleAdsAPI; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.fbExpert = new FacebookAdsExpert(); + this.googleExpert = new GoogleAdsExpert(); + this.fbAds = new FacebookAdsAPI(); + this.googleAds = new GoogleAdsAPI(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Starting paid ads campaigns', { businessId: context.businessId }); + + const results: any = { + facebook: null, + google: null, + }; + + try { + // Step 1: Create Facebook Ads campaign + if (integrations.hasFacebookAds()) { + results.facebook = await this.createFacebookCampaign(business); + log.info('Facebook campaign created', { businessId: context.businessId }); + } else { + log.warn('Facebook Ads not configured - skipping', { + businessId: context.businessId, + }); + } + + // Step 2: Create Google Ads campaign + if (integrations.hasGoogleAds()) { + results.google = await this.createGoogleCampaign(business); + log.info('Google Ads campaign created', { businessId: context.businessId }); + } else { + log.warn('Google Ads not configured - skipping', { + businessId: context.businessId, + }); + } + + // Step 3: Update business status + await this.db.business.update({ + where: { id: context.businessId }, + data: { + adsActive: true, + status: 'RUNNING_ADS', + }, + }); + + return { + success: true, + data: results, + }; + } catch (error) { + log.error('Paid ads workflow failed', error, { businessId: context.businessId }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private async createFacebookCampaign(business: any): Promise { + try { + // Get campaign strategy from Claude + const strategy = await this.fbExpert.generateCampaignStrategy({ + businessName: business.name, + businessIdea: business.idea, + budget: business.budget || 500, + targetAudience: business.targetAudience || 'general', + goal: 'CONVERSIONS', + }); + + // Create campaign via Facebook Ads API + const campaign = await this.fbAds.createCampaign({ + name: `${business.name} - Conversions`, + objective: 'CONVERSIONS', + budget: business.budget || 500, + targeting: { + age_min: 25, + age_max: 65, + interests: [], + }, + }); + + // Save campaign to database + await this.db.campaign.create({ + data: { + businessId: business.id, + platform: 'FACEBOOK', + campaignId: campaign.id, + name: campaign.name, + budget: business.budget || 500, + dailyBudget: (business.budget || 500) / 30, + active: true, + targeting: campaign.targeting || {}, + }, + }); + + return { + success: true, + campaignId: campaign.id, + strategy: strategy.output, + }; + } catch (error) { + log.error('Facebook campaign creation failed', error); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private async createGoogleCampaign(business: any): Promise { + try { + // Get campaign strategy from Claude + const strategy = await this.googleExpert.generateCampaignStrategy({ + businessName: business.name, + businessIdea: business.idea, + budget: business.budget || 500, + targetKeywords: this.extractKeywords(business.idea), + campaignType: 'SEARCH', + }); + + // Create campaign via Google Ads API + const campaign = await this.googleAds.createCampaign({ + name: `${business.name} - Search`, + type: 'SEARCH', + budget: business.budget || 500, + keywords: this.extractKeywords(business.idea), + }); + + // Save campaign to database + await this.db.campaign.create({ + data: { + businessId: business.id, + platform: 'GOOGLE', + campaignId: campaign.id, + name: campaign.name, + budget: business.budget || 500, + dailyBudget: (business.budget || 500) / 30, + active: true, + }, + }); + + return { + success: true, + campaignId: campaign.id, + strategy: strategy.output, + }; + } catch (error) { + log.error('Google Ads campaign creation failed', error); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private extractKeywords(text: string): string[] { + return text + .toLowerCase() + .replace(/[^a-z0-9\s]/g, '') + .split(/\s+/) + .filter((w) => w.length > 3) + .slice(0, 20); + } +} diff --git a/packages/orchestrator/src/workflows/05-content-marketing.ts b/packages/orchestrator/src/workflows/05-content-marketing.ts new file mode 100644 index 0000000..1573c62 --- /dev/null +++ b/packages/orchestrator/src/workflows/05-content-marketing.ts @@ -0,0 +1,65 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { ClaudeClient } from '../integrations/claude/claude-client'; +import { log } from '../monitoring/logger'; + +export class ContentMarketingWorkflow extends WorkflowBase { + protected type: WorkflowType = 'CONTENT_MARKETING'; + private claude: ClaudeClient; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.claude = new ClaudeClient(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Starting content marketing setup', { businessId: context.businessId }); + + try { + // Generate SEO content for landing page and blog + const content = await this.claude.generateSEOContent( + business.name, + business.idea, + this.extractKeywords(business.idea) + ); + + log.info('Content generated', { + businessId: context.businessId, + contentLength: content.length, + }); + + // In production, this would: + // 1. Create blog posts + // 2. Publish to CMS + // 3. Share on social media + // 4. Submit to content directories + + return { + success: true, + data: { + contentGenerated: true, + contentLength: content.length, + }, + }; + } catch (error) { + log.error('Content marketing workflow failed', error, { + businessId: context.businessId, + }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private extractKeywords(text: string): string[] { + return text + .toLowerCase() + .replace(/[^a-z0-9\s]/g, '') + .split(/\s+/) + .filter((w) => w.length > 3) + .slice(0, 10); + } +} diff --git a/packages/orchestrator/src/workflows/06-email-automation.ts b/packages/orchestrator/src/workflows/06-email-automation.ts new file mode 100644 index 0000000..2a29b52 --- /dev/null +++ b/packages/orchestrator/src/workflows/06-email-automation.ts @@ -0,0 +1,81 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { SendgridClient } from '../integrations/email/sendgrid-client'; +import { log } from '../monitoring/logger'; +import { integrations } from '../utils/config'; + +export class EmailAutomationWorkflow extends WorkflowBase { + protected type: WorkflowType = 'EMAIL_AUTOMATION'; + private sendgrid: SendgridClient; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.sendgrid = new SendgridClient(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Starting email automation setup', { businessId: context.businessId }); + + try { + if (!integrations.hasSendgrid()) { + log.warn('Sendgrid not configured - skipping email automation', { + businessId: context.businessId, + }); + return { + success: true, + data: { configured: false, reason: 'Sendgrid not configured' }, + }; + } + + // Create email templates + const templates = await this.createEmailTemplates(business); + + log.info('Email templates created', { + businessId: context.businessId, + templateCount: templates.length, + }); + + // Update business + await this.db.business.update({ + where: { id: context.businessId }, + data: { emailAutomation: true }, + }); + + return { + success: true, + data: { + configured: true, + templates: templates.length, + }, + }; + } catch (error) { + log.error('Email automation workflow failed', error, { + businessId: context.businessId, + }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private async createEmailTemplates(business: any): Promise { + const templates = [ + { + name: 'Welcome Email', + subject: `Welcome to ${business.name}!`, + content: `Thank you for joining ${business.name}. We're excited to have you!`, + }, + { + name: 'Onboarding Sequence', + subject: `Get started with ${business.name}`, + content: `Here's how to make the most of ${business.name}...`, + }, + ]; + + // In production, would create actual templates via Sendgrid API + return templates; + } +} diff --git a/packages/orchestrator/src/workflows/07-analytics-setup.ts b/packages/orchestrator/src/workflows/07-analytics-setup.ts new file mode 100644 index 0000000..cd32f38 --- /dev/null +++ b/packages/orchestrator/src/workflows/07-analytics-setup.ts @@ -0,0 +1,90 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { GoogleAnalyticsClient } from '../integrations/analytics/google-analytics'; +import { log } from '../monitoring/logger'; +import { integrations } from '../utils/config'; + +export class AnalyticsSetupWorkflow extends WorkflowBase { + protected type: WorkflowType = 'ANALYTICS_SETUP'; + private ga: GoogleAnalyticsClient; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.ga = new GoogleAnalyticsClient(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Starting analytics setup', { businessId: context.businessId }); + + try { + // Set up Google Analytics tracking + const gaSetup = await this.setupGoogleAnalytics(business); + + // Set up Meta Pixel for Facebook Ads + const metaPixel = await this.setupMetaPixel(business); + + // Set up conversion tracking + const conversionTracking = await this.setupConversionTracking(business); + + log.info('Analytics setup complete', { businessId: context.businessId }); + + return { + success: true, + data: { + googleAnalytics: gaSetup, + metaPixel, + conversionTracking, + }, + }; + } catch (error) { + log.error('Analytics setup workflow failed', error, { + businessId: context.businessId, + }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private async setupGoogleAnalytics(business: any): Promise { + // In production, would: + // 1. Create GA4 property + // 2. Install tracking code on MVP + // 3. Set up conversion goals + // 4. Configure e-commerce tracking + + return { + configured: integrations.hasVercel(), + trackingId: 'G-XXXXXXXXXX', // Would be real ID + }; + } + + private async setupMetaPixel(business: any): Promise { + // In production, would: + // 1. Create Meta Pixel + // 2. Install pixel code on MVP + // 3. Set up custom events + // 4. Configure conversion tracking + + return { + configured: integrations.hasFacebookAds(), + pixelId: '1234567890', // Would be real ID + }; + } + + private async setupConversionTracking(business: any): Promise { + // Track key events: + // - Page views + // - Sign-ups + // - Purchases + // - Email subscriptions + + return { + configured: true, + events: ['page_view', 'signup', 'purchase', 'subscribe'], + }; + } +} diff --git a/packages/orchestrator/src/workflows/08-optimization-loop.ts b/packages/orchestrator/src/workflows/08-optimization-loop.ts new file mode 100644 index 0000000..90ea907 --- /dev/null +++ b/packages/orchestrator/src/workflows/08-optimization-loop.ts @@ -0,0 +1,224 @@ +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { WorkflowType } from '@prisma/client'; +import { MetricsCollector } from '../monitoring/metrics'; +import { FacebookAdsAPI } from '../integrations/ads/facebook-ads'; +import { GoogleAdsAPI } from '../integrations/ads/google-ads'; +import { log } from '../monitoring/logger'; + +export class OptimizationLoopWorkflow extends WorkflowBase { + protected type: WorkflowType = 'OPTIMIZATION_LOOP'; + private metrics: MetricsCollector; + private fbAds: FacebookAdsAPI; + private googleAds: GoogleAdsAPI; + + constructor(db: any, alerts: any) { + super(db, alerts); + this.metrics = new MetricsCollector(db); + this.fbAds = new FacebookAdsAPI(); + this.googleAds = new GoogleAdsAPI(); + } + + protected async execute(context: WorkflowContext): Promise { + const business = await this.getBusiness(context.businessId); + + log.info('Running optimization loop', { businessId: context.businessId }); + + try { + // Step 1: Collect latest metrics from all sources + const currentMetrics = await this.collectMetrics(context.businessId); + + // Step 2: Analyze campaign performance + const campaignAnalysis = await this.analyzeCampaigns(context.businessId); + + // Step 3: Optimize budget allocation + const budgetOptimization = await this.optimizeBudgets( + context.businessId, + campaignAnalysis + ); + + // Step 4: Pause underperforming campaigns + const pausedCampaigns = await this.pauseUnderperformers( + context.businessId, + campaignAnalysis + ); + + // Step 5: Test new ad variations + const adTesting = await this.runAdTests(context.businessId); + + // Step 6: Record metrics + await this.metrics.recordMetric(context.businessId, { + revenue: currentMetrics.revenue, + adSpend: currentMetrics.adSpend, + visitors: currentMetrics.visitors, + conversions: currentMetrics.conversions, + }); + + log.info('Optimization loop completed', { + businessId: context.businessId, + revenue: currentMetrics.revenue, + pausedCampaigns: pausedCampaigns.length, + }); + + return { + success: true, + data: { + metrics: currentMetrics, + budgetChanges: budgetOptimization, + pausedCampaigns, + adTests: adTesting, + }, + }; + } catch (error) { + log.error('Optimization loop failed', error, { businessId: context.businessId }); + return { + success: false, + error: error instanceof Error ? error.message : String(error), + }; + } + } + + private async collectMetrics(businessId: string): Promise { + // Fetch metrics from: + // 1. Google Analytics + // 2. Facebook Ads + // 3. Google Ads + // 4. Payment processor (Stripe) + + const campaigns = await this.db.campaign.findMany({ + where: { businessId, active: true }, + }); + + const totalSpend = campaigns.reduce((sum: number, c: any) => sum + c.spend, 0); + const totalRevenue = campaigns.reduce((sum: number, c: any) => sum + c.revenue, 0); + + return { + revenue: totalRevenue, + adSpend: totalSpend, + visitors: Math.floor(Math.random() * 1000), // Would fetch from GA + conversions: Math.floor(Math.random() * 50), // Would fetch from GA + roas: totalSpend > 0 ? totalRevenue / totalSpend : 0, + }; + } + + private async analyzeCampaigns(businessId: string): Promise { + const campaigns = await this.db.campaign.findMany({ + where: { businessId, active: true }, + }); + + return campaigns.map((campaign: any) => ({ + id: campaign.id, + platform: campaign.platform, + roas: campaign.spend > 0 ? campaign.revenue / campaign.spend : 0, + ctr: campaign.impressions > 0 ? campaign.clicks / campaign.impressions : 0, + conversionRate: + campaign.clicks > 0 ? campaign.conversions / campaign.clicks : 0, + performance: + campaign.spend > 0 && campaign.revenue / campaign.spend >= 2 + ? 'good' + : campaign.revenue / campaign.spend >= 1 + ? 'acceptable' + : 'poor', + })); + } + + private async optimizeBudgets( + businessId: string, + analysis: any[] + ): Promise { + const optimizations = []; + + for (const campaign of analysis) { + if (campaign.performance === 'good' && campaign.roas >= 3) { + // Increase budget for high performers + const newBudget = (await this.getCampaignBudget(campaign.id)) * 1.2; + + await this.updateCampaignBudget(campaign.id, newBudget); + + optimizations.push({ + campaignId: campaign.id, + action: 'increase_budget', + change: '+20%', + }); + + log.info('Increased budget for high-performing campaign', { + campaignId: campaign.id, + newBudget, + }); + } else if (campaign.performance === 'poor') { + // Decrease budget for poor performers + const newBudget = (await this.getCampaignBudget(campaign.id)) * 0.7; + + await this.updateCampaignBudget(campaign.id, newBudget); + + optimizations.push({ + campaignId: campaign.id, + action: 'decrease_budget', + change: '-30%', + }); + + log.info('Decreased budget for poor-performing campaign', { + campaignId: campaign.id, + newBudget, + }); + } + } + + return optimizations; + } + + private async pauseUnderperformers( + businessId: string, + analysis: any[] + ): Promise { + const paused = []; + + for (const campaign of analysis) { + if (campaign.performance === 'poor' && campaign.roas < 0.5) { + // Pause campaigns with ROAS < 0.5 (losing 50%+) + await this.db.campaign.update({ + where: { id: campaign.id }, + data: { active: false }, + }); + + paused.push(campaign.id); + + log.warn('Paused underperforming campaign', { + campaignId: campaign.id, + roas: campaign.roas, + }); + } + } + + return paused; + } + + private async runAdTests(businessId: string): Promise { + // In production, would: + // 1. Create A/B test variants + // 2. Test different ad copy + // 3. Test different targeting + // 4. Test different creatives + + return { + testsRunning: 2, + testsCompleted: 0, + }; + } + + private async getCampaignBudget(campaignId: string): Promise { + const campaign = await this.db.campaign.findUnique({ + where: { id: campaignId }, + }); + return campaign?.budget || 0; + } + + private async updateCampaignBudget( + campaignId: string, + newBudget: number + ): Promise { + await this.db.campaign.update({ + where: { id: campaignId }, + data: { budget: newBudget }, + }); + } +} diff --git a/packages/orchestrator/src/workflows/workflow-base.ts b/packages/orchestrator/src/workflows/workflow-base.ts new file mode 100644 index 0000000..8d73d72 --- /dev/null +++ b/packages/orchestrator/src/workflows/workflow-base.ts @@ -0,0 +1,238 @@ +import { PrismaClient, WorkflowType, WorkflowStatus } from '@prisma/client'; +import { log } from '../monitoring/logger'; +import { AlertSystem } from '../monitoring/alerts'; + +export interface WorkflowContext { + businessId: string; + inputData?: Record; +} + +export interface WorkflowResult { + success: boolean; + data?: Record; + error?: string; +} + +export abstract class WorkflowBase { + protected db: PrismaClient; + protected alerts: AlertSystem; + protected abstract type: WorkflowType; + protected maxRetries: number = 3; + protected retryDelay: number = 2000; // Base delay in ms + + constructor(db: PrismaClient, alerts: AlertSystem) { + this.db = db; + this.alerts = alerts; + } + + /** + * Main execution method - must be implemented by subclasses + */ + protected abstract execute(context: WorkflowContext): Promise; + + /** + * Execute workflow with retry logic, error handling, and logging + */ + async executeWithRetry(context: WorkflowContext): Promise { + const { businessId } = context; + let workflowRun; + + try { + // Create workflow run record + workflowRun = await this.db.workflowRun.create({ + data: { + businessId, + workflowType: this.type, + status: 'IN_PROGRESS', + inputData: context.inputData || {}, + startedAt: new Date(), + maxRetries: this.maxRetries, + }, + }); + + log.workflow.started(this.type, businessId); + + // Execute with retries + for (let attempt = 1; attempt <= this.maxRetries; attempt++) { + try { + // Update attempt count + await this.db.workflowRun.update({ + where: { id: workflowRun.id }, + data: { attempts: attempt }, + }); + + // Execute the workflow + const startTime = Date.now(); + const result = await this.execute(context); + const duration = Date.now() - startTime; + + if (result.success) { + // Success - update record and return + await this.db.workflowRun.update({ + where: { id: workflowRun.id }, + data: { + status: 'COMPLETED', + outputData: result.data || {}, + completedAt: new Date(), + }, + }); + + log.workflow.completed(this.type, businessId, duration); + await this.alerts.workflowCompleted(businessId, this.type); + + return result; + } else { + // Workflow returned failure + throw new Error(result.error || 'Workflow execution failed'); + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + log.workflow.failed(this.type, businessId, error as Error, attempt); + + // If this was the last attempt, fail permanently + if (attempt === this.maxRetries) { + await this.handleFinalFailure(workflowRun.id, businessId, errorMessage); + return { + success: false, + error: errorMessage, + }; + } + + // Otherwise, log retry and wait + log.workflow.retrying(this.type, businessId, attempt, this.maxRetries); + + await this.db.workflowRun.update({ + where: { id: workflowRun.id }, + data: { + status: 'RETRYING', + error: errorMessage, + }, + }); + + // Exponential backoff + const delay = this.retryDelay * Math.pow(2, attempt - 1); + await this.sleep(delay); + } + } + + // Should never reach here, but just in case + throw new Error('Exhausted all retries'); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + log.error(`Workflow ${this.type} failed completely`, error, { businessId }); + + if (workflowRun) { + await this.handleFinalFailure(workflowRun.id, businessId, errorMessage); + } + + return { + success: false, + error: errorMessage, + }; + } + } + + /** + * Handle final workflow failure after all retries + */ + private async handleFinalFailure( + workflowRunId: string, + businessId: string, + error: string + ): Promise { + // Update workflow run + await this.db.workflowRun.update({ + where: { id: workflowRunId }, + data: { + status: 'FAILED', + error, + completedAt: new Date(), + }, + }); + + // Send alert + await this.alerts.workflowFailed(businessId, this.type, error); + + // Pause business for critical workflows + if (this.isCriticalWorkflow()) { + await this.db.business.update({ + where: { id: businessId }, + data: { status: 'PAUSED' }, + }); + + log.warn('Business paused due to critical workflow failure', { + businessId, + workflowType: this.type, + }); + } + } + + /** + * Determine if this workflow is critical (should pause business on failure) + */ + protected isCriticalWorkflow(): boolean { + const criticalWorkflows: WorkflowType[] = [ + 'MARKET_VALIDATION', + 'MVP_DEVELOPMENT', + ]; + return criticalWorkflows.includes(this.type); + } + + /** + * Sleep utility for retry delays + */ + protected sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + /** + * Get business data + */ + protected async getBusiness(businessId: string) { + const business = await this.db.business.findUnique({ + where: { id: businessId }, + }); + + if (!business) { + throw new Error(`Business not found: ${businessId}`); + } + + return business; + } + + /** + * Update business status + */ + protected async updateBusinessStatus( + businessId: string, + status: any, + updates?: Record + ) { + await this.db.business.update({ + where: { id: businessId }, + data: { + status, + ...updates, + }, + }); + + log.business.statusChanged(businessId, 'unknown', status); + } + + /** + * Validate context before execution + */ + protected validateContext(context: WorkflowContext): void { + if (!context.businessId) { + throw new Error('businessId is required in workflow context'); + } + } + + /** + * Execute workflow (public method) + */ + async run(context: WorkflowContext): Promise { + this.validateContext(context); + return await this.executeWithRetry(context); + } +} diff --git a/packages/orchestrator/src/workflows/workflow-executor.ts b/packages/orchestrator/src/workflows/workflow-executor.ts new file mode 100644 index 0000000..7f7a875 --- /dev/null +++ b/packages/orchestrator/src/workflows/workflow-executor.ts @@ -0,0 +1,181 @@ +import { PrismaClient, WorkflowType } from '@prisma/client'; +import { AlertSystem } from '../monitoring/alerts'; +import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base'; +import { log } from '../monitoring/logger'; + +// Workflow imports (will be created) +import { MarketValidationWorkflow } from './01-market-validation'; +import { MVPDevelopmentWorkflow } from './02-mvp-development'; +import { LandingPageSEOWorkflow } from './03-landing-page-seo'; +import { PaidAdsWorkflow } from './04-paid-ads'; +import { ContentMarketingWorkflow } from './05-content-marketing'; +import { EmailAutomationWorkflow } from './06-email-automation'; +import { AnalyticsSetupWorkflow } from './07-analytics-setup'; +import { OptimizationLoopWorkflow } from './08-optimization-loop'; + +export class WorkflowExecutor { + private db: PrismaClient; + private alerts: AlertSystem; + private workflows: Map; + + constructor(db: PrismaClient, alerts: AlertSystem) { + this.db = db; + this.alerts = alerts; + + // Initialize all workflows + this.workflows = new Map([ + ['MARKET_VALIDATION', new MarketValidationWorkflow(db, alerts)], + ['MVP_DEVELOPMENT', new MVPDevelopmentWorkflow(db, alerts)], + ['LANDING_PAGE_SEO', new LandingPageSEOWorkflow(db, alerts)], + ['PAID_ADS', new PaidAdsWorkflow(db, alerts)], + ['CONTENT_MARKETING', new ContentMarketingWorkflow(db, alerts)], + ['EMAIL_AUTOMATION', new EmailAutomationWorkflow(db, alerts)], + ['ANALYTICS_SETUP', new AnalyticsSetupWorkflow(db, alerts)], + ['OPTIMIZATION_LOOP', new OptimizationLoopWorkflow(db, alerts)], + ]); + } + + /** + * Execute a single workflow + */ + async run( + businessId: string, + workflowType: WorkflowType, + inputData?: Record + ): Promise { + const workflow = this.workflows.get(workflowType); + + if (!workflow) { + throw new Error(`Unknown workflow type: ${workflowType}`); + } + + const context: WorkflowContext = { + businessId, + inputData, + }; + + return await workflow.run(context); + } + + /** + * Execute multiple workflows in parallel + */ + async runParallel( + businessId: string, + workflowTypes: WorkflowType[], + inputData?: Record + ): Promise { + log.info(`Running ${workflowTypes.length} workflows in parallel`, { + businessId, + workflowTypes, + }); + + const promises = workflowTypes.map((type) => this.run(businessId, type, inputData)); + + return await Promise.all(promises); + } + + /** + * Execute workflows in sequence + */ + async runSequence( + businessId: string, + workflowTypes: WorkflowType[], + inputData?: Record + ): Promise { + log.info(`Running ${workflowTypes.length} workflows in sequence`, { + businessId, + workflowTypes, + }); + + const results: WorkflowResult[] = []; + + for (const type of workflowTypes) { + const result = await this.run(businessId, type, inputData); + results.push(result); + + // If a workflow fails, stop the sequence + if (!result.success) { + log.error(`Workflow sequence stopped due to failure: ${type}`, undefined, { + businessId, + }); + break; + } + } + + return results; + } + + /** + * Run a workflow forever (with interval) - for optimization loop + */ + async runForever( + businessId: string, + workflowType: WorkflowType, + intervalMinutes: number = 1440 // Daily by default + ): Promise { + log.info(`Starting infinite workflow loop: ${workflowType}`, { + businessId, + intervalMinutes, + }); + + while (true) { + try { + // Check if business is still active + const business = await this.db.business.findUnique({ + where: { id: businessId }, + }); + + if (!business || business.status === 'SHUTDOWN' || business.status === 'PAUSED') { + log.info('Stopping workflow loop - business no longer active', { + businessId, + status: business?.status, + }); + break; + } + + // Run workflow + await this.run(businessId, workflowType); + + // Wait for interval + const delayMs = intervalMinutes * 60 * 1000; + await new Promise((resolve) => setTimeout(resolve, delayMs)); + } catch (error) { + log.error('Error in workflow loop', error, { businessId, workflowType }); + + // Wait a bit before retrying to avoid rapid failure loops + await new Promise((resolve) => setTimeout(resolve, 60000)); // 1 minute + } + } + } + + /** + * Check if a workflow has already been completed for a business + */ + async hasCompleted(businessId: string, workflowType: WorkflowType): Promise { + const run = await this.db.workflowRun.findFirst({ + where: { + businessId, + workflowType, + status: 'COMPLETED', + }, + }); + + return run !== null; + } + + /** + * Get workflow status for a business + */ + async getWorkflowStatus(businessId: string, workflowType: WorkflowType) { + return await this.db.workflowRun.findFirst({ + where: { + businessId, + workflowType, + }, + orderBy: { + createdAt: 'desc', + }, + }); + } +} diff --git a/packages/orchestrator/tsconfig.json b/packages/orchestrator/tsconfig.json new file mode 100644 index 0000000..b6433c6 --- /dev/null +++ b/packages/orchestrator/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "lib": ["ES2022"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000..c36ac29 --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,14 @@ +{ + "name": "@srb/shared", + "version": "1.0.0", + "description": "Shared types and utilities", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc", + "clean": "rm -rf dist" + }, + "devDependencies": { + "typescript": "^5.6.0" + } +} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts new file mode 100644 index 0000000..dac9bc2 --- /dev/null +++ b/packages/shared/src/index.ts @@ -0,0 +1,3 @@ +export * from './types/business'; +export * from './types/workflow'; +export * from './types/metrics'; diff --git a/packages/shared/src/types/business.ts b/packages/shared/src/types/business.ts new file mode 100644 index 0000000..869bce6 --- /dev/null +++ b/packages/shared/src/types/business.ts @@ -0,0 +1,61 @@ +export enum BusinessStatus { + VALIDATING = 'VALIDATING', + VALIDATION_FAILED = 'VALIDATION_FAILED', + DEVELOPING_MVP = 'DEVELOPING_MVP', + LAUNCHING = 'LAUNCHING', + RUNNING_ADS = 'RUNNING_ADS', + OPTIMIZING = 'OPTIMIZING', + SCALING = 'SCALING', + SELLING = 'SELLING', + SHUTDOWN = 'SHUTDOWN', + PAUSED = 'PAUSED' +} + +export interface Business { + id: string; + name: string; + idea: string; + status: BusinessStatus; + viable: boolean | null; + mvpUrl: string | null; + landingPageUrl: string | null; + seoOptimized: boolean; + adsActive: boolean; + emailAutomation: boolean; + monthlyRevenue: number; + totalRevenue: number; + createdAt: Date; + updatedAt: Date; +} + +export interface BusinessInput { + name: string; + idea: string; + targetAudience?: string; + budget?: number; +} + +export interface ValidationResult { + viable: boolean; + score: number; + competitors: CompetitorInfo[]; + demandData: DemandData; + analysis: string; + risks: string[]; + opportunities: string[]; +} + +export interface CompetitorInfo { + name: string; + url: string; + estimatedTraffic?: number; + strengths: string[]; + weaknesses: string[]; +} + +export interface DemandData { + searchVolume: number; + trend: 'rising' | 'stable' | 'declining'; + seasonality: boolean; + relatedKeywords: string[]; +} diff --git a/packages/shared/src/types/metrics.ts b/packages/shared/src/types/metrics.ts new file mode 100644 index 0000000..b408bf7 --- /dev/null +++ b/packages/shared/src/types/metrics.ts @@ -0,0 +1,61 @@ +export enum Platform { + FACEBOOK = 'FACEBOOK', + GOOGLE = 'GOOGLE', + ORGANIC = 'ORGANIC' +} + +export enum DecisionType { + SCALE_PRODUCT = 'SCALE_PRODUCT', + SELL_BUSINESS = 'SELL_BUSINESS', + SHUTDOWN = 'SHUTDOWN', + PAUSE_CAMPAIGN = 'PAUSE_CAMPAIGN', + INCREASE_BUDGET = 'INCREASE_BUDGET', + HIRE_VA = 'HIRE_VA' +} + +export interface Campaign { + id: string; + businessId: string; + platform: Platform; + budget: number; + active: boolean; + impressions: number; + clicks: number; + conversions: number; + revenue: number; + createdAt: Date; + updatedAt: Date; +} + +export interface Metric { + id: string; + businessId: string; + timestamp: Date; + revenue: number; + adSpend: number; + visitors: number; + conversions: number; + roas: number | null; +} + +export interface Decision { + id: string; + businessId: string; + decisionType: DecisionType; + action: string; + reasoning: string; + revenueAtDecision: number | null; + executed: boolean; + createdAt: Date; +} + +export interface BusinessMetrics { + totalRevenue: number; + monthlyRevenue: number; + totalAdSpend: number; + monthlyAdSpend: number; + averageRoas: number; + totalConversions: number; + totalVisitors: number; + conversionRate: number; +} diff --git a/packages/shared/src/types/workflow.ts b/packages/shared/src/types/workflow.ts new file mode 100644 index 0000000..fe9085e --- /dev/null +++ b/packages/shared/src/types/workflow.ts @@ -0,0 +1,44 @@ +export enum WorkflowType { + MARKET_VALIDATION = 'MARKET_VALIDATION', + MVP_DEVELOPMENT = 'MVP_DEVELOPMENT', + LANDING_PAGE_SEO = 'LANDING_PAGE_SEO', + PAID_ADS = 'PAID_ADS', + CONTENT_MARKETING = 'CONTENT_MARKETING', + EMAIL_AUTOMATION = 'EMAIL_AUTOMATION', + ANALYTICS_SETUP = 'ANALYTICS_SETUP', + OPTIMIZATION_LOOP = 'OPTIMIZATION_LOOP' +} + +export enum WorkflowStatus { + PENDING = 'PENDING', + IN_PROGRESS = 'IN_PROGRESS', + COMPLETED = 'COMPLETED', + FAILED = 'FAILED', + RETRYING = 'RETRYING' +} + +export interface WorkflowRun { + id: string; + businessId: string; + workflowType: WorkflowType; + status: WorkflowStatus; + inputData: Record; + outputData: Record | null; + error: string | null; + attempts: number; + startedAt: Date | null; + completedAt: Date | null; +} + +export interface WorkflowExecutionContext { + businessId: string; + workflowType: WorkflowType; + inputData: Record; + retryCount: number; +} + +export interface WorkflowResult { + success: boolean; + data?: Record; + error?: string; +} diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json new file mode 100644 index 0000000..15bb33d --- /dev/null +++ b/packages/shared/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "lib": ["ES2022"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..18ec407 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - 'packages/*' diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..170dc3f --- /dev/null +++ b/turbo.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://turbo.build/schema.json", + "tasks": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", ".next/**", "!.next/cache/**"] + }, + "dev": { + "cache": false, + "persistent": true + }, + "test": { + "dependsOn": ["build"], + "outputs": ["coverage/**"] + }, + "lint": { + "outputs": [] + }, + "clean": { + "cache": false + } + } +}