Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Automatically scrapes and analyzes multi-platform user reviews to identify, score, and report validated hidden SaaS business opportunities and market gaps.
Automatically scrapes and analyzes multi-platform user reviews to identify, score, and report validated hidden SaaS business opportunities and market gaps.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
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.
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.
This skill builds an automated business intelligence engine that: Apify scrapes App Store reviews, Amazon reviews, Reddit, niche forums, and Product Hunt Claude (OpenClaw) deep-analyzes the raw frustrations, recurring requests, and unmet needs Produces a structured market gap report with validated SaaS ideas, scored by opportunity size This is how the best indie hackers and founders find their next product โ systematically. ๐ Apify: https://www.apify.com/?fpr=dx06p
Scrape App Store & Google Play reviews to find what users hate about existing apps Scrape Amazon reviews (1โ2 stars) to extract product frustrations at scale Mine Reddit niche communities for recurring complaints and feature requests Crawl niche forums and communities for unmet needs Scrape Product Hunt for emerging tools and gaps in the market Feed all raw data into Claude for structured opportunity analysis Output a ranked list of business opportunities with validation signals Generate SaaS idea briefs with positioning, features, and GTM angle
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ HIDDEN BUSINESS OPPORTUNITY DETECTOR โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โ LAYER 1 โ DATA MINING (Apify) โ โ โ โ App Store โ Google Play โ Amazon โ Reddit โ Forums โ โ โ โ Product Hunt โ G2 โ Trustpilot โ Indie Hackers โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โ LAYER 2 โ OPPORTUNITY ANALYSIS ENGINE (Claude) โ โ โ โ โ โ โ โ โข Frustration Extractor โ what people hate/struggle โ โ โ โ โข Pattern Detector โ recurring complaints โ โ โ โ โข Gap Analyzer โ what nobody is building โ โ โ โ โข Opportunity Scorer โ market size x pain level โ โ โ โ โข SaaS Idea Generator โ concrete product briefs โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ โ LAYER 3 โ OPPORTUNITY REPORT โ โ โ โ Ranked ideas โ Validation signals โ GTM angles โ โ โ โ JSON export โ Markdown report โ Notion / Slack push โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Sign up at https://www.apify.com/?fpr=dx06p Go to Settings โ Integrations Copy your token: export APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx
export CLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx
npm install apify-client axios node-cron dotenv fs-extra
import ApifyClient from 'apify-client'; const apify = new ApifyClient({ token: process.env.APIFY_TOKEN }); // Define the niche and competitor apps to analyze const TARGET_NICHE = "project management"; const COMPETITOR_APPS = [ { name: "Notion", appStoreId: "1232780281", playStoreId: "notion.id" }, { name: "Asana", appStoreId: "489969512", playStoreId: "com.asana.app" }, { name: "Trello", appStoreId: "461504587", playStoreId: "com.trello" }, { name: "Monday", appStoreId: "1298450011", playStoreId: "com.monday.monday" } ]; async function scrapeAppReviews() { console.log("๐ฑ Scraping App Store & Play Store reviews..."); const jobs = COMPETITOR_APPS.map(app => Promise.all([ // App Store โ focus on 1-3 star reviews (the gold mine) apify.actor("apify/apple-app-store-scraper").call({ appIds: [app.appStoreId], maxReviews: 100, filterStars: [1, 2, 3] }).then(run => run.dataset().getData()) .then(d => d.items.map(r => ({ source: "app_store", appName: app.name, rating: r.rating, review: r.review, title: r.title, date: r.date, country: r.country }))), // Google Play Store apify.actor("apify/google-play-scraper").call({ appId: app.playStoreId, maxReviews: 100, filterScore: [1, 2, 3] }).then(run => run.dataset().getData()) .then(d => d.items.map(r => ({ source: "google_play", appName: app.name, rating: r.score, review: r.text, title: r.title || "", date: r.date, thumbsUp: r.thumbsUp }))) ]).then(results => results.flat()) ); const allReviews = await Promise.all(jobs); return allReviews.flat(); }
async function scrapeAmazonReviews() { console.log("๐ฆ Scraping Amazon negative reviews..."); // Target products in your niche const TARGET_PRODUCTS = [ "https://www.amazon.com/dp/B08N5WRWNW", // productivity tool example "https://www.amazon.com/dp/B09G9HD6PD" ]; const jobs = TARGET_PRODUCTS.map(url => apify.actor("apify/amazon-reviews-scraper").call({ startUrls: [{ url }], maxReviews: 100, filterByStar: ["one_star", "two_star", "three_star"] }).then(run => run.dataset().getData()) .then(d => d.items.map(r => ({ source: "amazon", productTitle: r.productTitle, rating: r.ratingScore, review: r.reviewText, title: r.reviewTitle, date: r.date, helpfulVotes: r.helpfulVotes, verifiedPurchase: r.verifiedPurchase }))) ); const results = await Promise.all(jobs); return results.flat(); }
async function scrapeRedditFrustrations() { console.log("๐ฌ Scraping Reddit communities..."); const SUBREDDITS = [ "r/Entrepreneur", "r/SaaS", "r/smallbusiness", "r/productivity", "r/projectmanagement", "r/startups", "r/indiehackers" ]; const [posts, searchResults] = await Promise.all([ // Hot/top posts in subreddits apify.actor("apify/reddit-scraper").call({ startUrls: SUBREDDITS.map(s => ({ url: `https://www.reddit.com/${s}/` })), maxPostCount: 30, maxComments: 15, sort: "top" }).then(run => run.dataset().getData()), // Search for frustration signals apify.actor("apify/reddit-search-scraper").call({ queries: [ `${TARGET_NICHE} frustrated wish`, `${TARGET_NICHE} hate problem broken`, `${TARGET_NICHE} alternative looking for better`, `${TARGET_NICHE} feature request need`, `${TARGET_NICHE} why is there no tool` ], maxItems: 50 }).then(run => run.dataset().getData()) ]); return [ ...posts.items.map(p => ({ source: "reddit_post", subreddit: p.subreddit, title: p.title, text: p.selftext, score: p.score, comments: p.numComments, url: p.url })), ...searchResults.items.map(p => ({ source: "reddit_search", subreddit: p.subreddit, title: p.title, text: p.selftext, score: p.score, url: p.url })) ]; }
async function scrapeProductIntelligence() { console.log("๐ Scraping Product Hunt & review platforms..."); const [productHunt, g2] = await Promise.all([ // Product Hunt โ see what's launching and what comments say apify.actor("apify/product-hunt-scraper").call({ mode: "search", searchQuery: TARGET_NICHE, maxItems: 30 }).then(run => run.dataset().getData()) .then(d => d.items.map(p => ({ source: "product_hunt", name: p.name, tagline: p.tagline, description: p.description, upvotes: p.votesCount, comments: p.commentsCount, topics: p.topics, url: p.url }))), // G2 reviews for competitor software apify.actor("apify/website-content-crawler").call({ startUrls: [ { url: `https://www.g2.com/categories/${TARGET_NICHE.replace(/\s+/g, '-')}-software` } ], maxCrawlingDepth: 1, maxRequestsPerCrawl: 10 }).then(run => run.dataset().getData()) .then(d => d.items.map(p => ({ source: "g2", text: p.text?.slice(0, 2000), url: p.url }))) ]); return [...productHunt, ...g2]; }
import axios from 'axios'; const claude = axios.create({ baseURL: 'https://api.anthropic.com/v1', headers: { 'x-api-key': process.env.CLAUDE_API_KEY, 'anthropic-version': '2023-06-01', 'Content-Type': 'application/json' } }); async function extractFrustrations(allData) { const prompt = ` You are a world-class product researcher and market analyst. Analyze this raw data from app reviews, Amazon reviews, Reddit posts, and product listings. Extract every customer frustration, unmet need, and recurring complaint. NICHE: ${TARGET_NICHE} RAW DATA (sample): ${JSON.stringify(allData.slice(0, 30), null, 2)} Respond ONLY in this JSON format: { "frustrations": [ { "theme": "short label", "description": "what users are frustrated about", "frequency": "how often this comes up (high/medium/low)", "emotionalIntensity": "how angry/upset users are (1-10)", "affectedSegment": "who experiences this most", "evidenceQuotes": ["direct quote 1", "direct quote 2"], "sources": ["app_store", "reddit"] } ], "featureRequests": [ { "request": "what users are explicitly asking for", "frequency": "high | medium | low", "currentWorkaround": "what users do today instead", "evidenceQuotes": ["quote"] } ], "recurringPatterns": [ "pattern 1 observed across multiple sources", "pattern 2" ], "underservedSegments": [ { "segment": "who is being ignored", "unmetNeed": "what they need", "currentSolution": "what they use today despite it being bad" } ] } `; const { data } = await claude.post('/messages', { model: "claude-opus-4-5", max_tokens: 3000, messages: [{ role: "user", content: prompt }] }); return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim()); }
async function analyzeMarketGaps(frustrations, productIntel) { const prompt = ` You are a serial entrepreneur and SaaS product strategist. Based on these validated customer frustrations and market intelligence, identify the highest-potential business opportunities and generate concrete SaaS ideas. FRUSTRATIONS & PATTERNS: ${JSON.stringify(frustrations, null, 2)} MARKET INTELLIGENCE (existing products): ${JSON.stringify(productIntel.slice(0, 10), null, 2)} Respond ONLY in this JSON format: { "marketGaps": [ { "gap": "what is clearly missing from the market", "evidenceStrength": "strong | moderate | weak", "estimatedMarketSize": "niche | small | medium | large", "competitionLevel": "none | low | medium | high", "urgency": "nice-to-have | important | critical" } ], "saasIdeas": [ { "rank": 1, "name": "working product name", "oneLiner": "X for Y โ one sentence pitch", "problem": "exact problem it solves", "targetCustomer": "specific ICP (ideal customer profile)", "coreFeatures": ["feature 1", "feature 2", "feature 3"], "differentiator": "why this beats existing solutions", "monetization": "pricing model (per seat | usage | freemium | etc)", "estimatedMRR": "rough MRR potential at 100 customers", "validationSignals": ["signal from data that confirms the need"], "gtmAngle": "how to acquire first 100 customers", "buildComplexity": "low | medium | high", "opportunityScore": 8, "risksAndChallenges": ["risk 1", "risk 2"] } ], "quickWins": [ { "idea": "simplest possible version of a solution", "timeToMVP": "estimated days/weeks to build", "validationMethod": "how to validate before building" } ], "topRecommendation": "single best opportunity with 1-paragraph reasoning" } `; const { data } = await claude.post('/messages', { model: "claude-opus-4-5", max_tokens: 4000, messages: [{ role: "user", content: prompt }] }); return JSON.parse(data.content[0].text.replace(/```json|```/g, '').trim()); }
async function runOpportunityDetector(niche = TARGET_NICHE) { console.log(`\n๐ฏ Opportunity Detector started โ ${niche}`); console.log(`Timestamp: ${new Date().toISOString()}\n`); try { // STEP 1 โ Mine all data sources in parallel console.log("[1/5] Mining data sources..."); const [appReviews, amazonReviews, redditData, productIntel] = await Promise.all([ scrapeAppReviews(), scrapeAmazonReviews(), scrapeRedditFrustrations(), scrapeProductIntelligence() ]); const allData = [...appReviews, ...amazonReviews, ...redditData, ...productIntel]; console.log(` โ ${allData.length} data points collected`); console.log(` App reviews: ${appReviews.length} | Amazon: ${amazonReviews.length}`); console.log(` Reddit: ${redditData.length} | Product intel: ${productIntel.length}`); // STEP 2 โ Extract frustrations console.log("\n[2/5] Extracting frustrations with Claude..."); const frustrations = await extractFrustrations(allData); console.log(` โ ${frustrations.frustrations?.length} frustration themes identified`); console.log(` โ ${frustrations.featureRequests?.length} feature requests found`); // STEP 3 โ Analyze market gaps and generate SaaS ideas console.log("\n[3/5] Analyzing market gaps..."); const gaps = await analyzeMarketGaps(frustrations, productIntel); console.log(` โ ${gaps.marketGaps?.length} gaps identified`); console.log(` โ ${gaps.saasIdeas?.length} SaaS ideas generated`); // STEP 4 โ Score all opportunities console.log("\n[4/5] Scoring opportunities..."); const scored = await scoreOpportunities(gaps, allData); console.log(` โ Ideas scored | Winner: ${scored.winnerIdea}`); // STEP 5 โ Generate report console.log("\n[5/5] Generating report..."); const report = generateMarkdownReport(frustrations, gaps, scored, allData.length); writeFileSync(`./opportunity-report-${Date.now()}.md`, report); const outputJSON = { niche, analyzedAt: new Date().toISOString(), dataPoints: allData.length, frustrationThemes: frustrations.frustrations?.length, marketGaps: gaps.marketGaps, saasIdeas: scored.scoredIdeas, winnerIdea: scored.winnerIdea, quickWins: gaps.quickWins, executiveSummary: scored.executiveSummary }; writeFileSync(`./opportunity-data-${Date.now()}.json`, JSON.stringify(outputJSON, null, 2)); console.log("\nโ Reports saved to disk"); // Optional: push to Slack if (process.env.SLACK_WEBHOOK_URL) { await axios.post(process.env.SLACK_WEBHOOK_URL, { text: `๐ฏ *Opportunity Report Ready โ ${niche}*\n` + `๐ ${allData.length} data points analyzed\n` + `๐ Top idea: *${scored.winnerIdea}*\n` + `๐ฌ ${scored.executiveSummary}` }); } return outputJSON; } catch (err) { console.error("Pipeline error:", err.message); throw err; } } // Run immediately runOpportunityDetector("project management tools");
# .env APIFY_TOKEN=apify_api_xxxxxxxxxxxxxxxx CLAUDE_API_KEY=sk-ant-xxxxxxxxxxxxxxxx # Optional notifications SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/xxx/xxx NOTION_API_KEY=secret_xxxxxxxxxxxxxxxx
{ "niche": "project management", "analyzedAt": "2025-02-25T10:00:00Z", "dataPoints": 380, "winnerIdea": "AutoStandup", "saasIdeas": [ { "rank": 1, "name": "AutoStandup", "oneLiner": "Async standups that actually get filled out", "overallScore": 8.5, "verdict": "๐ฅ Build this", "targetCustomer": "Remote engineering teams 5-50 people", "estimatedMRR": "$12,000 at 100 customers ($120/mo per team)", "timeToMVP": "3 weeks", "nextStep": "Post in r/remotework and r/SaaS โ ask if this is a real problem", "validationSignals": [ "47 Reddit posts complaining about standups being ignored", "3-star Slack reviews: 'nobody fills them out'" ] } ], "quickWins": [ { "idea": "Notion template for async standups", "timeToMVP": "2 days", "validationMethod": "Post on Gumroad, see if anyone pays $9" } ] }
Focus on 1โ3 star reviews โ that's where the real pain lives Scrape at least 200+ reviews per competitor for statistically significant patterns Always include a "why is there no tool for X" Reddit search โ goldmine for gaps Cross-validate: an idea is strong only if the same frustration appears in 3+ sources The Quick Wins section is perfect for validation before building โ ship a landing page first Re-run the pipeline on a new niche weekly to build a pipeline of ideas Track which ideas get the most Slack/Notion engagement from your team
try { const data = await scrapeAppReviews(); return data; } catch (error) { if (error.statusCode === 401) throw new Error("Invalid Apify token"); if (error.statusCode === 429) throw new Error("Rate limit โ reduce concurrent scrapers"); if (error.message.includes("actor")) throw new Error("Actor not found โ verify actor ID"); throw error; }
Apify account โ https://www.apify.com/?fpr=dx06p Claude / OpenClaw API key Node.js 18+ with apify-client, axios, node-cron, fs-extra Optional: Slack, Notion, or Airtable for team collaboration on the output
Data access, storage, extraction, analysis, reporting, and insight generation.
Largest current source with strong distribution and engagement signals.