@veyralabs/skills 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/bin/cli.js +3 -2
- package/commands/venture-analyst.md +16 -0
- package/install.sh +1 -0
- package/package.json +6 -2
- package/skills/venture-suite/venture-analyst/SKILL.md +269 -0
- package/skills/venture-suite/venture-analyst/references/blue-ocean.md +130 -0
- package/skills/venture-suite/venture-analyst/references/customer-dev.md +147 -0
- package/skills/venture-suite/venture-analyst/references/lean-startup.md +123 -0
- package/skills/venture-suite/venture-analyst/references/mom-test.md +146 -0
- package/skills/venture-suite/venture-analyst/references/traction.md +154 -0
- package/skills/venture-suite/venture-analyst/scripts/enhance_detect.py +172 -0
- package/skills/venture-suite/venture-analyst/scripts/experiments.py +228 -0
- package/skills/venture-suite/venture-analyst/scripts/scraper.py +194 -0
- package/skills/venture-suite/venture-analyst/scripts/sources.py +288 -0
- package/skills/venture-suite/venture-analyst/templates/experiment-spec.md +119 -0
- package/skills/venture-suite/venture-analyst/templates/verdict.md +160 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Lean Startup Reference
|
|
2
|
+
|
|
3
|
+
Core methodology for venture-analyst. Eric Ries, 2011. Still the most cited startup framework.
|
|
4
|
+
|
|
5
|
+
## Build-Measure-Learn loop
|
|
6
|
+
|
|
7
|
+
Not a sequential process — a loop. Start from Learn and work backwards:
|
|
8
|
+
|
|
9
|
+
1. **Learn** - What do we need to know? (Define the riskiest assumption)
|
|
10
|
+
2. **Build** - Build the minimum thing to test that assumption
|
|
11
|
+
3. **Measure** - Collect data on whether assumption is true
|
|
12
|
+
|
|
13
|
+
Speed through the loop beats quality of any single cycle.
|
|
14
|
+
|
|
15
|
+
**Key insight:** Most startups fail not because they can't build, but because they build something nobody wants. The loop's purpose is to surface that failure cheaply and early.
|
|
16
|
+
|
|
17
|
+
## Validated learning
|
|
18
|
+
|
|
19
|
+
Not all learning is equal. Vanity metrics (page views, registered users) feel good and mean nothing.
|
|
20
|
+
|
|
21
|
+
**Vanity metric examples:**
|
|
22
|
+
- Total signups (meaningless without activation rate)
|
|
23
|
+
- Page views (meaningless without behavior)
|
|
24
|
+
- Press mentions (zero correlation with revenue)
|
|
25
|
+
- Lines of code shipped
|
|
26
|
+
|
|
27
|
+
**Actionable metrics (validated learning):**
|
|
28
|
+
- Activation rate: % of signups who complete key action
|
|
29
|
+
- Retention cohorts: do users come back week 2, week 4?
|
|
30
|
+
- Willingness to pay: who actually pays vs who says they would
|
|
31
|
+
- NPS with follow-up: would you be disappointed if gone?
|
|
32
|
+
|
|
33
|
+
**Test:** "If this metric doubled, would we change what we build next?" If no - it's vanity.
|
|
34
|
+
|
|
35
|
+
## Minimum Viable Product (MVP) types
|
|
36
|
+
|
|
37
|
+
### Concierge MVP
|
|
38
|
+
Do the service manually for 3-5 users. No automation.
|
|
39
|
+
- When: early problem validation, B2B, high-value customers
|
|
40
|
+
- Cost: time only
|
|
41
|
+
- What you learn: is the outcome valuable? What parts matter?
|
|
42
|
+
- Example: Airbnb founders photographed first listings themselves
|
|
43
|
+
|
|
44
|
+
### Wizard of Oz MVP
|
|
45
|
+
System looks automated but humans do the work behind the scenes.
|
|
46
|
+
- When: you want to simulate the product without building it
|
|
47
|
+
- Cost: time + some frontend work
|
|
48
|
+
- What you learn: do users engage with the interface? Is the outcome valuable?
|
|
49
|
+
- Example: Zappos CEO manually bought shoes from stores to test demand
|
|
50
|
+
|
|
51
|
+
### Landing Page / Fake Door
|
|
52
|
+
Page describes product, collects signups or clicks before product exists.
|
|
53
|
+
- When: demand signal, product not built
|
|
54
|
+
- Cost: hours (Carrd.co is free)
|
|
55
|
+
- What you learn: does the message resonate? Will people take action?
|
|
56
|
+
- Caution: doesn't test willingness to pay - only interest
|
|
57
|
+
|
|
58
|
+
### Piecemeal MVP
|
|
59
|
+
Assemble from existing tools. Don't build infrastructure.
|
|
60
|
+
- When: proving the workflow works before custom tech
|
|
61
|
+
- Cost: subscription fees for tools used
|
|
62
|
+
- Example: use Airtable + Zapier + Stripe before building SaaS
|
|
63
|
+
|
|
64
|
+
### Single-Feature MVP
|
|
65
|
+
Ship one core feature only. Cut everything else.
|
|
66
|
+
- When: you know the problem, testing one solution
|
|
67
|
+
- Risk: might ship the wrong feature
|
|
68
|
+
- Rule: what is the single thing that makes this valuable? Ship only that.
|
|
69
|
+
|
|
70
|
+
## Pivot types
|
|
71
|
+
|
|
72
|
+
When data says current direction is wrong, pivot — don't persevere blindly.
|
|
73
|
+
|
|
74
|
+
| Pivot type | What changes | Example |
|
|
75
|
+
|-----------|--------------|---------|
|
|
76
|
+
| Zoom-in | Narrow one feature into whole product | Instagram pivoted from Burbn |
|
|
77
|
+
| Zoom-out | Widen — current product becomes one feature | - |
|
|
78
|
+
| Customer segment | Same product, different customer | B2C → B2B |
|
|
79
|
+
| Customer need | Same customer, different problem | - |
|
|
80
|
+
| Platform | App → platform or vice versa | - |
|
|
81
|
+
| Business architecture | High margin/low volume ↔ low margin/high volume | - |
|
|
82
|
+
| Value capture | How you charge (not what you sell) | Per seat → flat rate |
|
|
83
|
+
| Engine of growth | Viral → sticky → paid acquisition | - |
|
|
84
|
+
| Channel | Direct → partner → marketplace | - |
|
|
85
|
+
| Technology | Same problem, completely different tech | - |
|
|
86
|
+
|
|
87
|
+
**When to pivot vs persevere:**
|
|
88
|
+
- Experiments consistently failing over multiple cycles = pivot signal
|
|
89
|
+
- One experiment failing = not enough data
|
|
90
|
+
- Team excited about pivot because it's easier = wrong reason, investigate
|
|
91
|
+
|
|
92
|
+
## Innovation accounting
|
|
93
|
+
|
|
94
|
+
3 milestones before declaring pivot/persevere:
|
|
95
|
+
|
|
96
|
+
1. Establish baseline (where are we now? honest numbers)
|
|
97
|
+
2. Tune the engine (optimize toward ideal, eliminate waste)
|
|
98
|
+
3. Decide pivot or persevere (did tuning move numbers? if no, pivot)
|
|
99
|
+
|
|
100
|
+
## Engines of growth
|
|
101
|
+
|
|
102
|
+
**Sticky engine:** Retention is the driver. Churn rate < growth rate.
|
|
103
|
+
- Metric: customer lifetime value vs churn rate
|
|
104
|
+
- Strategy: improve activation and retention before acquisition
|
|
105
|
+
|
|
106
|
+
**Viral engine:** Users recruit users.
|
|
107
|
+
- Metric: viral coefficient (K-factor). K > 1 = exponential growth
|
|
108
|
+
- K = (invites sent per user) × (conversion rate of invites)
|
|
109
|
+
- Strategy: build referral loop into core product
|
|
110
|
+
|
|
111
|
+
**Paid engine:** Buy customers profitably.
|
|
112
|
+
- Metric: LTV > CAC (lifetime value > customer acquisition cost)
|
|
113
|
+
- Rule of thumb: LTV should be 3x CAC minimum
|
|
114
|
+
- Strategy: find one channel that scales before optimizing others
|
|
115
|
+
|
|
116
|
+
## Signals this framework applies
|
|
117
|
+
|
|
118
|
+
Use lean startup when:
|
|
119
|
+
- Building a new product in uncertain market
|
|
120
|
+
- Validating a problem before heavy investment
|
|
121
|
+
- Deciding between multiple possible solutions
|
|
122
|
+
|
|
123
|
+
Don't use it to justify shipping forever-incomplete products. "Lean" = eliminate waste, not "don't finish things."
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Mom Test Reference
|
|
2
|
+
|
|
3
|
+
Rob Fitzpatrick, "The Mom Test" (2013).
|
|
4
|
+
Core rule: your mom loves you and will lie to make you feel good. Most customers will too.
|
|
5
|
+
The test: would your mom give you honest answers to these questions? If yes, they're good questions.
|
|
6
|
+
|
|
7
|
+
## The problem with bad interviews
|
|
8
|
+
|
|
9
|
+
Founders ask questions that make customers feel good but reveal nothing:
|
|
10
|
+
|
|
11
|
+
- "Do you think this is a good idea?" — Everyone says yes. Means nothing.
|
|
12
|
+
- "Would you use a product that does X?" — Hypothetical. People overestimate future behavior.
|
|
13
|
+
- "How much would you pay for this?" — Hypothetical. Actual payments are the only data.
|
|
14
|
+
|
|
15
|
+
**The lie:** "That's a great idea, you should build that." Customers say this to be kind. It's not validation.
|
|
16
|
+
|
|
17
|
+
**Real validation:** someone pays, or gives up time, or says something unprompted that matches your hypothesis.
|
|
18
|
+
|
|
19
|
+
## The three rules
|
|
20
|
+
|
|
21
|
+
### Rule 1 — Talk about their life, not your idea
|
|
22
|
+
|
|
23
|
+
Ask about what they already do. Not what they would do.
|
|
24
|
+
|
|
25
|
+
Good: "How do you currently handle invoicing?"
|
|
26
|
+
Bad: "Would you use an AI invoicing tool?"
|
|
27
|
+
|
|
28
|
+
### Rule 2 — Ask about specifics in the past, not generics or opinions
|
|
29
|
+
|
|
30
|
+
Past behavior predicts future behavior. Opinions don't.
|
|
31
|
+
|
|
32
|
+
Good: "Walk me through the last time you dealt with that."
|
|
33
|
+
Bad: "Do you often have trouble with that?"
|
|
34
|
+
|
|
35
|
+
### Rule 3 — Listen, don't pitch
|
|
36
|
+
|
|
37
|
+
If you're explaining your idea, you're not learning. You're convincing.
|
|
38
|
+
The moment you pitch, all their answers become validation attempts, not honest signals.
|
|
39
|
+
|
|
40
|
+
## Good vs bad questions
|
|
41
|
+
|
|
42
|
+
### Good questions
|
|
43
|
+
|
|
44
|
+
- "How do you currently handle [problem]? Walk me through your last time."
|
|
45
|
+
- "What's the most frustrating part of that process?"
|
|
46
|
+
- "How long does that take you per week?"
|
|
47
|
+
- "Have you tried other solutions? What happened?"
|
|
48
|
+
- "How much are you currently spending on this? Time + money."
|
|
49
|
+
- "What would you do if this problem disappeared tomorrow?"
|
|
50
|
+
- "Who else in your team deals with this?"
|
|
51
|
+
- "How do you find out about tools like this?"
|
|
52
|
+
- "What would make you switch away from your current solution?"
|
|
53
|
+
|
|
54
|
+
### Bad questions
|
|
55
|
+
|
|
56
|
+
- "Would you use X if it existed?"
|
|
57
|
+
- "Do you think this is a good idea?"
|
|
58
|
+
- "What features would you want?"
|
|
59
|
+
- "How much would you pay for this?"
|
|
60
|
+
- "Would you pay $X/month for this?"
|
|
61
|
+
- "Don't you think [problem] is really bad?"
|
|
62
|
+
- "If we built X, would that solve your problem?"
|
|
63
|
+
|
|
64
|
+
## Detecting false positives
|
|
65
|
+
|
|
66
|
+
Customers say things that sound like validation but aren't.
|
|
67
|
+
|
|
68
|
+
**Compliments (ignore these):**
|
|
69
|
+
- "That's really interesting."
|
|
70
|
+
- "I could see that being useful."
|
|
71
|
+
- "You should definitely build that."
|
|
72
|
+
- "I know people who would use that."
|
|
73
|
+
|
|
74
|
+
**Weak signals (not enough alone):**
|
|
75
|
+
- "I would use it if it had X feature."
|
|
76
|
+
- "I might sign up when it's live."
|
|
77
|
+
- "Send me info when you launch."
|
|
78
|
+
|
|
79
|
+
**Strong signals (real validation):**
|
|
80
|
+
- They ask when it will be available and push for a date
|
|
81
|
+
- They offer to pay now, even before it's built
|
|
82
|
+
- They ask for a demo with their boss on the call
|
|
83
|
+
- They describe a specific workflow where they'd use it
|
|
84
|
+
- They give you a referral without being asked
|
|
85
|
+
|
|
86
|
+
**The commitment test:**
|
|
87
|
+
"Would you be willing to [try the beta / join a pilot / pay a deposit / introduce me to your VP]?"
|
|
88
|
+
|
|
89
|
+
Their reaction tells you more than anything they said before.
|
|
90
|
+
|
|
91
|
+
## Extracting signal from praise
|
|
92
|
+
|
|
93
|
+
When they say "I love it" — push:
|
|
94
|
+
|
|
95
|
+
- "What specifically would you use it for?"
|
|
96
|
+
- "How often would that come up?"
|
|
97
|
+
- "How much time/money is that costing you now?"
|
|
98
|
+
- "What would you stop doing if you had this?"
|
|
99
|
+
|
|
100
|
+
Turn abstract enthusiasm into concrete use cases and quantified pain.
|
|
101
|
+
|
|
102
|
+
## Signs you found a real customer
|
|
103
|
+
|
|
104
|
+
1. They describe the problem in detail without being asked
|
|
105
|
+
2. They have a workaround they're not happy with
|
|
106
|
+
3. They ask questions about your solution (not just compliment it)
|
|
107
|
+
4. They connect you to other people with the same problem
|
|
108
|
+
5. They put time/money on the line (small commitment = real interest)
|
|
109
|
+
|
|
110
|
+
## Signs this is the wrong customer
|
|
111
|
+
|
|
112
|
+
1. They can't remember a specific recent example of the problem
|
|
113
|
+
2. Their "solution" is to just not deal with it
|
|
114
|
+
3. They're enthusiastic but can't make a buying decision
|
|
115
|
+
4. Every answer is "it depends" without specifics
|
|
116
|
+
5. The problem you're describing is news to them
|
|
117
|
+
|
|
118
|
+
## Interview format that works
|
|
119
|
+
|
|
120
|
+
**Setup (2 min):** "I'm researching how [people like you] handle [domain]. Not selling anything. Want honest feedback."
|
|
121
|
+
|
|
122
|
+
**Warm-up (3 min):** Ask about their role, day-to-day. Build context.
|
|
123
|
+
|
|
124
|
+
**Core (15 min):** Story-based questions about past behavior.
|
|
125
|
+
- "Tell me about the last time..."
|
|
126
|
+
- "Walk me through what you did..."
|
|
127
|
+
- "What happened after that?"
|
|
128
|
+
|
|
129
|
+
**Quantify (5 min):** Pin down real numbers.
|
|
130
|
+
- "How often does this happen?"
|
|
131
|
+
- "How long does it take?"
|
|
132
|
+
- "What does it cost you?"
|
|
133
|
+
|
|
134
|
+
**Wrap-up (3 min):** "Who else would you suggest I talk to about this?"
|
|
135
|
+
|
|
136
|
+
Total: 25-30 minutes. Don't go over — respect their time.
|
|
137
|
+
|
|
138
|
+
## Pattern recognition across interviews
|
|
139
|
+
|
|
140
|
+
After 10+ interviews:
|
|
141
|
+
- Which problems do they all mention? (signal)
|
|
142
|
+
- Which problems do only 1-2 mention? (noise or niche)
|
|
143
|
+
- Which solutions do they all currently use? (incumbent to beat)
|
|
144
|
+
- What do they all want but nobody builds? (gap)
|
|
145
|
+
|
|
146
|
+
Don't average opinions. Look for patterns in specific behaviors.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Traction Reference
|
|
2
|
+
|
|
3
|
+
Gabriel Weinberg & Justin Mares, "Traction" (2014).
|
|
4
|
+
Framework for finding customer acquisition channels that actually work.
|
|
5
|
+
|
|
6
|
+
## Core insight
|
|
7
|
+
|
|
8
|
+
Most startups fail not because of product problems but traction problems. Building product and finding traction should happen in parallel, not sequentially.
|
|
9
|
+
|
|
10
|
+
Half your time should be spent on traction, not product — even pre-launch.
|
|
11
|
+
|
|
12
|
+
## The 19 traction channels
|
|
13
|
+
|
|
14
|
+
1. **Viral marketing** - product spreads through existing users (Dropbox, Slack)
|
|
15
|
+
2. **PR** - traditional press coverage
|
|
16
|
+
3. **Unconventional PR** - stunts, giveaways, memorable campaigns
|
|
17
|
+
4. **Search engine marketing (SEM)** - paid search (Google Ads)
|
|
18
|
+
5. **Social and display ads** - Meta, LinkedIn, programmatic
|
|
19
|
+
6. **Offline ads** - billboards, radio, TV, print
|
|
20
|
+
7. **Search engine optimization (SEO)** - organic search
|
|
21
|
+
8. **Content marketing** - blog, YouTube, podcast as acquisition
|
|
22
|
+
9. **Email marketing** - list building and outbound sequences
|
|
23
|
+
10. **Engineering as marketing** - free tools, calculators, embeds that drive signups
|
|
24
|
+
11. **Targeting blogs** - get covered by influential niche blogs
|
|
25
|
+
12. **Business development** - partnerships with complementary products
|
|
26
|
+
13. **Sales** - direct outbound sales, inside sales teams
|
|
27
|
+
14. **Affiliate programs** - revenue share for referrals
|
|
28
|
+
15. **Existing platforms** - App Store, Shopify App Store, Chrome extensions, marketplace distribution
|
|
29
|
+
16. **Trade shows** - industry events, conferences
|
|
30
|
+
17. **Offline events** - meetups, workshops, demos
|
|
31
|
+
18. **Speaking engagements** - conferences, podcasts, webinars
|
|
32
|
+
19. **Community building** - Slack groups, forums, ambassador programs
|
|
33
|
+
|
|
34
|
+
## Bullseye Framework
|
|
35
|
+
|
|
36
|
+
Don't try all 19 channels. Use the Bullseye to find the one that works.
|
|
37
|
+
|
|
38
|
+
### Step 1 — Brainstorm (outer ring)
|
|
39
|
+
For each of the 19 channels, answer:
|
|
40
|
+
- How could we use this channel?
|
|
41
|
+
- What would success look like?
|
|
42
|
+
- How could we test it cheaply?
|
|
43
|
+
|
|
44
|
+
Produces 19 rough hypotheses.
|
|
45
|
+
|
|
46
|
+
### Step 2 — Rank (middle ring)
|
|
47
|
+
Score each channel on 3 criteria (1-3):
|
|
48
|
+
- Probability of working
|
|
49
|
+
- Volume potential (enough customers to matter)
|
|
50
|
+
- Cost per acquisition (time + money)
|
|
51
|
+
|
|
52
|
+
Pick the top 6 channels. These are your "promising" channels.
|
|
53
|
+
|
|
54
|
+
### Step 3 — Test (inner ring — the bullseye)
|
|
55
|
+
Pick the 3 channels with highest combined score. Run cheap, fast tests on each simultaneously.
|
|
56
|
+
|
|
57
|
+
Each test:
|
|
58
|
+
- Fixed budget (~€200-500)
|
|
59
|
+
- Fixed time (2-4 weeks)
|
|
60
|
+
- One metric: cost per lead, or signups, or revenue
|
|
61
|
+
|
|
62
|
+
### Step 4 — Focus
|
|
63
|
+
One test will outperform the others. Focus 100% on that channel. Optimize it until it no longer scales.
|
|
64
|
+
|
|
65
|
+
When the channel plateaus, go back to Step 2.
|
|
66
|
+
|
|
67
|
+
## Channel selection by stage
|
|
68
|
+
|
|
69
|
+
Different channels dominate at different stages:
|
|
70
|
+
|
|
71
|
+
| Stage | Best channels |
|
|
72
|
+
|-------|--------------|
|
|
73
|
+
| Pre-PMF | Direct sales, outreach, niche blogs, communities |
|
|
74
|
+
| Early growth | Content, SEO, partnerships, email |
|
|
75
|
+
| Scaling | Paid acquisition (once LTV:CAC proven), viral, affiliates |
|
|
76
|
+
| Dominant | Brand, PR, events |
|
|
77
|
+
|
|
78
|
+
**Pre-PMF rule:** channels that require scale to work (SEO, paid ads, viral) are wrong for early stage. You don't have enough data to optimize them. Use channels where you control the targeting.
|
|
79
|
+
|
|
80
|
+
## Channel-market fit
|
|
81
|
+
|
|
82
|
+
Some channels only work for specific markets:
|
|
83
|
+
|
|
84
|
+
| Channel | Works for |
|
|
85
|
+
|---------|-----------|
|
|
86
|
+
| Cold outbound | B2B with clear ICP, high LTV |
|
|
87
|
+
| Content/SEO | Markets that Google actively |
|
|
88
|
+
| Product-led viral | Consumer, collaboration tools |
|
|
89
|
+
| Community | Niche markets with strong identity |
|
|
90
|
+
| Paid social | B2C with wide audience |
|
|
91
|
+
| Trade shows | B2B with offline buying decisions |
|
|
92
|
+
| Partnerships | Products with complementary distribution |
|
|
93
|
+
|
|
94
|
+
Picking the wrong channel for your market wastes 6 months.
|
|
95
|
+
|
|
96
|
+
## Cost benchmarks (rough, 2024)
|
|
97
|
+
|
|
98
|
+
| Channel | Metric | B2C benchmark | B2B benchmark |
|
|
99
|
+
|---------|--------|--------------|--------------|
|
|
100
|
+
| Facebook/Instagram ads | CPL | €3-8 | €15-30 |
|
|
101
|
+
| Google Search | CPL | €5-15 | €20-60 |
|
|
102
|
+
| LinkedIn ads | CPL | - | €40-100 |
|
|
103
|
+
| Cold email | CPL | - | €20-80 (time cost) |
|
|
104
|
+
| Content/SEO | CPL | €5-20 (long term) | €15-50 (long term) |
|
|
105
|
+
| Referral/viral | CPL | €1-5 | €5-20 |
|
|
106
|
+
|
|
107
|
+
LTV must be at least 3x CAC for paid channels to be viable.
|
|
108
|
+
|
|
109
|
+
## Traction metrics by channel
|
|
110
|
+
|
|
111
|
+
**Viral / product-led:**
|
|
112
|
+
- K-factor = (invites per user) × (invite conversion rate). Target K > 0.5 for meaningful viral effect
|
|
113
|
+
- Time to viral loop: how fast does one user create another?
|
|
114
|
+
|
|
115
|
+
**Content / SEO:**
|
|
116
|
+
- Organic sessions per month
|
|
117
|
+
- Keyword rankings for high-intent terms
|
|
118
|
+
- Time to rank: SEO takes 3-6 months minimum to show results
|
|
119
|
+
|
|
120
|
+
**Email:**
|
|
121
|
+
- List growth rate per week
|
|
122
|
+
- Open rate: >30% is good for cold; >50% for warm
|
|
123
|
+
- Click-through: >5% is strong
|
|
124
|
+
|
|
125
|
+
**Paid acquisition:**
|
|
126
|
+
- CPL and CAC (cost per acquired customer)
|
|
127
|
+
- Payback period: how many months to recoup CAC?
|
|
128
|
+
- ROAS (return on ad spend)
|
|
129
|
+
|
|
130
|
+
**Sales:**
|
|
131
|
+
- Leads per week
|
|
132
|
+
- Conversion rate (leads to paying)
|
|
133
|
+
- Sales cycle length
|
|
134
|
+
- Average contract value
|
|
135
|
+
|
|
136
|
+
## Applying to venture analysis
|
|
137
|
+
|
|
138
|
+
In Phase 3 (validation), recommend channels based on:
|
|
139
|
+
|
|
140
|
+
1. Market type (B2B vs B2C)
|
|
141
|
+
2. LTV estimate (high LTV = more channels viable)
|
|
142
|
+
3. Available budget
|
|
143
|
+
4. Target customer location (online? offline? specific communities?)
|
|
144
|
+
|
|
145
|
+
For zero-budget startups, the viable channels are:
|
|
146
|
+
- Direct outreach (cold email/DM) — time only
|
|
147
|
+
- Niche community posting (Reddit, specific Slack/Discord groups) — time only
|
|
148
|
+
- Engineering as marketing — build a free tool that attracts ICPs
|
|
149
|
+
- Content on a specific topic ICP searches for
|
|
150
|
+
|
|
151
|
+
For startups with €100-500/month budget:
|
|
152
|
+
- Fake door test (landing page + small paid traffic)
|
|
153
|
+
- LinkedIn outreach with Sales Navigator trial
|
|
154
|
+
- Sponsored newsletter in a niche (often €100-300 per send)
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Level 2 auto-detection.
|
|
3
|
+
Silently detects available enhancements. Never asks the user for config.
|
|
4
|
+
"""
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
import time
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def detect_level() -> dict:
|
|
12
|
+
"""
|
|
13
|
+
Detect what's available. Returns a capability map.
|
|
14
|
+
Called once at session start — results cached for the session.
|
|
15
|
+
"""
|
|
16
|
+
return {
|
|
17
|
+
"docker": _has_docker(),
|
|
18
|
+
"searxng": _has_searxng(),
|
|
19
|
+
"veyrascrape_mcp": _has_env("VEYRASCRAPE_API_KEY"),
|
|
20
|
+
"github_token": _has_env("GITHUB_TOKEN"),
|
|
21
|
+
"exa_key": _has_env("EXA_API_KEY"),
|
|
22
|
+
"tavily_key": _has_env("TAVILY_API_KEY"),
|
|
23
|
+
"groq_key": _has_env("GROQ_API_KEY"),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _has_env(key: str) -> bool:
|
|
28
|
+
val = os.environ.get(key, "").strip()
|
|
29
|
+
return bool(val)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _has_docker() -> bool:
|
|
33
|
+
try:
|
|
34
|
+
result = subprocess.run(
|
|
35
|
+
["docker", "info"],
|
|
36
|
+
capture_output=True,
|
|
37
|
+
timeout=4,
|
|
38
|
+
)
|
|
39
|
+
return result.returncode == 0
|
|
40
|
+
except Exception:
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _has_searxng(ports: list[int] = None) -> bool:
|
|
45
|
+
if ports is None:
|
|
46
|
+
ports = [8080, 8888, 4000]
|
|
47
|
+
for port in ports:
|
|
48
|
+
try:
|
|
49
|
+
r = requests.get(
|
|
50
|
+
f"http://localhost:{port}/search",
|
|
51
|
+
params={"q": "test", "format": "json"},
|
|
52
|
+
timeout=2,
|
|
53
|
+
)
|
|
54
|
+
if r.status_code == 200:
|
|
55
|
+
return True
|
|
56
|
+
except Exception:
|
|
57
|
+
pass
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def ensure_searxng() -> dict:
|
|
62
|
+
"""
|
|
63
|
+
Launch SearXNG via Docker if available and not already running.
|
|
64
|
+
Returns status dict.
|
|
65
|
+
"""
|
|
66
|
+
if _has_searxng():
|
|
67
|
+
return {"available": True, "url": "http://localhost:8080", "launched": False}
|
|
68
|
+
|
|
69
|
+
if not _has_docker():
|
|
70
|
+
return {"available": False, "reason": "docker_not_found"}
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
subprocess.run(
|
|
74
|
+
[
|
|
75
|
+
"docker", "run", "-d",
|
|
76
|
+
"--name", "venture-searxng",
|
|
77
|
+
"-p", "8080:8080",
|
|
78
|
+
"searxng/searxng",
|
|
79
|
+
],
|
|
80
|
+
capture_output=True,
|
|
81
|
+
timeout=45,
|
|
82
|
+
)
|
|
83
|
+
# give it time to start
|
|
84
|
+
for _ in range(6):
|
|
85
|
+
time.sleep(2)
|
|
86
|
+
if _has_searxng():
|
|
87
|
+
return {"available": True, "url": "http://localhost:8080", "launched": True}
|
|
88
|
+
return {"available": False, "reason": "searxng_start_timeout"}
|
|
89
|
+
except Exception as e:
|
|
90
|
+
return {"available": False, "reason": str(e)}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def search_searxng(query: str, url: str = "http://localhost:8080", limit: int = 10) -> list[dict]:
|
|
94
|
+
"""Search via local SearXNG instance."""
|
|
95
|
+
try:
|
|
96
|
+
r = requests.get(
|
|
97
|
+
f"{url}/search",
|
|
98
|
+
params={"q": query, "format": "json", "pageno": 1},
|
|
99
|
+
timeout=10,
|
|
100
|
+
)
|
|
101
|
+
results = r.json().get("results", [])[:limit]
|
|
102
|
+
return [
|
|
103
|
+
{
|
|
104
|
+
"source": "searxng",
|
|
105
|
+
"title": res.get("title", ""),
|
|
106
|
+
"url": res.get("url", ""),
|
|
107
|
+
"text": res.get("content", ""),
|
|
108
|
+
"engine": res.get("engine", ""),
|
|
109
|
+
}
|
|
110
|
+
for res in results
|
|
111
|
+
]
|
|
112
|
+
except Exception:
|
|
113
|
+
return []
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def search_with_exa(query: str, api_key: str, limit: int = 10) -> list[dict]:
|
|
117
|
+
"""Semantic search via Exa API (optional Level 3 enhancement)."""
|
|
118
|
+
try:
|
|
119
|
+
import exa_py
|
|
120
|
+
exa = exa_py.Exa(api_key=api_key)
|
|
121
|
+
results = exa.search(query, num_results=limit, use_autoprompt=True)
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
"source": "exa",
|
|
125
|
+
"title": r.title or "",
|
|
126
|
+
"url": r.url,
|
|
127
|
+
"text": r.text or "",
|
|
128
|
+
}
|
|
129
|
+
for r in results.results
|
|
130
|
+
]
|
|
131
|
+
except Exception:
|
|
132
|
+
return []
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def best_search(query: str, env: dict, limit: int = 10) -> list[dict]:
|
|
136
|
+
"""
|
|
137
|
+
Use the best available search method based on detected environment.
|
|
138
|
+
Priority: Exa > SearXNG > Tavily > ddgs
|
|
139
|
+
"""
|
|
140
|
+
# Level 3: Exa
|
|
141
|
+
if env.get("exa_key"):
|
|
142
|
+
results = search_with_exa(query, os.environ["EXA_API_KEY"], limit)
|
|
143
|
+
if results:
|
|
144
|
+
return results
|
|
145
|
+
|
|
146
|
+
# Level 2: SearXNG
|
|
147
|
+
if env.get("searxng"):
|
|
148
|
+
results = search_searxng(query, limit=limit)
|
|
149
|
+
if results:
|
|
150
|
+
return results
|
|
151
|
+
|
|
152
|
+
# Level 2: Tavily
|
|
153
|
+
if env.get("tavily_key"):
|
|
154
|
+
try:
|
|
155
|
+
from tavily import TavilyClient
|
|
156
|
+
client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
|
|
157
|
+
response = client.search(query, max_results=limit)
|
|
158
|
+
return [
|
|
159
|
+
{
|
|
160
|
+
"source": "tavily",
|
|
161
|
+
"title": r.get("title", ""),
|
|
162
|
+
"url": r.get("url", ""),
|
|
163
|
+
"text": r.get("content", ""),
|
|
164
|
+
}
|
|
165
|
+
for r in response.get("results", [])
|
|
166
|
+
]
|
|
167
|
+
except Exception:
|
|
168
|
+
pass
|
|
169
|
+
|
|
170
|
+
# Level 1: ddgs (always available)
|
|
171
|
+
from scripts.sources import search_web
|
|
172
|
+
return search_web(query, limit)
|