growth-tools 0.1.0__tar.gz

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.
Files changed (52) hide show
  1. growth_tools-0.1.0/.env.example +32 -0
  2. growth_tools-0.1.0/.github/workflows/ci.yml +52 -0
  3. growth_tools-0.1.0/.gitignore +10 -0
  4. growth_tools-0.1.0/PKG-INFO +201 -0
  5. growth_tools-0.1.0/README.md +173 -0
  6. growth_tools-0.1.0/examples/sample-icp.env +39 -0
  7. growth_tools-0.1.0/examples/sample-leads.json +78 -0
  8. growth_tools-0.1.0/examples/test-output.txt +14 -0
  9. growth_tools-0.1.0/growth_tools/__init__.py +0 -0
  10. growth_tools-0.1.0/growth_tools/api/__init__.py +0 -0
  11. growth_tools-0.1.0/growth_tools/api/main.py +83 -0
  12. growth_tools-0.1.0/growth_tools/config/__init__.py +0 -0
  13. growth_tools-0.1.0/growth_tools/config/settings.py +68 -0
  14. growth_tools-0.1.0/growth_tools/core/__init__.py +0 -0
  15. growth_tools-0.1.0/growth_tools/core/db.py +153 -0
  16. growth_tools-0.1.0/growth_tools/core/llm.py +232 -0
  17. growth_tools-0.1.0/growth_tools/core/scoring.py +49 -0
  18. growth_tools-0.1.0/growth_tools/run_api.py +36 -0
  19. growth_tools-0.1.0/growth_tools/run_discord.py +20 -0
  20. growth_tools-0.1.0/growth_tools/run_reddit.py +33 -0
  21. growth_tools-0.1.0/growth_tools/systems/__init__.py +0 -0
  22. growth_tools-0.1.0/growth_tools/systems/crm_sequencer.py +151 -0
  23. growth_tools-0.1.0/growth_tools/systems/discord_bot.py +176 -0
  24. growth_tools-0.1.0/growth_tools/systems/github_auditor.py +179 -0
  25. growth_tools-0.1.0/growth_tools/systems/linkedin_bot.py +202 -0
  26. growth_tools-0.1.0/growth_tools/systems/linkedin_enricher.py +191 -0
  27. growth_tools-0.1.0/growth_tools/systems/reddit_capture.py +176 -0
  28. growth_tools-0.1.0/growth_tools/systems/website_auditor.py +121 -0
  29. growth_tools-0.1.0/pyproject.toml +48 -0
  30. growth_tools-0.1.0/requirements.txt +27 -0
  31. growth_tools-0.1.0/run_api.py +36 -0
  32. growth_tools-0.1.0/run_discord.py +20 -0
  33. growth_tools-0.1.0/run_reddit.py +33 -0
  34. growth_tools-0.1.0/src/growth_tools/__init__.py +0 -0
  35. growth_tools-0.1.0/src/growth_tools/api/__init__.py +0 -0
  36. growth_tools-0.1.0/src/growth_tools/api/main.py +84 -0
  37. growth_tools-0.1.0/src/growth_tools/config/__init__.py +0 -0
  38. growth_tools-0.1.0/src/growth_tools/config/settings.py +68 -0
  39. growth_tools-0.1.0/src/growth_tools/core/__init__.py +0 -0
  40. growth_tools-0.1.0/src/growth_tools/core/db.py +153 -0
  41. growth_tools-0.1.0/src/growth_tools/core/llm.py +232 -0
  42. growth_tools-0.1.0/src/growth_tools/core/scoring.py +49 -0
  43. growth_tools-0.1.0/src/growth_tools/systems/__init__.py +0 -0
  44. growth_tools-0.1.0/src/growth_tools/systems/crm_sequencer.py +151 -0
  45. growth_tools-0.1.0/src/growth_tools/systems/discord_bot.py +176 -0
  46. growth_tools-0.1.0/src/growth_tools/systems/github_auditor.py +179 -0
  47. growth_tools-0.1.0/src/growth_tools/systems/linkedin_bot.py +202 -0
  48. growth_tools-0.1.0/src/growth_tools/systems/linkedin_enricher.py +190 -0
  49. growth_tools-0.1.0/src/growth_tools/systems/reddit_capture.py +177 -0
  50. growth_tools-0.1.0/src/growth_tools/systems/website_auditor.py +120 -0
  51. growth_tools-0.1.0/tests/__init__.py +0 -0
  52. growth_tools-0.1.0/tests/test_brand_config.py +42 -0
@@ -0,0 +1,32 @@
1
+ # ── Reddit ────────────────────────────────────────────────────────────────────
2
+ REDDIT_CLIENT_ID=your_reddit_app_id
3
+ REDDIT_CLIENT_SECRET=your_reddit_app_secret
4
+ REDDIT_USER_AGENT=growth-tools/1.0
5
+
6
+ # ── OpenAI (for classification + outreach drafts) ─────────────────────────────
7
+ OPENAI_API_KEY=sk-...
8
+ OPENAI_MODEL=gpt-4.1-mini
9
+
10
+ # ── Supabase (lead storage) ───────────────────────────────────────────────────
11
+ SUPABASE_URL=https://your-project.supabase.co
12
+ SUPABASE_SERVICE_ROLE_KEY=eyJ...
13
+
14
+ # ── Discord ───────────────────────────────────────────────────────────────────
15
+ DISCORD_TOKEN=your_discord_bot_token
16
+ # Comma-separated channel IDs to monitor (leave blank = all channels)
17
+ ALLOWED_CHANNEL_IDS=
18
+
19
+ # ── GitHub ────────────────────────────────────────────────────────────────────
20
+ GITHUB_TOKEN=ghp_...
21
+
22
+ # ── Scoring thresholds ────────────────────────────────────────────────────────
23
+ # Min intent score (0-100) to save a lead
24
+ LEAD_INTENT_THRESHOLD=70
25
+ # Min confidence for Discord auto-reply
26
+ DISCORD_CONFIDENCE_THRESHOLD=0.75
27
+
28
+ # ── Brand identity (used in LLM-generated reply/outreach drafts) ──────────────
29
+ BRAND_NAME=YourProduct
30
+ BRAND_TAGLINE=helps teams ship production-ready apps
31
+ # Describe the core problem your ICP (ideal customer profile) has
32
+ ICP_PAIN=move from prototype to production
@@ -0,0 +1,52 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.10", "3.11", "3.12"]
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+
22
+ - name: Install package
23
+ run: pip install -e ".[dev]"
24
+
25
+ - name: Run tests
26
+ run: pytest tests/ -v
27
+
28
+ - name: Lint
29
+ run: |
30
+ pip install ruff
31
+ ruff check src/
32
+
33
+ dry-run-reddit:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ - uses: actions/setup-python@v5
38
+ with:
39
+ python-version: "3.11"
40
+ - name: Install package
41
+ run: pip install -e .
42
+ - name: Smoke test CLI (dry-run)
43
+ run: growth-reddit --dry-run --subreddits SaaS
44
+ env:
45
+ BRAND_NAME: TestBrand
46
+ BRAND_TAGLINE: Test tagline
47
+ ICP_PAIN: Test pain
48
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
49
+ REDDIT_CLIENT_ID: ${{ secrets.REDDIT_CLIENT_ID }}
50
+ REDDIT_CLIENT_SECRET: ${{ secrets.REDDIT_CLIENT_SECRET }}
51
+ REDDIT_USER_AGENT: CI/1.0
52
+ continue-on-error: true
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ venv/
8
+ .env
9
+ *.log
10
+ .DS_Store
@@ -0,0 +1,201 @@
1
+ Metadata-Version: 2.4
2
+ Name: growth-tools
3
+ Version: 0.1.0
4
+ Summary: Lead capture from Reddit, Discord and GitHub with hybrid LLM scoring and outreach drafts.
5
+ Project-URL: Repository, https://github.com/nometria/growth-tools
6
+ License: MIT
7
+ Keywords: discord,growth,leads,outreach,reddit,saas,scoring
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Internet :: WWW/HTTP
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: beautifulsoup4>=4.12.0
13
+ Requires-Dist: discord-py>=2.3.0
14
+ Requires-Dist: fastapi>=0.115.0
15
+ Requires-Dist: openai>=1.52.0
16
+ Requires-Dist: praw>=7.7.0
17
+ Requires-Dist: pydantic-settings>=2.0.0
18
+ Requires-Dist: pydantic>=2.0.0
19
+ Requires-Dist: python-dotenv>=1.0.0
20
+ Requires-Dist: requests>=2.31.0
21
+ Requires-Dist: supabase>=2.0.0
22
+ Requires-Dist: tenacity>=8.2.0
23
+ Requires-Dist: uvicorn[standard]>=0.30.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest-cov; extra == 'dev'
26
+ Requires-Dist: pytest>=8.0; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # growth-tools
30
+
31
+ > Automated lead capture from Reddit, Discord and GitHub — with hybrid LLM scoring and outreach drafts.
32
+
33
+ Built for dev-tool and SaaS companies that want inbound signal from developer communities
34
+ without hiring a full-time growth team.
35
+
36
+ ---
37
+
38
+ ## Quick start
39
+
40
+ ```bash
41
+ # Clone and install
42
+ git clone https://github.com/ownmy-app/growth-tools
43
+ cd growth-tools
44
+ pip install -e .
45
+
46
+ # Configure your environment
47
+ cp examples/sample-icp.env .env
48
+ # Edit .env with your API keys and brand config
49
+
50
+ # Run Reddit monitor (one-shot)
51
+ growth-reddit
52
+
53
+ # Run the website auditor API
54
+ growth-api
55
+ # or: uvicorn growth_tools.api.main:app --port 8000
56
+
57
+ # Run tests
58
+ pytest tests/ -v
59
+ ```
60
+
61
+ Required environment variables (see `examples/sample-icp.env`):
62
+ ```bash
63
+ OPENAI_API_KEY=sk-proj-...
64
+ REDDIT_CLIENT_ID=...
65
+ REDDIT_CLIENT_SECRET=...
66
+ BRAND_NAME="Your Product"
67
+ ICP_KEYWORDS="supabase,self-host,postgres,..."
68
+ ```
69
+
70
+ ---
71
+
72
+ ## What's included
73
+
74
+ | Module | What it does |
75
+ |--------|-------------|
76
+ | `systems/reddit_capture.py` | Monitors subreddits, two-stage filter (keyword → LLM), saves hot leads |
77
+ | `systems/discord_bot.py` | Discord bot with per-channel cooldown, confidence threshold gating |
78
+ | `systems/website_auditor.py` | Detects tech stack from HTML/headers (Next.js, Vite, Supabase, Vercel…) |
79
+ | `systems/github_auditor.py` | Scans repos for migration readiness (package.json, Dockerfile analysis) |
80
+ | `systems/crm_sequencer.py` | LLM-generated outreach drafts (capped at 90 words for reply rates) |
81
+ | `core/scoring.py` | Hybrid rule + LLM scoring: `0.5 × rule_score + 0.5 × llm_intent_score` |
82
+ | `core/llm.py` | OpenAI client with fallback model + tenacity retries |
83
+ | `api/main.py` | FastAPI: `POST /audit/website`, `POST /audit/github`, `GET /health` |
84
+
85
+ ---
86
+
87
+ ## Scoring tiers
88
+
89
+ | Score | Tier | Action |
90
+ |-------|------|--------|
91
+ | ≥ 80 | **hot** | Immediate outreach |
92
+ | 60–79 | **nurture** | Add to sequence |
93
+ | 40–59 | **educate** | Send content |
94
+ | < 40 | **ignore** | Skip |
95
+
96
+ Rule signals: `+25` high-intent builder (Lovable/Replit/Bolt/v0), `+30` high-intent pain
97
+ (deploy/migrate/security/ownership), `+20` has public repo, `+25` mentions clients.
98
+ Blended 50/50 with LLM intent score.
99
+
100
+ ---
101
+
102
+ ## Supabase schema
103
+
104
+ ```sql
105
+ create table lead_signals (
106
+ id uuid primary key default gen_random_uuid(),
107
+ source text, -- 'reddit' | 'discord' | 'github'
108
+ title text,
109
+ body text,
110
+ url text,
111
+ author text,
112
+ intent_score int,
113
+ tier text,
114
+ builder text,
115
+ pain_type text,
116
+ reply_draft text,
117
+ created_at timestamptz default now()
118
+ );
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Setup
124
+
125
+ ```bash
126
+ git clone https://github.com/ownmy-app/growth-tools
127
+ cd growth-tools
128
+ pip install -e .
129
+ cp examples/sample-icp.env .env
130
+ # Edit .env
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Run
136
+
137
+ ```bash
138
+ # Reddit monitor (one-shot)
139
+ growth-reddit
140
+
141
+ # Discord bot (persistent)
142
+ python -m growth_tools.systems.discord_bot
143
+
144
+ # Website auditor API
145
+ growth-api
146
+ # or: uvicorn growth_tools.api.main:app --port 8000
147
+
148
+ # Audit a specific website
149
+ curl -X POST http://localhost:8000/audit/website -H 'Content-Type: application/json' \
150
+ -d '{"url": "https://example.com"}'
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Customise
156
+
157
+ **Target subreddits** — set `ICP_KEYWORDS` in `.env`
158
+
159
+ **Lead scoring** — edit weights in `core/scoring.py` (or move to YAML config)
160
+
161
+ **Outreach tone** — edit prompts in `core/llm.py`
162
+
163
+ ---
164
+
165
+ ## Immediate next steps
166
+ 1. Make subreddits + keywords configurable via env / YAML
167
+ 2. Add GitHub lead capture (scan repos that import competitor SDKs)
168
+ 3. Add Slack notification on "hot" leads
169
+ 4. Package as `pip install growth-tools`
170
+
171
+ ---
172
+
173
+ ## Commercial viability
174
+ - Open-core: open source the capture + scoring, charge for the CRM sequencer
175
+ - SaaS: $200–500/mo per team for managed lead pipeline
176
+ - Competitors: Trigify, Drippi — neither does GitHub + Reddit + LLM scoring combined
177
+
178
+ ---
179
+
180
+ ## Example output
181
+
182
+ Running `pytest tests/ -v`:
183
+
184
+ ```
185
+ ============================= test session starts ==============================
186
+ platform darwin -- Python 3.13.9, pytest-9.0.2, pluggy-1.5.0
187
+ cachedir: .pytest_cache
188
+ rootdir: /tmp/ownmy-releases/growth-tools
189
+ configfile: pyproject.toml
190
+ plugins: anyio-4.12.1, cov-7.1.0
191
+ collecting ... collected 4 items
192
+
193
+ tests/test_brand_config.py::test_brand_name_reads_from_env PASSED [ 25%]
194
+ tests/test_brand_config.py::test_brand_tagline_reads_from_env PASSED [ 50%]
195
+ tests/test_brand_config.py::test_icp_pain_reads_from_env PASSED [ 75%]
196
+ tests/test_brand_config.py::test_no_hardcoded_brand_names_in_source PASSED [100%]
197
+
198
+ ============================== 4 passed in 0.03s ===============================
199
+ ```
200
+
201
+ See `examples/sample-leads.json` for representative scored lead output and `examples/sample-icp.env` for required environment variable configuration.
@@ -0,0 +1,173 @@
1
+ # growth-tools
2
+
3
+ > Automated lead capture from Reddit, Discord and GitHub — with hybrid LLM scoring and outreach drafts.
4
+
5
+ Built for dev-tool and SaaS companies that want inbound signal from developer communities
6
+ without hiring a full-time growth team.
7
+
8
+ ---
9
+
10
+ ## Quick start
11
+
12
+ ```bash
13
+ # Clone and install
14
+ git clone https://github.com/ownmy-app/growth-tools
15
+ cd growth-tools
16
+ pip install -e .
17
+
18
+ # Configure your environment
19
+ cp examples/sample-icp.env .env
20
+ # Edit .env with your API keys and brand config
21
+
22
+ # Run Reddit monitor (one-shot)
23
+ growth-reddit
24
+
25
+ # Run the website auditor API
26
+ growth-api
27
+ # or: uvicorn growth_tools.api.main:app --port 8000
28
+
29
+ # Run tests
30
+ pytest tests/ -v
31
+ ```
32
+
33
+ Required environment variables (see `examples/sample-icp.env`):
34
+ ```bash
35
+ OPENAI_API_KEY=sk-proj-...
36
+ REDDIT_CLIENT_ID=...
37
+ REDDIT_CLIENT_SECRET=...
38
+ BRAND_NAME="Your Product"
39
+ ICP_KEYWORDS="supabase,self-host,postgres,..."
40
+ ```
41
+
42
+ ---
43
+
44
+ ## What's included
45
+
46
+ | Module | What it does |
47
+ |--------|-------------|
48
+ | `systems/reddit_capture.py` | Monitors subreddits, two-stage filter (keyword → LLM), saves hot leads |
49
+ | `systems/discord_bot.py` | Discord bot with per-channel cooldown, confidence threshold gating |
50
+ | `systems/website_auditor.py` | Detects tech stack from HTML/headers (Next.js, Vite, Supabase, Vercel…) |
51
+ | `systems/github_auditor.py` | Scans repos for migration readiness (package.json, Dockerfile analysis) |
52
+ | `systems/crm_sequencer.py` | LLM-generated outreach drafts (capped at 90 words for reply rates) |
53
+ | `core/scoring.py` | Hybrid rule + LLM scoring: `0.5 × rule_score + 0.5 × llm_intent_score` |
54
+ | `core/llm.py` | OpenAI client with fallback model + tenacity retries |
55
+ | `api/main.py` | FastAPI: `POST /audit/website`, `POST /audit/github`, `GET /health` |
56
+
57
+ ---
58
+
59
+ ## Scoring tiers
60
+
61
+ | Score | Tier | Action |
62
+ |-------|------|--------|
63
+ | ≥ 80 | **hot** | Immediate outreach |
64
+ | 60–79 | **nurture** | Add to sequence |
65
+ | 40–59 | **educate** | Send content |
66
+ | < 40 | **ignore** | Skip |
67
+
68
+ Rule signals: `+25` high-intent builder (Lovable/Replit/Bolt/v0), `+30` high-intent pain
69
+ (deploy/migrate/security/ownership), `+20` has public repo, `+25` mentions clients.
70
+ Blended 50/50 with LLM intent score.
71
+
72
+ ---
73
+
74
+ ## Supabase schema
75
+
76
+ ```sql
77
+ create table lead_signals (
78
+ id uuid primary key default gen_random_uuid(),
79
+ source text, -- 'reddit' | 'discord' | 'github'
80
+ title text,
81
+ body text,
82
+ url text,
83
+ author text,
84
+ intent_score int,
85
+ tier text,
86
+ builder text,
87
+ pain_type text,
88
+ reply_draft text,
89
+ created_at timestamptz default now()
90
+ );
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Setup
96
+
97
+ ```bash
98
+ git clone https://github.com/ownmy-app/growth-tools
99
+ cd growth-tools
100
+ pip install -e .
101
+ cp examples/sample-icp.env .env
102
+ # Edit .env
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Run
108
+
109
+ ```bash
110
+ # Reddit monitor (one-shot)
111
+ growth-reddit
112
+
113
+ # Discord bot (persistent)
114
+ python -m growth_tools.systems.discord_bot
115
+
116
+ # Website auditor API
117
+ growth-api
118
+ # or: uvicorn growth_tools.api.main:app --port 8000
119
+
120
+ # Audit a specific website
121
+ curl -X POST http://localhost:8000/audit/website -H 'Content-Type: application/json' \
122
+ -d '{"url": "https://example.com"}'
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Customise
128
+
129
+ **Target subreddits** — set `ICP_KEYWORDS` in `.env`
130
+
131
+ **Lead scoring** — edit weights in `core/scoring.py` (or move to YAML config)
132
+
133
+ **Outreach tone** — edit prompts in `core/llm.py`
134
+
135
+ ---
136
+
137
+ ## Immediate next steps
138
+ 1. Make subreddits + keywords configurable via env / YAML
139
+ 2. Add GitHub lead capture (scan repos that import competitor SDKs)
140
+ 3. Add Slack notification on "hot" leads
141
+ 4. Package as `pip install growth-tools`
142
+
143
+ ---
144
+
145
+ ## Commercial viability
146
+ - Open-core: open source the capture + scoring, charge for the CRM sequencer
147
+ - SaaS: $200–500/mo per team for managed lead pipeline
148
+ - Competitors: Trigify, Drippi — neither does GitHub + Reddit + LLM scoring combined
149
+
150
+ ---
151
+
152
+ ## Example output
153
+
154
+ Running `pytest tests/ -v`:
155
+
156
+ ```
157
+ ============================= test session starts ==============================
158
+ platform darwin -- Python 3.13.9, pytest-9.0.2, pluggy-1.5.0
159
+ cachedir: .pytest_cache
160
+ rootdir: /tmp/ownmy-releases/growth-tools
161
+ configfile: pyproject.toml
162
+ plugins: anyio-4.12.1, cov-7.1.0
163
+ collecting ... collected 4 items
164
+
165
+ tests/test_brand_config.py::test_brand_name_reads_from_env PASSED [ 25%]
166
+ tests/test_brand_config.py::test_brand_tagline_reads_from_env PASSED [ 50%]
167
+ tests/test_brand_config.py::test_icp_pain_reads_from_env PASSED [ 75%]
168
+ tests/test_brand_config.py::test_no_hardcoded_brand_names_in_source PASSED [100%]
169
+
170
+ ============================== 4 passed in 0.03s ===============================
171
+ ```
172
+
173
+ See `examples/sample-leads.json` for representative scored lead output and `examples/sample-icp.env` for required environment variable configuration.
@@ -0,0 +1,39 @@
1
+ # Growth Tools — Required Environment Variables
2
+ # Copy this to .env and fill in your values
3
+
4
+ # ── Brand / ICP Configuration ─────────────────────────────────────────────────
5
+ # These define YOUR product so the LLM generates accurate outreach
6
+ BRAND_NAME="Acme DevTools"
7
+ BRAND_TAGLINE="The fastest way to self-host your AI-generated app"
8
+ ICP_PAIN="teams that built with Lovable, Bolt, or Manus and now need to self-host"
9
+ ICP_KEYWORDS="supabase,self-host,postgres,multi-tenant,AI-generated,Lovable,Bolt,Manus,v0"
10
+ OUTREACH_CTA="Want a 5-minute demo?"
11
+
12
+ # ── Reddit Credentials ────────────────────────────────────────────────────────
13
+ REDDIT_CLIENT_ID=your_reddit_client_id
14
+ REDDIT_CLIENT_SECRET=your_reddit_client_secret
15
+ REDDIT_USER_AGENT=growth-tools/0.1 by u/your_reddit_username
16
+ REDDIT_USERNAME=your_reddit_username
17
+ REDDIT_PASSWORD=your_reddit_password
18
+
19
+ # Subreddits to monitor (comma-separated)
20
+ REDDIT_SUBREDDITS=SaaS,webdev,nextjs,reactjs,Supabase,startups,entrepreneur
21
+
22
+ # ── Discord Configuration ─────────────────────────────────────────────────────
23
+ DISCORD_BOT_TOKEN=your_discord_bot_token
24
+ DISCORD_GUILD_IDS=123456789012345678,987654321098765432
25
+
26
+ # ── OpenAI (for LLM scoring) ──────────────────────────────────────────────────
27
+ OPENAI_API_KEY=sk-proj-...
28
+ OPENAI_MODEL=gpt-4o-mini
29
+ LLM_SCORE_THRESHOLD=0.6
30
+
31
+ # ── Supabase (for lead storage) ───────────────────────────────────────────────
32
+ SUPABASE_URL=https://your-project-ref.supabase.co
33
+ SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
34
+
35
+ # ── Scoring Weights ───────────────────────────────────────────────────────────
36
+ # Final score = RULE_WEIGHT * rule_score + LLM_WEIGHT * llm_score
37
+ RULE_WEIGHT=0.5
38
+ LLM_WEIGHT=0.5
39
+ MIN_SCORE_THRESHOLD=0.55
@@ -0,0 +1,78 @@
1
+ [
2
+ {
3
+ "id": "reddit_abc123",
4
+ "source": "reddit",
5
+ "platform_url": "https://reddit.com/r/SaaS/comments/abc123/is_there_a_good_solution_for_multi_tenant_auth",
6
+ "author": "u/buildingmysaas",
7
+ "content": "We're trying to build a multi-tenant SaaS on top of Supabase but running into issues with RLS and per-tenant schemas. Anyone have a good solution? Currently we're on Vercel + Next.js.",
8
+ "subreddit": "SaaS",
9
+ "score": 0.87,
10
+ "rule_score": 0.75,
11
+ "llm_intent_score": 0.99,
12
+ "scoring_breakdown": {
13
+ "keyword_hits": ["supabase", "multi-tenant", "RLS", "Next.js"],
14
+ "pain_match": "schema isolation, auth complexity",
15
+ "intent": "actively evaluating solutions"
16
+ },
17
+ "outreach_draft": "Hey! Saw your post about multi-tenant Supabase — we built a schema-per-tenant migration tool that handles exactly this. It sets up isolated app_{id} schemas with RLS and Supabase auth wired in. Happy to share a quick demo if that's useful.",
18
+ "captured_at": "2026-03-22T09:14:32Z",
19
+ "status": "new"
20
+ },
21
+ {
22
+ "id": "reddit_def456",
23
+ "source": "reddit",
24
+ "platform_url": "https://reddit.com/r/webdev/comments/def456/migrating_from_firebase_to_supabase",
25
+ "author": "u/migrationpain",
26
+ "content": "Has anyone migrated from Firebase to Supabase? We have ~50k users and need to move auth and the Firestore data. Looking for tools that can help automate this.",
27
+ "subreddit": "webdev",
28
+ "score": 0.71,
29
+ "rule_score": 0.65,
30
+ "llm_intent_score": 0.77,
31
+ "scoring_breakdown": {
32
+ "keyword_hits": ["firebase", "supabase", "migrate", "auth"],
33
+ "pain_match": "migration complexity, user data",
34
+ "intent": "looking for migration tooling"
35
+ },
36
+ "outreach_draft": "We help teams migrate from Firebase to Supabase — auth users, Firestore collections, and storage. Done it for teams with 100k+ users. Worth a call?",
37
+ "captured_at": "2026-03-22T10:02:11Z",
38
+ "status": "new"
39
+ },
40
+ {
41
+ "id": "discord_ghi789",
42
+ "source": "discord",
43
+ "platform_url": "https://discord.com/channels/1016518.../#general",
44
+ "author": "devuser#4821",
45
+ "content": "anyone tried deploying a manus.im project to their own infra? want to use postgres instead of their managed db",
46
+ "channel": "general",
47
+ "score": 0.63,
48
+ "rule_score": 0.58,
49
+ "llm_intent_score": 0.68,
50
+ "scoring_breakdown": {
51
+ "keyword_hits": ["manus", "postgres", "deploy", "infra"],
52
+ "pain_match": "vendor lock-in, self-hosting",
53
+ "intent": "exploring self-hosting options"
54
+ },
55
+ "outreach_draft": "Hey! We have a one-command tool that migrates Manus projects to self-hosted Supabase + Postgres. Takes about 5 minutes. DM me if you want to try it.",
56
+ "captured_at": "2026-03-22T11:45:00Z",
57
+ "status": "contacted"
58
+ },
59
+ {
60
+ "id": "reddit_jkl012",
61
+ "source": "reddit",
62
+ "platform_url": "https://reddit.com/r/nextjs/comments/jkl012/security_review_of_ai_generated_code",
63
+ "author": "u/securityminded",
64
+ "content": "We used Bolt to generate our MVP and now our CTO wants a security review before we go to production. Anyone know a good tool that catches secrets and SQL injection in AI-generated code?",
65
+ "subreddit": "nextjs",
66
+ "score": 0.92,
67
+ "rule_score": 0.88,
68
+ "llm_intent_score": 0.96,
69
+ "scoring_breakdown": {
70
+ "keyword_hits": ["bolt", "security", "secrets", "SQL injection", "AI-generated"],
71
+ "pain_match": "production security, AI code quality",
72
+ "intent": "actively searching for a specific tool"
73
+ },
74
+ "outreach_draft": "We built a free static scanner specifically for AI-generated code (Bolt, Lovable, v0). Catches hardcoded secrets, SQL injection, CORS misconfigs — zero dependencies, runs in CI. Check it out at github.com/ownmy-app/security-scanner",
75
+ "captured_at": "2026-03-22T14:30:55Z",
76
+ "status": "new"
77
+ }
78
+ ]
@@ -0,0 +1,14 @@
1
+ ============================= test session starts ==============================
2
+ platform darwin -- Python 3.13.9, pytest-9.0.2, pluggy-1.5.0 -- /Users/architsharma/miniconda3/bin/python3.13
3
+ cachedir: .pytest_cache
4
+ rootdir: /private/tmp/ownmy-releases/growth-tools
5
+ configfile: pyproject.toml
6
+ plugins: anyio-4.12.1, cov-7.1.0
7
+ collecting ... collected 4 items
8
+
9
+ tests/test_brand_config.py::test_brand_name_reads_from_env PASSED [ 25%]
10
+ tests/test_brand_config.py::test_brand_tagline_reads_from_env PASSED [ 50%]
11
+ tests/test_brand_config.py::test_icp_pain_reads_from_env PASSED [ 75%]
12
+ tests/test_brand_config.py::test_no_hardcoded_brand_names_in_source PASSED [100%]
13
+
14
+ ============================== 4 passed in 0.03s ===============================
File without changes
File without changes
@@ -0,0 +1,83 @@
1
+ """
2
+ FastAPI app: website auditor + GitHub repo auditor.
3
+ Run: uvicorn api.main:app --reload (from growth-tools dir)
4
+ """
5
+ import sys
6
+ from pathlib import Path
7
+
8
+ _root = Path(__file__).resolve().parent.parent
9
+ if str(_root) not in sys.path:
10
+ sys.path.insert(0, str(_root))
11
+
12
+ from fastapi import FastAPI, HTTPException
13
+ from fastapi.middleware.cors import CORSMiddleware
14
+ from pydantic import BaseModel
15
+
16
+ from systems.website_auditor import audit_url as website_audit
17
+ from systems.github_auditor import analyze_repo_url as github_audit
18
+ from systems.crm_sequencer import add_lead
19
+ from core.db import is_db_available
20
+
21
+ app = FastAPI(
22
+ title="Growth Tools API",
23
+ description="Website auditor & GitHub repo auditor for production-readiness.",
24
+ version="1.0.0",
25
+ )
26
+ app.add_middleware(
27
+ CORSMiddleware,
28
+ allow_origins=["*"],
29
+ allow_credentials=True,
30
+ allow_methods=["*"],
31
+ allow_headers=["*"],
32
+ )
33
+
34
+
35
+ class AuditWebsiteRequest(BaseModel):
36
+ url: str
37
+ save_as_lead: bool = False
38
+
39
+
40
+ class AuditGitHubRequest(BaseModel):
41
+ repo_url: str
42
+
43
+
44
+ @app.get("/health")
45
+ def health():
46
+ return {"status": "ok", "db": is_db_available()}
47
+
48
+
49
+ @app.post("/audit/website")
50
+ def audit_website(req: AuditWebsiteRequest):
51
+ """Paste app URL; returns detected stack, risks, and next step. Optionally saves as lead."""
52
+ if not req.url or len(req.url) > 2048:
53
+ raise HTTPException(status_code=400, detail="Invalid URL")
54
+ result = website_audit(req.url)
55
+ if req.save_as_lead and result.get("ok") and is_db_available():
56
+ try:
57
+ lead = add_lead(
58
+ source=result.get("url", req.url),
59
+ source_url=result.get("url", req.url),
60
+ title=result.get("title"),
61
+ platform="website",
62
+ pain_type="audit",
63
+ intent_score=50,
64
+ metadata={"audit": result},
65
+ )
66
+ if lead:
67
+ result["lead_id"] = lead.get("id")
68
+ except Exception:
69
+ pass
70
+ return result
71
+
72
+
73
+ @app.post("/audit/github")
74
+ def audit_github(req: AuditGitHubRequest):
75
+ """Provide repo URL; returns detected stack, missing items, migration suggestions."""
76
+ if not req.repo_url or len(req.repo_url) > 2048:
77
+ raise HTTPException(status_code=400, detail="Invalid repo URL")
78
+ return github_audit(req.repo_url)
79
+
80
+
81
+ if __name__ == "__main__":
82
+ import uvicorn
83
+ uvicorn.run(app, host="0.0.0.0", port=8000)