{
  "schemaVersion": "1.0",
  "item": {
    "slug": "business-opportunity-detector",
    "name": "Hidden Business Opportunity Detector",
    "source": "tencent",
    "type": "skill",
    "category": "数据分析",
    "sourceUrl": "https://clawhub.ai/g4dr/business-opportunity-detector",
    "canonicalUrl": "https://clawhub.ai/g4dr/business-opportunity-detector",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/business-opportunity-detector",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=business-opportunity-detector",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/business-opportunity-detector"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/business-opportunity-detector",
    "agentPageUrl": "https://openagent3.xyz/skills/business-opportunity-detector/agent",
    "manifestUrl": "https://openagent3.xyz/skills/business-opportunity-detector/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/business-opportunity-detector/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Overview",
        "body": "This skill builds an automated business intelligence engine that:\n\nApify scrapes App Store reviews, Amazon reviews, Reddit, niche forums, and Product Hunt\nClaude (OpenClaw) deep-analyzes the raw frustrations, recurring requests, and unmet needs\nProduces a structured market gap report with validated SaaS ideas, scored by opportunity size\n\nThis is how the best indie hackers and founders find their next product — systematically.\n\n🔗 Apify: https://www.apify.com/?fpr=dx06p"
      },
      {
        "title": "What This Skill Does",
        "body": "Scrape App Store & Google Play reviews to find what users hate about existing apps\nScrape Amazon reviews (1–2 stars) to extract product frustrations at scale\nMine Reddit niche communities for recurring complaints and feature requests\nCrawl niche forums and communities for unmet needs\nScrape Product Hunt for emerging tools and gaps in the market\nFeed all raw data into Claude for structured opportunity analysis\nOutput a ranked list of business opportunities with validation signals\nGenerate SaaS idea briefs with positioning, features, and GTM angle"
      },
      {
        "title": "Architecture Overview",
        "body": "┌─────────────────────────────────────────────────────────────────┐\n│           HIDDEN BUSINESS OPPORTUNITY DETECTOR                  │\n│                                                                 │\n│  ┌─────────────────────────────────────────────────────────┐   │\n│  │  LAYER 1 — DATA MINING (Apify)                          │   │\n│  │  App Store │ Google Play │ Amazon │ Reddit │ Forums      │   │\n│  │  Product Hunt │ G2 │ Trustpilot │ Indie Hackers          │   │\n│  └──────────────────────────┬──────────────────────────────┘   │\n│                             │                                   │\n│  ┌──────────────────────────▼──────────────────────────────┐   │\n│  │  LAYER 2 — OPPORTUNITY ANALYSIS ENGINE (Claude)         │   │\n│  │                                                         │   │\n│  │  • Frustration Extractor  → what people hate/struggle   │   │\n│  │  • Pattern Detector       → recurring complaints        │   │\n│  │  • Gap Analyzer           → what nobody is building     │   │\n│  │  • Opportunity Scorer     → market size x pain level    │   │\n│  │  • SaaS Idea Generator    → concrete product briefs     │   │\n│  └──────────────────────────┬──────────────────────────────┘   │\n│                             │                                   │\n│  ┌──────────────────────────▼──────────────────────────────┐   │\n│  │  LAYER 3 — OPPORTUNITY REPORT                           │   │\n│  │  Ranked ideas │ Validation signals │ GTM angles          │   │\n│  │  JSON export │ Markdown report │ Notion / Slack push     │   │\n│  └─────────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────────┘"
      },
      {
        "title": "Apify",
        "body": "Sign up at https://www.apify.com/?fpr=dx06p\nGo to Settings → Integrations\nCopy your token:\nexport APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx"
      },
      {
        "title": "Claude / OpenClaw",
        "body": "export CLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx"
      },
      {
        "title": "Step 2 — Install Dependencies",
        "body": "npm install apify-client axios node-cron dotenv fs-extra"
      },
      {
        "title": "Mine App Store & Google Play Reviews",
        "body": "import ApifyClient from 'apify-client';\n\nconst apify = new ApifyClient({ token: process.env.APIFY_TOKEN });\n\n// Define the niche and competitor apps to analyze\nconst TARGET_NICHE = \"project management\";\nconst COMPETITOR_APPS = [\n  { name: \"Notion\",   appStoreId: \"1232780281\", playStoreId: \"notion.id\" },\n  { name: \"Asana\",    appStoreId: \"489969512\",  playStoreId: \"com.asana.app\" },\n  { name: \"Trello\",   appStoreId: \"461504587\",  playStoreId: \"com.trello\" },\n  { name: \"Monday\",   appStoreId: \"1298450011\", playStoreId: \"com.monday.monday\" }\n];\n\nasync function scrapeAppReviews() {\n  console.log(\"📱 Scraping App Store & Play Store reviews...\");\n\n  const jobs = COMPETITOR_APPS.map(app =>\n    Promise.all([\n\n      // App Store — focus on 1-3 star reviews (the gold mine)\n      apify.actor(\"apify/apple-app-store-scraper\").call({\n        appIds: [app.appStoreId],\n        maxReviews: 100,\n        filterStars: [1, 2, 3]\n      }).then(run => run.dataset().getData())\n        .then(d => d.items.map(r => ({\n          source: \"app_store\",\n          appName: app.name,\n          rating: r.rating,\n          review: r.review,\n          title: r.title,\n          date: r.date,\n          country: r.country\n        }))),\n\n      // Google Play Store\n      apify.actor(\"apify/google-play-scraper\").call({\n        appId: app.playStoreId,\n        maxReviews: 100,\n        filterScore: [1, 2, 3]\n      }).then(run => run.dataset().getData())\n        .then(d => d.items.map(r => ({\n          source: \"google_play\",\n          appName: app.name,\n          rating: r.score,\n          review: r.text,\n          title: r.title || \"\",\n          date: r.date,\n          thumbsUp: r.thumbsUp\n        })))\n\n    ]).then(results => results.flat())\n  );\n\n  const allReviews = await Promise.all(jobs);\n  return allReviews.flat();\n}"
      },
      {
        "title": "Mine Amazon Reviews (1-3 Stars)",
        "body": "async function scrapeAmazonReviews() {\n  console.log(\"📦 Scraping Amazon negative reviews...\");\n\n  // Target products in your niche\n  const TARGET_PRODUCTS = [\n    \"https://www.amazon.com/dp/B08N5WRWNW\", // productivity tool example\n    \"https://www.amazon.com/dp/B09G9HD6PD\"\n  ];\n\n  const jobs = TARGET_PRODUCTS.map(url =>\n    apify.actor(\"apify/amazon-reviews-scraper\").call({\n      startUrls: [{ url }],\n      maxReviews: 100,\n      filterByStar: [\"one_star\", \"two_star\", \"three_star\"]\n    }).then(run => run.dataset().getData())\n      .then(d => d.items.map(r => ({\n        source: \"amazon\",\n        productTitle: r.productTitle,\n        rating: r.ratingScore,\n        review: r.reviewText,\n        title: r.reviewTitle,\n        date: r.date,\n        helpfulVotes: r.helpfulVotes,\n        verifiedPurchase: r.verifiedPurchase\n      })))\n  );\n\n  const results = await Promise.all(jobs);\n  return results.flat();\n}"
      },
      {
        "title": "Mine Reddit Niche Communities",
        "body": "async function scrapeRedditFrustrations() {\n  console.log(\"💬 Scraping Reddit communities...\");\n\n  const SUBREDDITS = [\n    \"r/Entrepreneur\",\n    \"r/SaaS\",\n    \"r/smallbusiness\",\n    \"r/productivity\",\n    \"r/projectmanagement\",\n    \"r/startups\",\n    \"r/indiehackers\"\n  ];\n\n  const [posts, searchResults] = await Promise.all([\n\n    // Hot/top posts in subreddits\n    apify.actor(\"apify/reddit-scraper\").call({\n      startUrls: SUBREDDITS.map(s => ({ url: `https://www.reddit.com/${s}/` })),\n      maxPostCount: 30,\n      maxComments: 15,\n      sort: \"top\"\n    }).then(run => run.dataset().getData()),\n\n    // Search for frustration signals\n    apify.actor(\"apify/reddit-search-scraper\").call({\n      queries: [\n        `${TARGET_NICHE} frustrated wish`,\n        `${TARGET_NICHE} hate problem broken`,\n        `${TARGET_NICHE} alternative looking for better`,\n        `${TARGET_NICHE} feature request need`,\n        `${TARGET_NICHE} why is there no tool`\n      ],\n      maxItems: 50\n    }).then(run => run.dataset().getData())\n\n  ]);\n\n  return [\n    ...posts.items.map(p => ({\n      source: \"reddit_post\",\n      subreddit: p.subreddit,\n      title: p.title,\n      text: p.selftext,\n      score: p.score,\n      comments: p.numComments,\n      url: p.url\n    })),\n    ...searchResults.items.map(p => ({\n      source: \"reddit_search\",\n      subreddit: p.subreddit,\n      title: p.title,\n      text: p.selftext,\n      score: p.score,\n      url: p.url\n    }))\n  ];\n}"
      },
      {
        "title": "Mine Product Hunt & G2 Reviews",
        "body": "async function scrapeProductIntelligence() {\n  console.log(\"🚀 Scraping Product Hunt & review platforms...\");\n\n  const [productHunt, g2] = await Promise.all([\n\n    // Product Hunt — see what's launching and what comments say\n    apify.actor(\"apify/product-hunt-scraper\").call({\n      mode: \"search\",\n      searchQuery: TARGET_NICHE,\n      maxItems: 30\n    }).then(run => run.dataset().getData())\n      .then(d => d.items.map(p => ({\n        source: \"product_hunt\",\n        name: p.name,\n        tagline: p.tagline,\n        description: p.description,\n        upvotes: p.votesCount,\n        comments: p.commentsCount,\n        topics: p.topics,\n        url: p.url\n      }))),\n\n    // G2 reviews for competitor software\n    apify.actor(\"apify/website-content-crawler\").call({\n      startUrls: [\n        { url: `https://www.g2.com/categories/${TARGET_NICHE.replace(/\\s+/g, '-')}-software` }\n      ],\n      maxCrawlingDepth: 1,\n      maxRequestsPerCrawl: 10\n    }).then(run => run.dataset().getData())\n      .then(d => d.items.map(p => ({\n        source: \"g2\",\n        text: p.text?.slice(0, 2000),\n        url: p.url\n      })))\n\n  ]);\n\n  return [...productHunt, ...g2];\n}"
      },
      {
        "title": "Frustration Extractor",
        "body": "import axios from 'axios';\n\nconst claude = axios.create({\n  baseURL: 'https://api.anthropic.com/v1',\n  headers: {\n    'x-api-key': process.env.CLAUDE_API_KEY,\n    'anthropic-version': '2023-06-01',\n    'Content-Type': 'application/json'\n  }\n});\n\nasync function extractFrustrations(allData) {\n  const prompt = `\nYou are a world-class product researcher and market analyst.\n\nAnalyze this raw data from app reviews, Amazon reviews, Reddit posts, and product listings.\nExtract every customer frustration, unmet need, and recurring complaint.\n\nNICHE: ${TARGET_NICHE}\n\nRAW DATA (sample):\n${JSON.stringify(allData.slice(0, 30), null, 2)}\n\nRespond ONLY in this JSON format:\n{\n  \"frustrations\": [\n    {\n      \"theme\": \"short label\",\n      \"description\": \"what users are frustrated about\",\n      \"frequency\": \"how often this comes up (high/medium/low)\",\n      \"emotionalIntensity\": \"how angry/upset users are (1-10)\",\n      \"affectedSegment\": \"who experiences this most\",\n      \"evidenceQuotes\": [\"direct quote 1\", \"direct quote 2\"],\n      \"sources\": [\"app_store\", \"reddit\"]\n    }\n  ],\n  \"featureRequests\": [\n    {\n      \"request\": \"what users are explicitly asking for\",\n      \"frequency\": \"high | medium | low\",\n      \"currentWorkaround\": \"what users do today instead\",\n      \"evidenceQuotes\": [\"quote\"]\n    }\n  ],\n  \"recurringPatterns\": [\n    \"pattern 1 observed across multiple sources\",\n    \"pattern 2\"\n  ],\n  \"underservedSegments\": [\n    {\n      \"segment\": \"who is being ignored\",\n      \"unmetNeed\": \"what they need\",\n      \"currentSolution\": \"what they use today despite it being bad\"\n    }\n  ]\n}\n`;\n\n  const { data } = await claude.post('/messages', {\n    model: \"claude-opus-4-5\",\n    max_tokens: 3000,\n    messages: [{ role: \"user\", content: prompt }]\n  });\n\n  return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim());\n}"
      },
      {
        "title": "Market Gap Analyzer & SaaS Idea Generator",
        "body": "async function analyzeMarketGaps(frustrations, productIntel) {\n  const prompt = `\nYou are a serial entrepreneur and SaaS product strategist.\n\nBased on these validated customer frustrations and market intelligence, identify\nthe highest-potential business opportunities and generate concrete SaaS ideas.\n\nFRUSTRATIONS & PATTERNS:\n${JSON.stringify(frustrations, null, 2)}\n\nMARKET INTELLIGENCE (existing products):\n${JSON.stringify(productIntel.slice(0, 10), null, 2)}\n\nRespond ONLY in this JSON format:\n{\n  \"marketGaps\": [\n    {\n      \"gap\": \"what is clearly missing from the market\",\n      \"evidenceStrength\": \"strong | moderate | weak\",\n      \"estimatedMarketSize\": \"niche | small | medium | large\",\n      \"competitionLevel\": \"none | low | medium | high\",\n      \"urgency\": \"nice-to-have | important | critical\"\n    }\n  ],\n  \"saasIdeas\": [\n    {\n      \"rank\": 1,\n      \"name\": \"working product name\",\n      \"oneLiner\": \"X for Y — one sentence pitch\",\n      \"problem\": \"exact problem it solves\",\n      \"targetCustomer\": \"specific ICP (ideal customer profile)\",\n      \"coreFeatures\": [\"feature 1\", \"feature 2\", \"feature 3\"],\n      \"differentiator\": \"why this beats existing solutions\",\n      \"monetization\": \"pricing model (per seat | usage | freemium | etc)\",\n      \"estimatedMRR\": \"rough MRR potential at 100 customers\",\n      \"validationSignals\": [\"signal from data that confirms the need\"],\n      \"gtmAngle\": \"how to acquire first 100 customers\",\n      \"buildComplexity\": \"low | medium | high\",\n      \"opportunityScore\": 8,\n      \"risksAndChallenges\": [\"risk 1\", \"risk 2\"]\n    }\n  ],\n  \"quickWins\": [\n    {\n      \"idea\": \"simplest possible version of a solution\",\n      \"timeToMVP\": \"estimated days/weeks to build\",\n      \"validationMethod\": \"how to validate before building\"\n    }\n  ],\n  \"topRecommendation\": \"single best opportunity with 1-paragraph reasoning\"\n}\n`;\n\n  const { data } = await claude.post('/messages', {\n    model: \"claude-opus-4-5\",\n    max_tokens: 4000,\n    messages: [{ role: \"user\", content: prompt }]\n  });\n\n  return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim());\n}"
      },
      {
        "title": "Validation Signal Scorer",
        "body": "async function scoreOpportunities(ideas, rawData) {\n  const prompt = `\nScore each SaaS idea based on the evidence in the raw data.\nApply the Rob Walling (TinySeed) and Paul Graham opportunity frameworks.\n\nIDEAS TO SCORE:\n${JSON.stringify(ideas.saasIdeas, null, 2)}\n\nRAW DATA SIGNALS:\n- Total reviews analyzed: ${rawData.length}\n- Sources: ${[...new Set(rawData.map(r => r.source))].join(', ')}\n- Top frustration themes: ${JSON.stringify(ideas.marketGaps?.slice(0, 5))}\n\nRespond ONLY in this JSON format:\n{\n  \"scoredIdeas\": [\n    {\n      \"rank\": 1,\n      \"name\": \"product name\",\n      \"scores\": {\n        \"painLevel\":       { \"score\": 9, \"reasoning\": \"why\" },\n        \"marketSize\":      { \"score\": 7, \"reasoning\": \"why\" },\n        \"competition\":     { \"score\": 8, \"reasoning\": \"why\" },\n        \"buildability\":    { \"score\": 6, \"reasoning\": \"why\" },\n        \"monetization\":    { \"score\": 8, \"reasoning\": \"why\" },\n        \"founderFit\":      { \"score\": 7, \"reasoning\": \"why\" }\n      },\n      \"overallScore\": 7.5,\n      \"verdict\": \"🔥 Build this | ✅ Worth exploring | ⚠️ Risky | ❌ Skip\",\n      \"nextStep\": \"concrete first action to validate this idea\"\n    }\n  ],\n  \"winnerIdea\": \"name of the single best opportunity\",\n  \"executiveSummary\": \"2-3 sentence summary of the full analysis\"\n}\n`;\n\n  const { data } = await claude.post('/messages', {\n    model: \"claude-opus-4-5\",\n    max_tokens: 2500,\n    messages: [{ role: \"user\", content: prompt }]\n  });\n\n  return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim());\n}"
      },
      {
        "title": "Layer 3 — Opportunity Report Generator",
        "body": "import { writeFileSync } from 'fs';\n\nfunction generateMarkdownReport(frustrations, gaps, scored, rawDataCount) {\n  const top = scored.scoredIdeas.slice(0, 3);\n  const date = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n\n  return `# 🎯 Business Opportunity Report\n**Niche:** ${TARGET_NICHE} | **Date:** ${date} | **Data Points Analyzed:** ${rawDataCount}\n\n---\n\n## Executive Summary\n${scored.executiveSummary}\n\n**🏆 Winner Idea: ${scored.winnerIdea}**\n\n---\n\n## Top Market Gaps Identified\n\n${gaps.marketGaps?.slice(0, 5).map((g, i) =>\n  `### ${i + 1}. ${g.gap}\n- **Evidence:** ${g.evidenceStrength} | **Market:** ${g.estimatedMarketSize} | **Competition:** ${g.competitionLevel}\n- **Urgency:** ${g.urgency}`\n).join('\\n\\n')}\n\n---\n\n## Top 3 SaaS Opportunities\n\n${top.map(idea => `### ${idea.rank}. ${idea.name} — Score: ${idea.overallScore}/10 ${idea.verdict}\n\n${gaps.saasIdeas?.find(i => i.name === idea.name)?.oneLiner || \"\"}\n\n| Dimension | Score | Notes |\n|---|---|---|\n| Pain Level | ${idea.scores.painLevel.score}/10 | ${idea.scores.painLevel.reasoning} |\n| Market Size | ${idea.scores.marketSize.score}/10 | ${idea.scores.marketSize.reasoning} |\n| Competition | ${idea.scores.competition.score}/10 | ${idea.scores.competition.reasoning} |\n| Buildability | ${idea.scores.buildability.score}/10 | ${idea.scores.buildability.reasoning} |\n| Monetization | ${idea.scores.monetization.score}/10 | ${idea.scores.monetization.reasoning} |\n\n**Next Step:** ${idea.nextStep}`\n).join('\\n\\n---\\n\\n')}\n\n---\n\n## Top Customer Frustrations\n\n${frustrations.frustrations?.slice(0, 8).map((f, i) =>\n  `**${i + 1}. ${f.theme}** (Intensity: ${f.emotionalIntensity}/10 | Frequency: ${f.frequency})\n> \"${f.evidenceQuotes?.[0] || 'No quote available'}\"\n${f.description}`\n).join('\\n\\n')}\n\n---\n\n## Quick Wins (Ship in Days)\n\n${gaps.quickWins?.map(q =>\n  `- **${q.idea}** | Time to MVP: ${q.timeToMVP} | Validate by: ${q.validationMethod}`\n).join('\\n')}\n\n---\n*Generated by Hidden Business Opportunity Detector • Powered by Apify + Claude*\n`;\n}"
      },
      {
        "title": "Master Orchestrator — Full Pipeline",
        "body": "async function runOpportunityDetector(niche = TARGET_NICHE) {\n  console.log(`\\n🎯 Opportunity Detector started — ${niche}`);\n  console.log(`Timestamp: ${new Date().toISOString()}\\n`);\n\n  try {\n    // STEP 1 — Mine all data sources in parallel\n    console.log(\"[1/5] Mining data sources...\");\n    const [appReviews, amazonReviews, redditData, productIntel] = await Promise.all([\n      scrapeAppReviews(),\n      scrapeAmazonReviews(),\n      scrapeRedditFrustrations(),\n      scrapeProductIntelligence()\n    ]);\n\n    const allData = [...appReviews, ...amazonReviews, ...redditData, ...productIntel];\n    console.log(`  ✅ ${allData.length} data points collected`);\n    console.log(`     App reviews: ${appReviews.length} | Amazon: ${amazonReviews.length}`);\n    console.log(`     Reddit: ${redditData.length} | Product intel: ${productIntel.length}`);\n\n    // STEP 2 — Extract frustrations\n    console.log(\"\\n[2/5] Extracting frustrations with Claude...\");\n    const frustrations = await extractFrustrations(allData);\n    console.log(`  ✅ ${frustrations.frustrations?.length} frustration themes identified`);\n    console.log(`  ✅ ${frustrations.featureRequests?.length} feature requests found`);\n\n    // STEP 3 — Analyze market gaps and generate SaaS ideas\n    console.log(\"\\n[3/5] Analyzing market gaps...\");\n    const gaps = await analyzeMarketGaps(frustrations, productIntel);\n    console.log(`  ✅ ${gaps.marketGaps?.length} gaps identified`);\n    console.log(`  ✅ ${gaps.saasIdeas?.length} SaaS ideas generated`);\n\n    // STEP 4 — Score all opportunities\n    console.log(\"\\n[4/5] Scoring opportunities...\");\n    const scored = await scoreOpportunities(gaps, allData);\n    console.log(`  ✅ Ideas scored | Winner: ${scored.winnerIdea}`);\n\n    // STEP 5 — Generate report\n    console.log(\"\\n[5/5] Generating report...\");\n    const report = generateMarkdownReport(frustrations, gaps, scored, allData.length);\n    writeFileSync(`./opportunity-report-${Date.now()}.md`, report);\n\n    const outputJSON = {\n      niche,\n      analyzedAt: new Date().toISOString(),\n      dataPoints: allData.length,\n      frustrationThemes: frustrations.frustrations?.length,\n      marketGaps: gaps.marketGaps,\n      saasIdeas: scored.scoredIdeas,\n      winnerIdea: scored.winnerIdea,\n      quickWins: gaps.quickWins,\n      executiveSummary: scored.executiveSummary\n    };\n\n    writeFileSync(`./opportunity-data-${Date.now()}.json`, JSON.stringify(outputJSON, null, 2));\n    console.log(\"\\n✅ Reports saved to disk\");\n\n    // Optional: push to Slack\n    if (process.env.SLACK_WEBHOOK_URL) {\n      await axios.post(process.env.SLACK_WEBHOOK_URL, {\n        text: `🎯 *Opportunity Report Ready — ${niche}*\\n` +\n              `📊 ${allData.length} data points analyzed\\n` +\n              `🏆 Top idea: *${scored.winnerIdea}*\\n` +\n              `💬 ${scored.executiveSummary}`\n      });\n    }\n\n    return outputJSON;\n\n  } catch (err) {\n    console.error(\"Pipeline error:\", err.message);\n    throw err;\n  }\n}\n\n// Run immediately\nrunOpportunityDetector(\"project management tools\");"
      },
      {
        "title": "Environment Variables",
        "body": "# .env\nAPIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx\nCLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx\n\n# Optional notifications\nSLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/xxx/xxx\nNOTION_API_KEY=secret_xxxxxxxxxxxxxxxx"
      },
      {
        "title": "Normalized Opportunity Output Schema",
        "body": "{\n  \"niche\": \"project management\",\n  \"analyzedAt\": \"2025-02-25T10:00:00Z\",\n  \"dataPoints\": 380,\n  \"winnerIdea\": \"AutoStandup\",\n  \"saasIdeas\": [\n    {\n      \"rank\": 1,\n      \"name\": \"AutoStandup\",\n      \"oneLiner\": \"Async standups that actually get filled out\",\n      \"overallScore\": 8.5,\n      \"verdict\": \"🔥 Build this\",\n      \"targetCustomer\": \"Remote engineering teams 5-50 people\",\n      \"estimatedMRR\": \"$12,000 at 100 customers ($120/mo per team)\",\n      \"timeToMVP\": \"3 weeks\",\n      \"nextStep\": \"Post in r/remotework and r/SaaS — ask if this is a real problem\",\n      \"validationSignals\": [\n        \"47 Reddit posts complaining about standups being ignored\",\n        \"3-star Slack reviews: 'nobody fills them out'\"\n      ]\n    }\n  ],\n  \"quickWins\": [\n    {\n      \"idea\": \"Notion template for async standups\",\n      \"timeToMVP\": \"2 days\",\n      \"validationMethod\": \"Post on Gumroad, see if anyone pays $9\"\n    }\n  ]\n}"
      },
      {
        "title": "Best Practices",
        "body": "Focus on 1–3 star reviews — that's where the real pain lives\nScrape at least 200+ reviews per competitor for statistically significant patterns\nAlways include a \"why is there no tool for X\" Reddit search — goldmine for gaps\nCross-validate: an idea is strong only if the same frustration appears in 3+ sources\nThe Quick Wins section is perfect for validation before building — ship a landing page first\nRe-run the pipeline on a new niche weekly to build a pipeline of ideas\nTrack which ideas get the most Slack/Notion engagement from your team"
      },
      {
        "title": "Error Handling",
        "body": "try {\n  const data = await scrapeAppReviews();\n  return data;\n} catch (error) {\n  if (error.statusCode === 401) throw new Error(\"Invalid Apify token\");\n  if (error.statusCode === 429) throw new Error(\"Rate limit — reduce concurrent scrapers\");\n  if (error.message.includes(\"actor\")) throw new Error(\"Actor not found — verify actor ID\");\n  throw error;\n}"
      },
      {
        "title": "Requirements",
        "body": "Apify account → https://www.apify.com/?fpr=dx06p\nClaude / OpenClaw API key\nNode.js 18+ with apify-client, axios, node-cron, fs-extra\nOptional: Slack, Notion, or Airtable for team collaboration on the output"
      }
    ],
    "body": "Hidden Business Opportunity Detector Skill\nOverview\n\nThis skill builds an automated business intelligence engine that:\n\nApify scrapes App Store reviews, Amazon reviews, Reddit, niche forums, and Product Hunt\nClaude (OpenClaw) deep-analyzes the raw frustrations, recurring requests, and unmet needs\nProduces a structured market gap report with validated SaaS ideas, scored by opportunity size\n\nThis is how the best indie hackers and founders find their next product — systematically.\n\n🔗 Apify: https://www.apify.com/?fpr=dx06p\n\nWhat This Skill Does\nScrape App Store & Google Play reviews to find what users hate about existing apps\nScrape Amazon reviews (1–2 stars) to extract product frustrations at scale\nMine Reddit niche communities for recurring complaints and feature requests\nCrawl niche forums and communities for unmet needs\nScrape Product Hunt for emerging tools and gaps in the market\nFeed all raw data into Claude for structured opportunity analysis\nOutput a ranked list of business opportunities with validation signals\nGenerate SaaS idea briefs with positioning, features, and GTM angle\nArchitecture Overview\n┌─────────────────────────────────────────────────────────────────┐\n│           HIDDEN BUSINESS OPPORTUNITY DETECTOR                  │\n│                                                                 │\n│  ┌─────────────────────────────────────────────────────────┐   │\n│  │  LAYER 1 — DATA MINING (Apify)                          │   │\n│  │  App Store │ Google Play │ Amazon │ Reddit │ Forums      │   │\n│  │  Product Hunt │ G2 │ Trustpilot │ Indie Hackers          │   │\n│  └──────────────────────────┬──────────────────────────────┘   │\n│                             │                                   │\n│  ┌──────────────────────────▼──────────────────────────────┐   │\n│  │  LAYER 2 — OPPORTUNITY ANALYSIS ENGINE (Claude)         │   │\n│  │                                                         │   │\n│  │  • Frustration Extractor  → what people hate/struggle   │   │\n│  │  • Pattern Detector       → recurring complaints        │   │\n│  │  • Gap Analyzer           → what nobody is building     │   │\n│  │  • Opportunity Scorer     → market size x pain level    │   │\n│  │  • SaaS Idea Generator    → concrete product briefs     │   │\n│  └──────────────────────────┬──────────────────────────────┘   │\n│                             │                                   │\n│  ┌──────────────────────────▼──────────────────────────────┐   │\n│  │  LAYER 3 — OPPORTUNITY REPORT                           │   │\n│  │  Ranked ideas │ Validation signals │ GTM angles          │   │\n│  │  JSON export │ Markdown report │ Notion / Slack push     │   │\n│  └─────────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────────┘\n\nStep 1 — Get Your API Keys\nApify\nSign up at https://www.apify.com/?fpr=dx06p\nGo to Settings → Integrations\nCopy your token:\nexport APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx\n\nClaude / OpenClaw\nexport CLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx\n\nStep 2 — Install Dependencies\nnpm install apify-client axios node-cron dotenv fs-extra\n\nLayer 1 — Multi-Source Data Miner (Apify)\nMine App Store & Google Play Reviews\nimport ApifyClient from 'apify-client';\n\nconst apify = new ApifyClient({ token: process.env.APIFY_TOKEN });\n\n// Define the niche and competitor apps to analyze\nconst TARGET_NICHE = \"project management\";\nconst COMPETITOR_APPS = [\n  { name: \"Notion\",   appStoreId: \"1232780281\", playStoreId: \"notion.id\" },\n  { name: \"Asana\",    appStoreId: \"489969512\",  playStoreId: \"com.asana.app\" },\n  { name: \"Trello\",   appStoreId: \"461504587\",  playStoreId: \"com.trello\" },\n  { name: \"Monday\",   appStoreId: \"1298450011\", playStoreId: \"com.monday.monday\" }\n];\n\nasync function scrapeAppReviews() {\n  console.log(\"📱 Scraping App Store & Play Store reviews...\");\n\n  const jobs = COMPETITOR_APPS.map(app =>\n    Promise.all([\n\n      // App Store — focus on 1-3 star reviews (the gold mine)\n      apify.actor(\"apify/apple-app-store-scraper\").call({\n        appIds: [app.appStoreId],\n        maxReviews: 100,\n        filterStars: [1, 2, 3]\n      }).then(run => run.dataset().getData())\n        .then(d => d.items.map(r => ({\n          source: \"app_store\",\n          appName: app.name,\n          rating: r.rating,\n          review: r.review,\n          title: r.title,\n          date: r.date,\n          country: r.country\n        }))),\n\n      // Google Play Store\n      apify.actor(\"apify/google-play-scraper\").call({\n        appId: app.playStoreId,\n        maxReviews: 100,\n        filterScore: [1, 2, 3]\n      }).then(run => run.dataset().getData())\n        .then(d => d.items.map(r => ({\n          source: \"google_play\",\n          appName: app.name,\n          rating: r.score,\n          review: r.text,\n          title: r.title || \"\",\n          date: r.date,\n          thumbsUp: r.thumbsUp\n        })))\n\n    ]).then(results => results.flat())\n  );\n\n  const allReviews = await Promise.all(jobs);\n  return allReviews.flat();\n}\n\nMine Amazon Reviews (1-3 Stars)\nasync function scrapeAmazonReviews() {\n  console.log(\"📦 Scraping Amazon negative reviews...\");\n\n  // Target products in your niche\n  const TARGET_PRODUCTS = [\n    \"https://www.amazon.com/dp/B08N5WRWNW\", // productivity tool example\n    \"https://www.amazon.com/dp/B09G9HD6PD\"\n  ];\n\n  const jobs = TARGET_PRODUCTS.map(url =>\n    apify.actor(\"apify/amazon-reviews-scraper\").call({\n      startUrls: [{ url }],\n      maxReviews: 100,\n      filterByStar: [\"one_star\", \"two_star\", \"three_star\"]\n    }).then(run => run.dataset().getData())\n      .then(d => d.items.map(r => ({\n        source: \"amazon\",\n        productTitle: r.productTitle,\n        rating: r.ratingScore,\n        review: r.reviewText,\n        title: r.reviewTitle,\n        date: r.date,\n        helpfulVotes: r.helpfulVotes,\n        verifiedPurchase: r.verifiedPurchase\n      })))\n  );\n\n  const results = await Promise.all(jobs);\n  return results.flat();\n}\n\nMine Reddit Niche Communities\nasync function scrapeRedditFrustrations() {\n  console.log(\"💬 Scraping Reddit communities...\");\n\n  const SUBREDDITS = [\n    \"r/Entrepreneur\",\n    \"r/SaaS\",\n    \"r/smallbusiness\",\n    \"r/productivity\",\n    \"r/projectmanagement\",\n    \"r/startups\",\n    \"r/indiehackers\"\n  ];\n\n  const [posts, searchResults] = await Promise.all([\n\n    // Hot/top posts in subreddits\n    apify.actor(\"apify/reddit-scraper\").call({\n      startUrls: SUBREDDITS.map(s => ({ url: `https://www.reddit.com/${s}/` })),\n      maxPostCount: 30,\n      maxComments: 15,\n      sort: \"top\"\n    }).then(run => run.dataset().getData()),\n\n    // Search for frustration signals\n    apify.actor(\"apify/reddit-search-scraper\").call({\n      queries: [\n        `${TARGET_NICHE} frustrated wish`,\n        `${TARGET_NICHE} hate problem broken`,\n        `${TARGET_NICHE} alternative looking for better`,\n        `${TARGET_NICHE} feature request need`,\n        `${TARGET_NICHE} why is there no tool`\n      ],\n      maxItems: 50\n    }).then(run => run.dataset().getData())\n\n  ]);\n\n  return [\n    ...posts.items.map(p => ({\n      source: \"reddit_post\",\n      subreddit: p.subreddit,\n      title: p.title,\n      text: p.selftext,\n      score: p.score,\n      comments: p.numComments,\n      url: p.url\n    })),\n    ...searchResults.items.map(p => ({\n      source: \"reddit_search\",\n      subreddit: p.subreddit,\n      title: p.title,\n      text: p.selftext,\n      score: p.score,\n      url: p.url\n    }))\n  ];\n}\n\nMine Product Hunt & G2 Reviews\nasync function scrapeProductIntelligence() {\n  console.log(\"🚀 Scraping Product Hunt & review platforms...\");\n\n  const [productHunt, g2] = await Promise.all([\n\n    // Product Hunt — see what's launching and what comments say\n    apify.actor(\"apify/product-hunt-scraper\").call({\n      mode: \"search\",\n      searchQuery: TARGET_NICHE,\n      maxItems: 30\n    }).then(run => run.dataset().getData())\n      .then(d => d.items.map(p => ({\n        source: \"product_hunt\",\n        name: p.name,\n        tagline: p.tagline,\n        description: p.description,\n        upvotes: p.votesCount,\n        comments: p.commentsCount,\n        topics: p.topics,\n        url: p.url\n      }))),\n\n    // G2 reviews for competitor software\n    apify.actor(\"apify/website-content-crawler\").call({\n      startUrls: [\n        { url: `https://www.g2.com/categories/${TARGET_NICHE.replace(/\\s+/g, '-')}-software` }\n      ],\n      maxCrawlingDepth: 1,\n      maxRequestsPerCrawl: 10\n    }).then(run => run.dataset().getData())\n      .then(d => d.items.map(p => ({\n        source: \"g2\",\n        text: p.text?.slice(0, 2000),\n        url: p.url\n      })))\n\n  ]);\n\n  return [...productHunt, ...g2];\n}\n\nLayer 2 — Opportunity Analysis Engine (Claude)\nFrustration Extractor\nimport axios from 'axios';\n\nconst claude = axios.create({\n  baseURL: 'https://api.anthropic.com/v1',\n  headers: {\n    'x-api-key': process.env.CLAUDE_API_KEY,\n    'anthropic-version': '2023-06-01',\n    'Content-Type': 'application/json'\n  }\n});\n\nasync function extractFrustrations(allData) {\n  const prompt = `\nYou are a world-class product researcher and market analyst.\n\nAnalyze this raw data from app reviews, Amazon reviews, Reddit posts, and product listings.\nExtract every customer frustration, unmet need, and recurring complaint.\n\nNICHE: ${TARGET_NICHE}\n\nRAW DATA (sample):\n${JSON.stringify(allData.slice(0, 30), null, 2)}\n\nRespond ONLY in this JSON format:\n{\n  \"frustrations\": [\n    {\n      \"theme\": \"short label\",\n      \"description\": \"what users are frustrated about\",\n      \"frequency\": \"how often this comes up (high/medium/low)\",\n      \"emotionalIntensity\": \"how angry/upset users are (1-10)\",\n      \"affectedSegment\": \"who experiences this most\",\n      \"evidenceQuotes\": [\"direct quote 1\", \"direct quote 2\"],\n      \"sources\": [\"app_store\", \"reddit\"]\n    }\n  ],\n  \"featureRequests\": [\n    {\n      \"request\": \"what users are explicitly asking for\",\n      \"frequency\": \"high | medium | low\",\n      \"currentWorkaround\": \"what users do today instead\",\n      \"evidenceQuotes\": [\"quote\"]\n    }\n  ],\n  \"recurringPatterns\": [\n    \"pattern 1 observed across multiple sources\",\n    \"pattern 2\"\n  ],\n  \"underservedSegments\": [\n    {\n      \"segment\": \"who is being ignored\",\n      \"unmetNeed\": \"what they need\",\n      \"currentSolution\": \"what they use today despite it being bad\"\n    }\n  ]\n}\n`;\n\n  const { data } = await claude.post('/messages', {\n    model: \"claude-opus-4-5\",\n    max_tokens: 3000,\n    messages: [{ role: \"user\", content: prompt }]\n  });\n\n  return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim());\n}\n\nMarket Gap Analyzer & SaaS Idea Generator\nasync function analyzeMarketGaps(frustrations, productIntel) {\n  const prompt = `\nYou are a serial entrepreneur and SaaS product strategist.\n\nBased on these validated customer frustrations and market intelligence, identify\nthe highest-potential business opportunities and generate concrete SaaS ideas.\n\nFRUSTRATIONS & PATTERNS:\n${JSON.stringify(frustrations, null, 2)}\n\nMARKET INTELLIGENCE (existing products):\n${JSON.stringify(productIntel.slice(0, 10), null, 2)}\n\nRespond ONLY in this JSON format:\n{\n  \"marketGaps\": [\n    {\n      \"gap\": \"what is clearly missing from the market\",\n      \"evidenceStrength\": \"strong | moderate | weak\",\n      \"estimatedMarketSize\": \"niche | small | medium | large\",\n      \"competitionLevel\": \"none | low | medium | high\",\n      \"urgency\": \"nice-to-have | important | critical\"\n    }\n  ],\n  \"saasIdeas\": [\n    {\n      \"rank\": 1,\n      \"name\": \"working product name\",\n      \"oneLiner\": \"X for Y — one sentence pitch\",\n      \"problem\": \"exact problem it solves\",\n      \"targetCustomer\": \"specific ICP (ideal customer profile)\",\n      \"coreFeatures\": [\"feature 1\", \"feature 2\", \"feature 3\"],\n      \"differentiator\": \"why this beats existing solutions\",\n      \"monetization\": \"pricing model (per seat | usage | freemium | etc)\",\n      \"estimatedMRR\": \"rough MRR potential at 100 customers\",\n      \"validationSignals\": [\"signal from data that confirms the need\"],\n      \"gtmAngle\": \"how to acquire first 100 customers\",\n      \"buildComplexity\": \"low | medium | high\",\n      \"opportunityScore\": 8,\n      \"risksAndChallenges\": [\"risk 1\", \"risk 2\"]\n    }\n  ],\n  \"quickWins\": [\n    {\n      \"idea\": \"simplest possible version of a solution\",\n      \"timeToMVP\": \"estimated days/weeks to build\",\n      \"validationMethod\": \"how to validate before building\"\n    }\n  ],\n  \"topRecommendation\": \"single best opportunity with 1-paragraph reasoning\"\n}\n`;\n\n  const { data } = await claude.post('/messages', {\n    model: \"claude-opus-4-5\",\n    max_tokens: 4000,\n    messages: [{ role: \"user\", content: prompt }]\n  });\n\n  return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim());\n}\n\nValidation Signal Scorer\nasync function scoreOpportunities(ideas, rawData) {\n  const prompt = `\nScore each SaaS idea based on the evidence in the raw data.\nApply the Rob Walling (TinySeed) and Paul Graham opportunity frameworks.\n\nIDEAS TO SCORE:\n${JSON.stringify(ideas.saasIdeas, null, 2)}\n\nRAW DATA SIGNALS:\n- Total reviews analyzed: ${rawData.length}\n- Sources: ${[...new Set(rawData.map(r => r.source))].join(', ')}\n- Top frustration themes: ${JSON.stringify(ideas.marketGaps?.slice(0, 5))}\n\nRespond ONLY in this JSON format:\n{\n  \"scoredIdeas\": [\n    {\n      \"rank\": 1,\n      \"name\": \"product name\",\n      \"scores\": {\n        \"painLevel\":       { \"score\": 9, \"reasoning\": \"why\" },\n        \"marketSize\":      { \"score\": 7, \"reasoning\": \"why\" },\n        \"competition\":     { \"score\": 8, \"reasoning\": \"why\" },\n        \"buildability\":    { \"score\": 6, \"reasoning\": \"why\" },\n        \"monetization\":    { \"score\": 8, \"reasoning\": \"why\" },\n        \"founderFit\":      { \"score\": 7, \"reasoning\": \"why\" }\n      },\n      \"overallScore\": 7.5,\n      \"verdict\": \"🔥 Build this | ✅ Worth exploring | ⚠️ Risky | ❌ Skip\",\n      \"nextStep\": \"concrete first action to validate this idea\"\n    }\n  ],\n  \"winnerIdea\": \"name of the single best opportunity\",\n  \"executiveSummary\": \"2-3 sentence summary of the full analysis\"\n}\n`;\n\n  const { data } = await claude.post('/messages', {\n    model: \"claude-opus-4-5\",\n    max_tokens: 2500,\n    messages: [{ role: \"user\", content: prompt }]\n  });\n\n  return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim());\n}\n\nLayer 3 — Opportunity Report Generator\nimport { writeFileSync } from 'fs';\n\nfunction generateMarkdownReport(frustrations, gaps, scored, rawDataCount) {\n  const top = scored.scoredIdeas.slice(0, 3);\n  const date = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n\n  return `# 🎯 Business Opportunity Report\n**Niche:** ${TARGET_NICHE} | **Date:** ${date} | **Data Points Analyzed:** ${rawDataCount}\n\n---\n\n## Executive Summary\n${scored.executiveSummary}\n\n**🏆 Winner Idea: ${scored.winnerIdea}**\n\n---\n\n## Top Market Gaps Identified\n\n${gaps.marketGaps?.slice(0, 5).map((g, i) =>\n  `### ${i + 1}. ${g.gap}\n- **Evidence:** ${g.evidenceStrength} | **Market:** ${g.estimatedMarketSize} | **Competition:** ${g.competitionLevel}\n- **Urgency:** ${g.urgency}`\n).join('\\n\\n')}\n\n---\n\n## Top 3 SaaS Opportunities\n\n${top.map(idea => `### ${idea.rank}. ${idea.name} — Score: ${idea.overallScore}/10 ${idea.verdict}\n\n${gaps.saasIdeas?.find(i => i.name === idea.name)?.oneLiner || \"\"}\n\n| Dimension | Score | Notes |\n|---|---|---|\n| Pain Level | ${idea.scores.painLevel.score}/10 | ${idea.scores.painLevel.reasoning} |\n| Market Size | ${idea.scores.marketSize.score}/10 | ${idea.scores.marketSize.reasoning} |\n| Competition | ${idea.scores.competition.score}/10 | ${idea.scores.competition.reasoning} |\n| Buildability | ${idea.scores.buildability.score}/10 | ${idea.scores.buildability.reasoning} |\n| Monetization | ${idea.scores.monetization.score}/10 | ${idea.scores.monetization.reasoning} |\n\n**Next Step:** ${idea.nextStep}`\n).join('\\n\\n---\\n\\n')}\n\n---\n\n## Top Customer Frustrations\n\n${frustrations.frustrations?.slice(0, 8).map((f, i) =>\n  `**${i + 1}. ${f.theme}** (Intensity: ${f.emotionalIntensity}/10 | Frequency: ${f.frequency})\n> \"${f.evidenceQuotes?.[0] || 'No quote available'}\"\n${f.description}`\n).join('\\n\\n')}\n\n---\n\n## Quick Wins (Ship in Days)\n\n${gaps.quickWins?.map(q =>\n  `- **${q.idea}** | Time to MVP: ${q.timeToMVP} | Validate by: ${q.validationMethod}`\n).join('\\n')}\n\n---\n*Generated by Hidden Business Opportunity Detector • Powered by Apify + Claude*\n`;\n}\n\nMaster Orchestrator — Full Pipeline\nasync function runOpportunityDetector(niche = TARGET_NICHE) {\n  console.log(`\\n🎯 Opportunity Detector started — ${niche}`);\n  console.log(`Timestamp: ${new Date().toISOString()}\\n`);\n\n  try {\n    // STEP 1 — Mine all data sources in parallel\n    console.log(\"[1/5] Mining data sources...\");\n    const [appReviews, amazonReviews, redditData, productIntel] = await Promise.all([\n      scrapeAppReviews(),\n      scrapeAmazonReviews(),\n      scrapeRedditFrustrations(),\n      scrapeProductIntelligence()\n    ]);\n\n    const allData = [...appReviews, ...amazonReviews, ...redditData, ...productIntel];\n    console.log(`  ✅ ${allData.length} data points collected`);\n    console.log(`     App reviews: ${appReviews.length} | Amazon: ${amazonReviews.length}`);\n    console.log(`     Reddit: ${redditData.length} | Product intel: ${productIntel.length}`);\n\n    // STEP 2 — Extract frustrations\n    console.log(\"\\n[2/5] Extracting frustrations with Claude...\");\n    const frustrations = await extractFrustrations(allData);\n    console.log(`  ✅ ${frustrations.frustrations?.length} frustration themes identified`);\n    console.log(`  ✅ ${frustrations.featureRequests?.length} feature requests found`);\n\n    // STEP 3 — Analyze market gaps and generate SaaS ideas\n    console.log(\"\\n[3/5] Analyzing market gaps...\");\n    const gaps = await analyzeMarketGaps(frustrations, productIntel);\n    console.log(`  ✅ ${gaps.marketGaps?.length} gaps identified`);\n    console.log(`  ✅ ${gaps.saasIdeas?.length} SaaS ideas generated`);\n\n    // STEP 4 — Score all opportunities\n    console.log(\"\\n[4/5] Scoring opportunities...\");\n    const scored = await scoreOpportunities(gaps, allData);\n    console.log(`  ✅ Ideas scored | Winner: ${scored.winnerIdea}`);\n\n    // STEP 5 — Generate report\n    console.log(\"\\n[5/5] Generating report...\");\n    const report = generateMarkdownReport(frustrations, gaps, scored, allData.length);\n    writeFileSync(`./opportunity-report-${Date.now()}.md`, report);\n\n    const outputJSON = {\n      niche,\n      analyzedAt: new Date().toISOString(),\n      dataPoints: allData.length,\n      frustrationThemes: frustrations.frustrations?.length,\n      marketGaps: gaps.marketGaps,\n      saasIdeas: scored.scoredIdeas,\n      winnerIdea: scored.winnerIdea,\n      quickWins: gaps.quickWins,\n      executiveSummary: scored.executiveSummary\n    };\n\n    writeFileSync(`./opportunity-data-${Date.now()}.json`, JSON.stringify(outputJSON, null, 2));\n    console.log(\"\\n✅ Reports saved to disk\");\n\n    // Optional: push to Slack\n    if (process.env.SLACK_WEBHOOK_URL) {\n      await axios.post(process.env.SLACK_WEBHOOK_URL, {\n        text: `🎯 *Opportunity Report Ready — ${niche}*\\n` +\n              `📊 ${allData.length} data points analyzed\\n` +\n              `🏆 Top idea: *${scored.winnerIdea}*\\n` +\n              `💬 ${scored.executiveSummary}`\n      });\n    }\n\n    return outputJSON;\n\n  } catch (err) {\n    console.error(\"Pipeline error:\", err.message);\n    throw err;\n  }\n}\n\n// Run immediately\nrunOpportunityDetector(\"project management tools\");\n\nEnvironment Variables\n# .env\nAPIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx\nCLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx\n\n# Optional notifications\nSLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/xxx/xxx\nNOTION_API_KEY=secret_xxxxxxxxxxxxxxxx\n\nNormalized Opportunity Output Schema\n{\n  \"niche\": \"project management\",\n  \"analyzedAt\": \"2025-02-25T10:00:00Z\",\n  \"dataPoints\": 380,\n  \"winnerIdea\": \"AutoStandup\",\n  \"saasIdeas\": [\n    {\n      \"rank\": 1,\n      \"name\": \"AutoStandup\",\n      \"oneLiner\": \"Async standups that actually get filled out\",\n      \"overallScore\": 8.5,\n      \"verdict\": \"🔥 Build this\",\n      \"targetCustomer\": \"Remote engineering teams 5-50 people\",\n      \"estimatedMRR\": \"$12,000 at 100 customers ($120/mo per team)\",\n      \"timeToMVP\": \"3 weeks\",\n      \"nextStep\": \"Post in r/remotework and r/SaaS — ask if this is a real problem\",\n      \"validationSignals\": [\n        \"47 Reddit posts complaining about standups being ignored\",\n        \"3-star Slack reviews: 'nobody fills them out'\"\n      ]\n    }\n  ],\n  \"quickWins\": [\n    {\n      \"idea\": \"Notion template for async standups\",\n      \"timeToMVP\": \"2 days\",\n      \"validationMethod\": \"Post on Gumroad, see if anyone pays $9\"\n    }\n  ]\n}\n\nBest Practices\nFocus on 1–3 star reviews — that's where the real pain lives\nScrape at least 200+ reviews per competitor for statistically significant patterns\nAlways include a \"why is there no tool for X\" Reddit search — goldmine for gaps\nCross-validate: an idea is strong only if the same frustration appears in 3+ sources\nThe Quick Wins section is perfect for validation before building — ship a landing page first\nRe-run the pipeline on a new niche weekly to build a pipeline of ideas\nTrack which ideas get the most Slack/Notion engagement from your team\nError Handling\ntry {\n  const data = await scrapeAppReviews();\n  return data;\n} catch (error) {\n  if (error.statusCode === 401) throw new Error(\"Invalid Apify token\");\n  if (error.statusCode === 429) throw new Error(\"Rate limit — reduce concurrent scrapers\");\n  if (error.message.includes(\"actor\")) throw new Error(\"Actor not found — verify actor ID\");\n  throw error;\n}\n\nRequirements\nApify account → https://www.apify.com/?fpr=dx06p\nClaude / OpenClaw API key\nNode.js 18+ with apify-client, axios, node-cron, fs-extra\nOptional: Slack, Notion, or Airtable for team collaboration on the output"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/g4dr/business-opportunity-detector",
    "publisherUrl": "https://clawhub.ai/g4dr/business-opportunity-detector",
    "owner": "g4dr",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/business-opportunity-detector",
    "downloadUrl": "https://openagent3.xyz/downloads/business-opportunity-detector",
    "agentUrl": "https://openagent3.xyz/skills/business-opportunity-detector/agent",
    "manifestUrl": "https://openagent3.xyz/skills/business-opportunity-detector/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/business-opportunity-detector/agent.md"
  }
}