vibebusiness 1.2.87 → 1.2.89
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/.next/standalone/.env +27 -14
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-build-manifest.json +89 -72
- package/.next/standalone/.next/app-path-routes-manifest.json +1 -1
- package/.next/standalone/.next/build-manifest.json +8 -8
- package/.next/standalone/.next/prerender-manifest.json +1 -1
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/routes-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/.next/server/app/api/analyze/route.js +1 -1
- package/.next/standalone/.next/server/app/api/analyze/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/briefing/route.js +1 -0
- package/.next/standalone/.next/server/app/api/briefing/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/checkout/route.js +1 -1
- package/.next/standalone/.next/server/app/api/config/detect-repos/route.js +1 -1
- package/.next/standalone/.next/server/app/api/config/route.js +1 -1
- package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/epics/[id]/ideas/route.js +1 -1
- package/.next/standalone/.next/server/app/api/epics/[id]/ideas/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/epics/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/epics/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/epics/route.js +1 -1
- package/.next/standalone/.next/server/app/api/epics/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/goals/[id]/kpis/route.js +1 -1
- package/.next/standalone/.next/server/app/api/goals/[id]/kpis/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/goals/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/goals/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/goals/route.js +1 -1
- package/.next/standalone/.next/server/app/api/goals/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/health/route.js +1 -1
- package/.next/standalone/.next/server/app/api/hypotheses/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/hypotheses/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/hypotheses/route.js +1 -1
- package/.next/standalone/.next/server/app/api/hypotheses/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/card/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/card/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/comments/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/comments/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/implement/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/implement/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/transition/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[id]/transition/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ideas/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/implementations/route.js +1 -1
- package/.next/standalone/.next/server/app/api/implementations/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/investor-updates/generate/route.js +1 -1
- package/.next/standalone/.next/server/app/api/kpis/refresh/route.js +1 -1
- package/.next/standalone/.next/server/app/api/kpis/refresh/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/license/route.js +1 -1
- package/.next/standalone/.next/server/app/api/portal/route.js +1 -1
- package/.next/standalone/.next/server/app/api/provider-status/route.js +1 -1
- package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js +1 -1
- package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/social/[id]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/social/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/social/route.js +1 -1
- package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/webhook/route.js +1 -1
- package/.next/standalone/.next/server/app/briefing/page.js +1 -0
- package/.next/standalone/.next/server/app/briefing/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/briefing/page_client-reference-manifest.js +1 -0
- package/.next/standalone/.next/server/app/goals/[id]/page.js +1 -1
- package/.next/standalone/.next/server/app/goals/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/goals/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/goals/page.js +1 -1
- package/.next/standalone/.next/server/app/goals/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/goals/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/hypotheses/[id]/page.js +1 -1
- package/.next/standalone/.next/server/app/hypotheses/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/hypotheses/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/hypotheses/page.js +1 -1
- package/.next/standalone/.next/server/app/hypotheses/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/hypotheses/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/ideas/[id]/page.js +1 -1
- package/.next/standalone/.next/server/app/ideas/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/ideas/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -0
- package/.next/standalone/.next/server/app/index.meta +6 -0
- package/.next/standalone/.next/server/app/index.rsc +6 -0
- package/.next/standalone/.next/server/app/kanban/page.js +1 -0
- package/.next/standalone/.next/server/app/kanban/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/kanban/page_client-reference-manifest.js +1 -0
- package/.next/standalone/.next/server/app/page.js +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/[id]/page.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/roadmap/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/investors/page.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/investors/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/roadmap/investors/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/page.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/roadmap/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/public/page.js +1 -1
- package/.next/standalone/.next/server/app/roadmap/public/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/roadmap/public/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/sessions/page.js +1 -1
- package/.next/standalone/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page.js +1 -1
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings.html +1 -1
- package/.next/standalone/.next/server/app/settings.rsc +3 -3
- package/.next/standalone/.next/server/app/social/page.js +1 -1
- package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/social.html +1 -1
- package/.next/standalone/.next/server/app/social.rsc +3 -3
- package/.next/standalone/.next/server/app/updates/[id]/page.js +1 -1
- package/.next/standalone/.next/server/app/updates/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/updates/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/updates/new/page.js +1 -1
- package/.next/standalone/.next/server/app/updates/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/updates/new.html +1 -1
- package/.next/standalone/.next/server/app/updates/new.rsc +3 -3
- package/.next/standalone/.next/server/app/updates/page.js +1 -1
- package/.next/standalone/.next/server/app/updates/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/updates/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +18 -15
- package/.next/standalone/.next/server/chunks/3098.js +1 -0
- package/.next/standalone/.next/server/chunks/3871.js +1 -1
- package/.next/standalone/.next/server/chunks/4355.js +1 -0
- package/.next/standalone/.next/server/chunks/4471.js +2 -2
- package/.next/standalone/.next/server/chunks/7151.js +10 -10
- package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/data/business-context.json +31 -181
- package/.next/standalone/data/codebase-snapshot.json +64 -42
- package/.next/standalone/data/competitors.json +39 -559
- package/.next/standalone/data/config.json +16 -40
- package/.next/standalone/data/goals.json +35 -410
- package/.next/standalone/data/positioning.json +10 -127
- package/.next/standalone/data/sessions.json +84 -299
- package/.next/standalone/node_modules/@esbuild/{darwin-arm64 → darwin-x64}/bin/esbuild +0 -0
- package/.next/standalone/node_modules/@esbuild/{darwin-arm64 → darwin-x64}/package.json +3 -3
- package/.next/standalone/package.json +3 -2
- package/.next/standalone/scripts/analyze.ts +70 -21
- package/.next/standalone/scripts/implement.ts +67 -17
- package/.next/standalone/server.js +1 -1
- package/.next/standalone/templates/commands/distribution-google-ads.md +86 -0
- package/.next/standalone/templates/commands/distribution-meta-ads.md +106 -0
- package/.next/standalone/templates/commands/distribution-repurpose.md +121 -0
- package/.next/standalone/templates/commands/distribution-seo-content.md +115 -0
- package/.next/standalone/templates/commands/distribution-social-expansion.md +128 -0
- package/.next/static/chunks/147-b00f2ac2bbec93ae.js +1 -0
- package/.next/static/chunks/159-4ce492ccac6de8f7.js +1 -0
- package/.next/static/chunks/47-eba0f8b4f9b17641.js +1 -0
- package/.next/static/chunks/547-921898871311cd72.js +1 -0
- package/.next/static/chunks/619-2b2ff3b9eaef112c.js +1 -0
- package/.next/static/chunks/735-b33805b2b19d17ad.js +1 -0
- package/.next/static/chunks/879-7fbd95e93ddc4636.js +1 -0
- package/.next/static/chunks/930-330300153dfcbfc0.js +1 -0
- package/.next/static/chunks/app/briefing/page-683aba0c52e910d7.js +1 -0
- package/.next/static/chunks/app/goals/[id]/page-40818dc7e710eeda.js +1 -0
- package/.next/static/chunks/app/goals/page-f80a64a68854e357.js +1 -0
- package/.next/static/chunks/app/hypotheses/[id]/page-023c882fa395f3ed.js +1 -0
- package/.next/static/chunks/app/hypotheses/page-168748bde00e7d90.js +1 -0
- package/.next/static/chunks/app/ideas/[id]/page-5f33e0ecf590ddec.js +1 -0
- package/.next/static/chunks/app/kanban/page-4f18f1e4f56948a5.js +1 -0
- package/.next/static/chunks/app/layout-cd1571ba4ed4a0fa.js +1 -0
- package/.next/static/chunks/app/page-0a8b9a7b052e6eac.js +1 -0
- package/.next/static/chunks/app/roadmap/[id]/page-9ba8a537e30c633c.js +1 -0
- package/.next/static/chunks/app/roadmap/investors/{page-0095ea5695573796.js → page-a914223623f56df3.js} +1 -1
- package/.next/static/chunks/app/roadmap/page-30de1fdc304eb572.js +1 -0
- package/.next/static/chunks/app/roadmap/public/page-c481b3f9217919ac.js +1 -0
- package/.next/static/chunks/app/sessions/page-d7eefd2fd42b4d55.js +1 -0
- package/.next/static/chunks/app/settings/{page-3afa908a96ce4e51.js → page-caf6daf930e4f2c6.js} +1 -1
- package/.next/static/chunks/app/social/page-21daeca0cf8af46b.js +1 -0
- package/.next/static/chunks/app/updates/[id]/page-2807cd17ae4938d0.js +1 -0
- package/.next/static/chunks/app/updates/new/{page-dcc67ffca587dcc2.js → page-ac5b966024ce0ddc.js} +1 -1
- package/.next/static/chunks/app/updates/page-b6efcdaae7f4f6d2.js +1 -0
- package/.next/static/chunks/{main-6ee938c5db2d5eb4.js → main-3eb11800bc19ca7f.js} +1 -1
- package/.next/static/chunks/{main-app-f42d9aa726a818bf.js → main-app-06ab73909d2a44c7.js} +1 -1
- package/.next/static/chunks/webpack-616e068a201ad621.js +1 -0
- package/.next/static/css/ff70d16171b1c02c.css +3 -0
- package/dist/bin/vibebusiness.js +1 -8
- package/dist/scripts/analyze.js +161 -19
- package/dist/scripts/heartbeat.js +24 -129
- package/dist/scripts/implement.js +77 -15
- package/dist/scripts/scan.js +0 -3
- package/dist/scripts/social-routine.js +0 -3
- package/package.json +3 -2
- package/scripts/lib/video/compositions/DemoVideo.tsx +50 -134
- package/scripts/lib/video/compositions/Root.tsx +2 -21
- package/templates/commands/distribution-google-ads.md +86 -0
- package/templates/commands/distribution-meta-ads.md +106 -0
- package/templates/commands/distribution-repurpose.md +121 -0
- package/templates/commands/distribution-seo-content.md +115 -0
- package/templates/commands/distribution-social-expansion.md +128 -0
- package/.next/standalone/.next/server/chunks/6299.js +0 -1
- package/.next/standalone/.next/server/chunks/995.js +0 -1
- package/.next/standalone/data/.analysis-prompt.txt +0 -170
- package/.next/standalone/data/copy/landing-improvements-2026-02-20.md +0 -111
- package/.next/standalone/data/copy/landing-landing-page-2026-02-20.md +0 -68
- package/.next/standalone/data/email-campaigns/sequences/onboarding.md +0 -183
- package/.next/standalone/data/email-campaigns/welcome-2026-02-20.md +0 -42
- package/.next/standalone/data/heartbeat-sessions.json +0 -7550
- package/.next/standalone/data/hypotheses.json +0 -269
- package/.next/standalone/data/ideas.json +0 -10764
- package/.next/standalone/data/implementations.json +0 -3342
- package/.next/standalone/data/pages.json +0 -22
- package/.next/standalone/data/payments.json +0 -33
- package/.next/standalone/data/reports/visuals/idea-3f4595f7-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-4rxt3mkj-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-6631456b-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-boot-001-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-fb3eba74-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-first-tweet-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-lp-hero-specificity-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-lp-og-meta-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-lp-social-proof-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-prqf3lob-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-readme-landing-url-card.png +0 -0
- package/.next/standalone/data/reports/visuals/idea-stripe-integration-card.png +0 -0
- package/.next/standalone/data/reports/visuals/promo-launch.png +0 -0
- package/.next/standalone/data/reports/visuals/promo-ship-fast.png +0 -0
- package/.next/standalone/data/reports/visuals/promo-while-you-slept-v2.png +0 -0
- package/.next/standalone/data/reports/visuals/promo-while-you-slept-v3.png +0 -0
- package/.next/standalone/data/reports/visuals/promo-while-you-slept.png +0 -0
- package/.next/standalone/data/social.json +0 -194
- package/.next/standalone/data/social.json.backup +0 -179
- package/.next/standalone/data/videos/ad-solo-founder-burnout.mp4 +0 -0
- package/.next/standalone/data/videos/ai-gets-business-feed.mp4 +0 -0
- package/.next/standalone/data/videos/idea-graveyard-feed.mp4 +0 -0
- package/.next/standalone/data/videos/lonely-founder-feed.mp4 +0 -0
- package/.next/standalone/data/videos/staging/ad-solo-founder-burnout.json +0 -54
- package/.next/standalone/data/videos/staging/ai-gets-business.json +0 -55
- package/.next/standalone/data/videos/staging/idea-graveyard.json +0 -61
- package/.next/standalone/data/videos/staging/lonely-founder.json +0 -60
- package/.next/standalone/data/videos/staging/while-you-slept-v2-fast.json +0 -67
- package/.next/standalone/data/videos/staging/while-you-slept-v3-dynamic.json +0 -67
- package/.next/standalone/data/videos/while-you-slept-demo-feed.mp4 +0 -0
- package/.next/standalone/data/videos/while-you-slept-v2-fast-feed.mp4 +0 -0
- package/.next/standalone/data/videos/while-you-slept-v3-dynamic-feed.mp4 +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/48519e014fdef8bfe40a0d447e90c96c/0.pack +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/48519e014fdef8bfe40a0d447e90c96c/index.pack +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/c99d23d3548030c8ff8de678c71eeb15/0.pack +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/c99d23d3548030c8ff8de678c71eeb15/1.pack +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/c99d23d3548030c8ff8de678c71eeb15/2.pack +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/c99d23d3548030c8ff8de678c71eeb15/3.pack +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/c99d23d3548030c8ff8de678c71eeb15/index.pack +0 -0
- package/.next/standalone/node_modules/.cache/webpack/remotion-production-4.0.428/c99d23d3548030c8ff8de678c71eeb15/index.pack.old +0 -0
- package/.next/static/chunks/280-fd1092f75f985b1e.js +0 -1
- package/.next/static/chunks/354-d5bc9619159f46c5.js +0 -1
- package/.next/static/chunks/429-8f4030371ebef5c3.js +0 -1
- package/.next/static/chunks/809-833fcb9fe6e81fd6.js +0 -1
- package/.next/static/chunks/827-6cf4bfc10d1ff0c7.js +0 -1
- package/.next/static/chunks/851-65b033bf38847cbb.js +0 -1
- package/.next/static/chunks/app/goals/[id]/page-231bb4daae0f06eb.js +0 -1
- package/.next/static/chunks/app/goals/page-4dfa36ac38853b88.js +0 -1
- package/.next/static/chunks/app/hypotheses/[id]/page-6ec09d5470557c18.js +0 -1
- package/.next/static/chunks/app/hypotheses/page-1732b7466579493e.js +0 -1
- package/.next/static/chunks/app/ideas/[id]/page-b3dfe1e61fc656a4.js +0 -1
- package/.next/static/chunks/app/layout-eeef7928298d2198.js +0 -1
- package/.next/static/chunks/app/page-d325a95479e7c453.js +0 -1
- package/.next/static/chunks/app/roadmap/[id]/page-b93a96f017c8d3dd.js +0 -1
- package/.next/static/chunks/app/roadmap/page-eacd69a99fcfc658.js +0 -1
- package/.next/static/chunks/app/roadmap/public/page-6b791041894b76d2.js +0 -1
- package/.next/static/chunks/app/sessions/page-a56ea625acdfa13e.js +0 -1
- package/.next/static/chunks/app/social/page-5211c78a5f37df65.js +0 -1
- package/.next/static/chunks/app/updates/[id]/page-fa20533878416cd0.js +0 -1
- package/.next/static/chunks/app/updates/page-19a09d7046577f70.js +0 -1
- package/.next/static/chunks/webpack-a3c37fcbf859f6f9.js +0 -1
- package/.next/static/css/654766eb547c6bab.css +0 -3
- /package/.next/static/{kgtR3Ls8MG4aQqwp3I0UE → UaMf1fmArAE78vyk_zQVK}/_buildManifest.js +0 -0
- /package/.next/static/{kgtR3Ls8MG4aQqwp3I0UE → UaMf1fmArAE78vyk_zQVK}/_ssgManifest.js +0 -0
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* npm run analyze -- --type=metrics
|
|
12
12
|
* npm run analyze -- --type=seo
|
|
13
13
|
* npm run analyze -- --type=research --topic="response time optimization" --context=<base64>
|
|
14
|
+
* npm run analyze -- --type=growth
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
import 'dotenv/config';
|
|
@@ -19,7 +20,7 @@ import * as fs from 'fs';
|
|
|
19
20
|
import * as path from 'path';
|
|
20
21
|
import { v4 as uuidv4 } from 'uuid';
|
|
21
22
|
import { getAnalysisPrompt } from '../src/lib/prompts';
|
|
22
|
-
import type { AnalystConfig as ImportedAnalystConfig, BusinessConfig
|
|
23
|
+
import type { AnalystConfig as ImportedAnalystConfig, BusinessConfig } from '../src/lib/types';
|
|
23
24
|
import { atomicWriteFileSync } from './lib/json-lock';
|
|
24
25
|
import { requireClaudeCLI } from './lib/ai-provider';
|
|
25
26
|
import { logError, logWarn } from './lib/logger';
|
|
@@ -117,7 +118,7 @@ import {
|
|
|
117
118
|
} from './lib/paths';
|
|
118
119
|
|
|
119
120
|
// Analysis types
|
|
120
|
-
type AnalysisType = 'quick' | 'deep' | 'metrics' | 'seo' | 'research';
|
|
121
|
+
type AnalysisType = 'quick' | 'deep' | 'metrics' | 'seo' | 'research' | 'growth';
|
|
121
122
|
|
|
122
123
|
// Parse command line arguments
|
|
123
124
|
function parseArgs(): { type: AnalysisType; topic?: string; context?: string } {
|
|
@@ -129,7 +130,7 @@ function parseArgs(): { type: AnalysisType; topic?: string; context?: string } {
|
|
|
129
130
|
for (const arg of args) {
|
|
130
131
|
if (arg.startsWith('--type=')) {
|
|
131
132
|
const value = arg.split('=')[1];
|
|
132
|
-
if (['quick', 'deep', 'metrics', 'seo', 'research'].includes(value)) {
|
|
133
|
+
if (['quick', 'deep', 'metrics', 'seo', 'research', 'growth'].includes(value)) {
|
|
133
134
|
type = value as AnalysisType;
|
|
134
135
|
}
|
|
135
136
|
} else if (arg.startsWith('--topic=')) {
|
|
@@ -253,16 +254,38 @@ function updateSession(sessionId: string, updates: Partial<Session>): void {
|
|
|
253
254
|
}
|
|
254
255
|
}
|
|
255
256
|
|
|
256
|
-
//
|
|
257
|
+
// Buffer for session log lines, keyed by session id
|
|
258
|
+
const pendingLogs = new Map<string, string[]>();
|
|
259
|
+
|
|
260
|
+
// Add log to session (buffered — call flushSessionLogs to persist)
|
|
257
261
|
function addSessionLog(sessionId: string, message: string): void {
|
|
258
|
-
const sessions = loadSessions();
|
|
259
|
-
const index = sessions.sessions.findIndex((s) => s.id === sessionId);
|
|
260
|
-
if (index !== -1) {
|
|
261
|
-
const timestamp = new Date().toISOString();
|
|
262
|
-
sessions.sessions[index].logs.push(`[${timestamp}] ${message}`);
|
|
263
|
-
saveSessions(sessions);
|
|
264
|
-
}
|
|
265
262
|
console.log(message);
|
|
263
|
+
const timestamp = new Date().toISOString();
|
|
264
|
+
const entry = `[${timestamp}] ${message}`;
|
|
265
|
+
const existing = pendingLogs.get(sessionId) ?? [];
|
|
266
|
+
existing.push(entry);
|
|
267
|
+
pendingLogs.set(sessionId, existing);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Flush buffered log lines to disk in a single write
|
|
271
|
+
function flushSessionLogs(sessionId: string): void {
|
|
272
|
+
const lines = pendingLogs.get(sessionId);
|
|
273
|
+
const n = lines?.length ?? 0;
|
|
274
|
+
console.log(`[analyze] Flushing ${n} buffered log lines for session ${sessionId}`);
|
|
275
|
+
try {
|
|
276
|
+
const sessions = loadSessions();
|
|
277
|
+
const index = sessions.sessions.findIndex((s) => s.id === sessionId);
|
|
278
|
+
if (index !== -1 && lines && lines.length > 0) {
|
|
279
|
+
sessions.sessions[index].logs.push(...lines);
|
|
280
|
+
saveSessions(sessions);
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
284
|
+
console.log(`[analyze] ERROR: failed to flush session logs for ${sessionId}: ${msg}`);
|
|
285
|
+
throw err;
|
|
286
|
+
} finally {
|
|
287
|
+
pendingLogs.delete(sessionId);
|
|
288
|
+
}
|
|
266
289
|
}
|
|
267
290
|
|
|
268
291
|
// Load goals and format as context string for prompts
|
|
@@ -409,14 +432,34 @@ function generatePrompt(
|
|
|
409
432
|
// Parse ideas from Claude's response
|
|
410
433
|
export function parseIdeas(response: string, sessionId: string): BusinessIdea[] {
|
|
411
434
|
// Try to extract JSON array from the response
|
|
412
|
-
|
|
413
|
-
|
|
435
|
+
// Strategy: first try markdown-fenced JSON, then raw JSON array
|
|
436
|
+
let jsonStr: string | null = null;
|
|
437
|
+
|
|
438
|
+
// 1. Try ```json ... ``` fenced block
|
|
439
|
+
const fencedMatch = response.match(/```json\s*\n?([\s\S]*?)```/);
|
|
440
|
+
if (fencedMatch) {
|
|
441
|
+
const inner = fencedMatch[1].trim();
|
|
442
|
+
if (inner.startsWith('[')) {
|
|
443
|
+
jsonStr = inner;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// 2. Fallback: raw JSON array anywhere in the response
|
|
448
|
+
if (!jsonStr) {
|
|
449
|
+
const rawMatch = response.match(/\[\s*\{[\s\S]*\}\s*\]/);
|
|
450
|
+
if (rawMatch) {
|
|
451
|
+
jsonStr = rawMatch[0];
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (!jsonStr) {
|
|
414
456
|
console.error('No JSON array found in response');
|
|
457
|
+
console.error('Response preview (first 500 chars):', response.slice(0, 500));
|
|
415
458
|
return [];
|
|
416
459
|
}
|
|
417
460
|
|
|
418
461
|
try {
|
|
419
|
-
const rawIdeas = JSON.parse(
|
|
462
|
+
const rawIdeas = JSON.parse(jsonStr) as IdeaInput[];
|
|
420
463
|
const now = new Date().toISOString();
|
|
421
464
|
|
|
422
465
|
return rawIdeas.map((idea) => {
|
|
@@ -488,12 +531,9 @@ export function parseIdeas(response: string, sessionId: string): BusinessIdea[]
|
|
|
488
531
|
title: idea.title || 'Untitled Idea',
|
|
489
532
|
summary: idea.summary || '',
|
|
490
533
|
category: idea.category || 'product',
|
|
491
|
-
priority:
|
|
492
|
-
effort:
|
|
493
|
-
impact:
|
|
494
|
-
if (idea.impact) logError('analyze:parseIdeas', new Error(`invalid impact "${idea.impact}" for idea "${idea.title}" — defaulting to "m"`));
|
|
495
|
-
return 'm' as SizeEstimate;
|
|
496
|
-
})(),
|
|
534
|
+
priority: idea.priority || 'medium',
|
|
535
|
+
effort: idea.effort || 'm',
|
|
536
|
+
impact: idea.impact || 'm',
|
|
497
537
|
context: idea.context || '',
|
|
498
538
|
rationale: idea.rationale || '',
|
|
499
539
|
implementation_plan: idea.implementation_plan || '',
|
|
@@ -556,6 +596,7 @@ async function runClaudeAnalysis(
|
|
|
556
596
|
console.log('[analyze] Prompt sent via stdin — no temp file written');
|
|
557
597
|
const claude = spawn('claude', [
|
|
558
598
|
'--print',
|
|
599
|
+
'--output-format', 'text',
|
|
559
600
|
'--dangerously-skip-permissions',
|
|
560
601
|
], {
|
|
561
602
|
cwd: workDir,
|
|
@@ -615,7 +656,13 @@ async function runClaudeAnalysis(
|
|
|
615
656
|
if (code === 0) {
|
|
616
657
|
logWarn('analyze:runClaudeAnalysis', `completed in ${elapsed}s phases=[${timing.phases.join(',')}]`);
|
|
617
658
|
console.log(`Claude Code completed in ${elapsed}s`);
|
|
618
|
-
|
|
659
|
+
console.log(`[analyze] stdout length: ${output.length}, stderr length: ${errorOutput.length}`);
|
|
660
|
+
if (output.length === 0 && errorOutput.length > 0) {
|
|
661
|
+
console.log('[analyze] WARNING: stdout empty but stderr has content — using stderr as response');
|
|
662
|
+
resolve(errorOutput);
|
|
663
|
+
} else {
|
|
664
|
+
resolve(output);
|
|
665
|
+
}
|
|
619
666
|
} else {
|
|
620
667
|
reject(new Error(`Claude Code exited with code ${code} after ${elapsed}s: ${errorOutput}`));
|
|
621
668
|
}
|
|
@@ -851,6 +898,8 @@ async function main() {
|
|
|
851
898
|
console.error('\n=== Analysis Failed ===');
|
|
852
899
|
console.error(error);
|
|
853
900
|
process.exit(1);
|
|
901
|
+
} finally {
|
|
902
|
+
flushSessionLogs(session.id);
|
|
854
903
|
}
|
|
855
904
|
}
|
|
856
905
|
|
|
@@ -68,6 +68,7 @@ interface ImplementationSession {
|
|
|
68
68
|
id: string;
|
|
69
69
|
idea_id: string;
|
|
70
70
|
status: string;
|
|
71
|
+
error_message?: string;
|
|
71
72
|
repo_name: string;
|
|
72
73
|
branch_name: string;
|
|
73
74
|
workspace_path: string;
|
|
@@ -173,6 +174,27 @@ function updateIdea(ideaId: string, updates: Partial<BusinessIdea['implementatio
|
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
// Revert idea stage from 'in_progress' back to 'approved' on failure
|
|
178
|
+
export function revertIdeaStage(ideaId: string, reason: string): void {
|
|
179
|
+
try {
|
|
180
|
+
const data = loadJson<{ ideas: Array<{ id: string; stage: string; comments: Array<{ id: string; author: string; body: string; created_at: string }> }> }>(IDEAS_FILE);
|
|
181
|
+
const index = data.ideas.findIndex((i) => i.id === ideaId);
|
|
182
|
+
if (index !== -1) {
|
|
183
|
+
data.ideas[index].stage = 'approved';
|
|
184
|
+
if (!data.ideas[index].comments) data.ideas[index].comments = [];
|
|
185
|
+
data.ideas[index].comments.push({
|
|
186
|
+
id: `comment-${Date.now()}`,
|
|
187
|
+
author: 'system',
|
|
188
|
+
body: reason,
|
|
189
|
+
created_at: new Date().toISOString(),
|
|
190
|
+
});
|
|
191
|
+
saveJson(IDEAS_FILE, data);
|
|
192
|
+
}
|
|
193
|
+
} catch (e) {
|
|
194
|
+
console.error('[implement] Failed to revert idea stage', { ideaId, error: (e as Error).message });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
176
198
|
// Create/update implementation session
|
|
177
199
|
function createImplementation(
|
|
178
200
|
ideaId: string,
|
|
@@ -198,7 +220,7 @@ function createImplementation(
|
|
|
198
220
|
return impl;
|
|
199
221
|
}
|
|
200
222
|
|
|
201
|
-
function updateImplementation(id: string, updates: Partial<ImplementationSession>): void {
|
|
223
|
+
export function updateImplementation(id: string, updates: Partial<ImplementationSession>): void {
|
|
202
224
|
const data = loadJson<{ implementations: ImplementationSession[] }>(IMPLEMENTATIONS_FILE);
|
|
203
225
|
const index = data.implementations.findIndex((i) => i.id === id);
|
|
204
226
|
if (index !== -1) {
|
|
@@ -420,7 +442,7 @@ async function runImplementation(
|
|
|
420
442
|
implId: string,
|
|
421
443
|
timeoutMs: number = 300000,
|
|
422
444
|
options: { model?: string; scoped?: boolean } = {}
|
|
423
|
-
): Promise<
|
|
445
|
+
): Promise<void> {
|
|
424
446
|
requireClaudeCLI('implementation');
|
|
425
447
|
|
|
426
448
|
const modelLabel = options.model ? ` (model: ${options.model})` : '';
|
|
@@ -443,7 +465,7 @@ async function runImplementation(
|
|
|
443
465
|
|
|
444
466
|
claudeArgs.push('-p', prompt);
|
|
445
467
|
|
|
446
|
-
return new Promise((resolve) => {
|
|
468
|
+
return new Promise((resolve, reject) => {
|
|
447
469
|
const claude = spawn('claude', claudeArgs, {
|
|
448
470
|
cwd: workspacePath,
|
|
449
471
|
env: { ...process.env },
|
|
@@ -475,7 +497,7 @@ async function runImplementation(
|
|
|
475
497
|
setTimeout(() => {
|
|
476
498
|
try { claude.kill('SIGKILL'); } catch {}
|
|
477
499
|
}, 5000);
|
|
478
|
-
|
|
500
|
+
reject(new Error(`Implementation timed out after ${timeoutMs / 1000}s`));
|
|
479
501
|
}
|
|
480
502
|
}, timeoutMs);
|
|
481
503
|
|
|
@@ -499,10 +521,10 @@ async function runImplementation(
|
|
|
499
521
|
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
|
500
522
|
if (code === 0) {
|
|
501
523
|
addLog(implId, `Claude Code completed successfully in ${elapsed}s (${output.length} chars)`);
|
|
502
|
-
resolve(
|
|
524
|
+
resolve();
|
|
503
525
|
} else {
|
|
504
526
|
addLog(implId, `Claude Code exited with code ${code} after ${elapsed}s`);
|
|
505
|
-
|
|
527
|
+
reject(new Error(`Claude Code exited with code ${code}`));
|
|
506
528
|
}
|
|
507
529
|
});
|
|
508
530
|
|
|
@@ -511,7 +533,7 @@ async function runImplementation(
|
|
|
511
533
|
isResolved = true;
|
|
512
534
|
clearTimeout(timeout);
|
|
513
535
|
addLog(implId, `Claude Code error: ${error.message}`);
|
|
514
|
-
|
|
536
|
+
reject(error);
|
|
515
537
|
});
|
|
516
538
|
});
|
|
517
539
|
}
|
|
@@ -618,11 +640,29 @@ async function main(): Promise<void> {
|
|
|
618
640
|
if (createPrOnly) console.log(`Mode: Create PR only`);
|
|
619
641
|
|
|
620
642
|
// Load config and idea
|
|
621
|
-
|
|
622
|
-
|
|
643
|
+
let config: ReturnType<typeof loadConfig>;
|
|
644
|
+
try {
|
|
645
|
+
config = loadConfig();
|
|
646
|
+
} catch (err: unknown) {
|
|
647
|
+
const e = err as Error;
|
|
648
|
+
console.error('[implement] Failed to load config', { error: e.message, file: CONFIG_FILE });
|
|
649
|
+
console.error(`[implement] Cannot continue without config — exiting. Check that ${CONFIG_FILE} exists and contains valid JSON.`);
|
|
650
|
+
process.exit(1);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
let idea: ReturnType<typeof loadIdea>;
|
|
654
|
+
try {
|
|
655
|
+
idea = loadIdea(ideaId);
|
|
656
|
+
} catch (err: unknown) {
|
|
657
|
+
const e = err as Error;
|
|
658
|
+
console.error('[implement] Failed to load idea', { ideaId, error: e.message, file: IDEAS_FILE });
|
|
659
|
+
console.error(`[implement] Cannot continue without idea record — exiting. Check that ${IDEAS_FILE} exists and contains valid JSON.`);
|
|
660
|
+
process.exit(1);
|
|
661
|
+
}
|
|
623
662
|
|
|
624
663
|
if (!idea) {
|
|
625
|
-
console.error(
|
|
664
|
+
console.error('[implement] Failed to load idea', { ideaId, error: 'idea not found in ideas file', file: IDEAS_FILE });
|
|
665
|
+
console.error(`[implement] Idea ${ideaId} not found — exiting.`);
|
|
626
666
|
process.exit(1);
|
|
627
667
|
}
|
|
628
668
|
|
|
@@ -657,7 +697,14 @@ async function main(): Promise<void> {
|
|
|
657
697
|
console.log(`Workspace: ${config.workspace_dir}`);
|
|
658
698
|
|
|
659
699
|
// Try to reuse an existing implementation session
|
|
660
|
-
|
|
700
|
+
let implData: { implementations: ImplementationSession[] };
|
|
701
|
+
try {
|
|
702
|
+
implData = loadJson<{ implementations: ImplementationSession[] }>(IMPLEMENTATIONS_FILE);
|
|
703
|
+
} catch (err: unknown) {
|
|
704
|
+
const e = err as Error;
|
|
705
|
+
console.error('[implement] Failed to load implementations file, falling back to fresh session', { error: e.message, file: IMPLEMENTATIONS_FILE });
|
|
706
|
+
implData = { implementations: [] };
|
|
707
|
+
}
|
|
661
708
|
const existingImpl = implData.implementations.find(
|
|
662
709
|
(i) => i.idea_id === ideaId && i.status !== 'failed' && i.status !== 'completed'
|
|
663
710
|
);
|
|
@@ -745,15 +792,11 @@ async function main(): Promise<void> {
|
|
|
745
792
|
// Run implementation
|
|
746
793
|
updateImplementation(impl.id, { status: 'implementing' });
|
|
747
794
|
const prompt = generatePrompt(idea, scope);
|
|
748
|
-
|
|
795
|
+
await runImplementation(workspacePath, prompt, impl.id, timeout, {
|
|
749
796
|
model: model || (scope ? 'sonnet' : undefined), // Default to sonnet for sub-tasks
|
|
750
797
|
scoped: !!scope,
|
|
751
798
|
});
|
|
752
799
|
|
|
753
|
-
if (!success) {
|
|
754
|
-
throw new Error('Implementation failed');
|
|
755
|
-
}
|
|
756
|
-
|
|
757
800
|
// Check for changes and commit
|
|
758
801
|
if (hasChanges(workspacePath)) {
|
|
759
802
|
addLog(impl.id, 'Changes detected, staging and committing...');
|
|
@@ -843,11 +886,18 @@ async function main(): Promise<void> {
|
|
|
843
886
|
addLog(impl.id, `Error: ${err.message}`);
|
|
844
887
|
updateImplementation(impl.id, {
|
|
845
888
|
status: 'failed',
|
|
889
|
+
error_message: err.message,
|
|
846
890
|
});
|
|
891
|
+
revertIdeaStage(ideaId, `Implementation failed: ${err.message}`);
|
|
892
|
+
console.error('[implement] Fatal error', { ideaId, implId: impl.id, error: err.message, stack: err.stack });
|
|
847
893
|
console.error(`\n=== Implementation Failed ===`);
|
|
848
894
|
console.error(err.message);
|
|
849
895
|
process.exit(1);
|
|
850
896
|
}
|
|
851
897
|
}
|
|
852
898
|
|
|
853
|
-
main()
|
|
899
|
+
// Only run main() when executed directly (not when imported in tests)
|
|
900
|
+
const _scriptPath = process.argv[1] ?? '';
|
|
901
|
+
if (_scriptPath.endsWith('implement.ts') || _scriptPath.endsWith('implement.js')) {
|
|
902
|
+
main().catch(console.error);
|
|
903
|
+
}
|
|
@@ -9,7 +9,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
|
|
|
9
9
|
const hostname = process.env.HOSTNAME || '0.0.0.0'
|
|
10
10
|
|
|
11
11
|
let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
|
|
12
|
-
const nextConfig = {"env":{},"webpack":null,"eslint":{"ignoreDuringBuilds":false},"typescript":{"ignoreBuildErrors":false,"tsconfigPath":"tsconfig.json"},"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.js","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"analyticsId":"","images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[16,32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":60,"formats":["image/webp"],"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"inline","remotePatterns":[],"unoptimized":false},"devIndicators":{"buildActivity":true,"buildActivityPosition":"bottom-right"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"amp":{"canonicalBase":""},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"optimizeFonts":true,"excludeDefaultMomentLocales":true,"serverRuntimeConfig":{},"publicRuntimeConfig":{},"reactProductionProfiling":false,"reactStrictMode":true,"httpAgentOptions":{"keepAlive":true},"outputFileTracing":true,"staticPageGenerationTimeout":60,"swcMinify":true,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"experimental":{"multiZoneDraftMode":false,"prerenderEarlyExit":false,"serverMinification":true,"serverSourceMaps":false,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","middlewarePrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":
|
|
12
|
+
const nextConfig = {"env":{},"webpack":null,"eslint":{"ignoreDuringBuilds":false},"typescript":{"ignoreBuildErrors":false,"tsconfigPath":"tsconfig.json"},"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.js","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"analyticsId":"","images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[16,32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":60,"formats":["image/webp"],"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"inline","remotePatterns":[],"unoptimized":false},"devIndicators":{"buildActivity":true,"buildActivityPosition":"bottom-right"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"amp":{"canonicalBase":""},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"optimizeFonts":true,"excludeDefaultMomentLocales":true,"serverRuntimeConfig":{},"publicRuntimeConfig":{},"reactProductionProfiling":false,"reactStrictMode":true,"httpAgentOptions":{"keepAlive":true},"outputFileTracing":true,"staticPageGenerationTimeout":60,"swcMinify":true,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"experimental":{"multiZoneDraftMode":false,"prerenderEarlyExit":false,"serverMinification":true,"serverSourceMaps":false,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","middlewarePrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":11,"memoryBasedWorkersCount":false,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"outputFileTracingRoot":"/Users/luismey/Code/100xmanager","swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"adjustFontFallbacks":false,"adjustFontFallbacksWithSizeAdjust":false,"typedRoutes":false,"instrumentationHook":false,"bundlePagesExternals":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"missingSuspenseWithCSRBailout":true,"optimizeServerReact":true,"useEarlyImport":false,"staleTimes":{"dynamic":30,"static":300},"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"configFileName":"next.config.js"}
|
|
13
13
|
|
|
14
14
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
|
|
15
15
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# /distribution-google-ads — Google Ads Campaign Playbook
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
```
|
|
5
|
+
/distribution-google-ads # Full campaign design
|
|
6
|
+
/distribution-google-ads {keyword} # Campaign for specific keyword cluster
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Input
|
|
10
|
+
- `$ARGUMENTS` — optional: specific keyword or keyword cluster to target
|
|
11
|
+
|
|
12
|
+
## Process
|
|
13
|
+
|
|
14
|
+
### Step 1: Load Context
|
|
15
|
+
1. Read `data/positioning.json` — value proposition, target audience, differentiators
|
|
16
|
+
2. Read `data/competitors.json` — competitor SEO keywords, growth channels
|
|
17
|
+
3. Read `data/business-context.json` — product name, funnels, KPIs, monetization
|
|
18
|
+
|
|
19
|
+
### Step 2: Keyword Research
|
|
20
|
+
Use WebSearch to find keyword opportunities:
|
|
21
|
+
- `"[product category] google ads keywords [year]"`
|
|
22
|
+
- `"[product category] search volume CPC benchmarks"`
|
|
23
|
+
- `"[competitor name] google ads keywords"` (for each top competitor)
|
|
24
|
+
- `"[product pain point] solution"` (problem-aware searches)
|
|
25
|
+
|
|
26
|
+
For each keyword group, estimate:
|
|
27
|
+
- Monthly search volume
|
|
28
|
+
- Average CPC
|
|
29
|
+
- Competition level (low/medium/high)
|
|
30
|
+
- Commercial intent (informational/commercial/transactional)
|
|
31
|
+
|
|
32
|
+
### Step 3: Campaign Structure
|
|
33
|
+
Design campaigns following Google Ads best practices:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Campaign: [Product Category] — Search
|
|
37
|
+
├── Ad Group: Brand Terms
|
|
38
|
+
│ ├── Keywords: [product name], [product name] review, [product name] pricing
|
|
39
|
+
│ └── Negative: free, open source, tutorial
|
|
40
|
+
├── Ad Group: Problem-Aware
|
|
41
|
+
│ ├── Keywords: [pain point] solution, how to [solve problem]
|
|
42
|
+
│ └── Negative: DIY, manual
|
|
43
|
+
├── Ad Group: Competitor Terms
|
|
44
|
+
│ ├── Keywords: [competitor] alternative, [competitor] vs
|
|
45
|
+
│ └── Negative: [competitor] login, [competitor] support
|
|
46
|
+
└── Ad Group: Category Terms
|
|
47
|
+
├── Keywords: best [category] tool, [category] software
|
|
48
|
+
└── Negative: free, open source
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Step 4: Generate Ad Copy
|
|
52
|
+
For each ad group, queue copy generation:
|
|
53
|
+
- `/promo-copy ad-google {keyword}` — generates 3 headlines (30 chars) + 2 descriptions (90 chars)
|
|
54
|
+
- Ensure copy matches keyword intent
|
|
55
|
+
- Include call-to-action aligned with landing page
|
|
56
|
+
|
|
57
|
+
### Step 5: Landing Page Recommendations
|
|
58
|
+
For each ad group:
|
|
59
|
+
- Map to existing page if available (check `data/pages.json`)
|
|
60
|
+
- If no matching page exists, queue `/build-page {slug}` with ad-specific messaging
|
|
61
|
+
- Ensure landing page has conversion tracking (PostHog events)
|
|
62
|
+
|
|
63
|
+
### Step 6: Budget & Bidding Strategy
|
|
64
|
+
Recommend starting budget:
|
|
65
|
+
- **Phase 1 (Week 1-2):** $10-15/day across all ad groups — gather data
|
|
66
|
+
- **Phase 2 (Week 3-4):** Pause underperformers, double down on winners — $15-20/day
|
|
67
|
+
- **Bidding:** Start with Maximize Clicks, switch to Target CPA after 30 conversions
|
|
68
|
+
|
|
69
|
+
### Step 7: Conversion Tracking
|
|
70
|
+
Define tracking setup:
|
|
71
|
+
- UTM parameters: `utm_source=google&utm_medium=cpc&utm_campaign={campaign-slug}&utm_content={ad-group}`
|
|
72
|
+
- PostHog events to track: page_view, signup_started, signup_completed
|
|
73
|
+
- Google Ads conversion action: signup_completed
|
|
74
|
+
|
|
75
|
+
### Step 8: Output
|
|
76
|
+
For each campaign, create an idea in `data/ideas.json` with:
|
|
77
|
+
- Category: "growth"
|
|
78
|
+
- Tags: ["growth", "google-ads", "{keyword-group}"]
|
|
79
|
+
- Implementation plan with full campaign structure
|
|
80
|
+
- Success metrics: impressions, clicks, CTR, CPC, conversions, CPA
|
|
81
|
+
- Budget recommendation
|
|
82
|
+
- Queue `copy-ad-google-{keyword}` tasks
|
|
83
|
+
|
|
84
|
+
## Output Files
|
|
85
|
+
- `data/ideas.json` — new Google Ads campaign ideas
|
|
86
|
+
- `data/campaigns/` — campaign briefs (optional)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# /distribution-meta-ads — Meta/Instagram Ads Campaign Playbook
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
```
|
|
5
|
+
/distribution-meta-ads # Full campaign design
|
|
6
|
+
/distribution-meta-ads {audience} # Campaign for specific audience segment
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Input
|
|
10
|
+
- `$ARGUMENTS` — optional: specific audience segment to target
|
|
11
|
+
|
|
12
|
+
## Process
|
|
13
|
+
|
|
14
|
+
### Step 1: Load Context
|
|
15
|
+
1. Read `data/positioning.json` — value proposition, target audience, pain points
|
|
16
|
+
2. Read `data/business-context.json` — product name, funnels, KPIs
|
|
17
|
+
3. Read `data/competitors.json` — competitor ad strategies
|
|
18
|
+
|
|
19
|
+
### Step 2: Audience Research
|
|
20
|
+
Use WebSearch to find audience targeting opportunities:
|
|
21
|
+
- `"[product category] facebook ads benchmarks CPM CPC CPA [year]"`
|
|
22
|
+
- `"[product category] facebook ads targeting"`
|
|
23
|
+
- `"[target audience] interests facebook ads"`
|
|
24
|
+
|
|
25
|
+
Define audience segments:
|
|
26
|
+
|
|
27
|
+
**Segment 1: Interest-Based (Cold)**
|
|
28
|
+
- Interests: [product category tools], [competitor names], [related technologies]
|
|
29
|
+
- Demographics: [age range], [job titles if B2B]
|
|
30
|
+
- Estimated audience size
|
|
31
|
+
|
|
32
|
+
**Segment 2: Behavior-Based (Warm)**
|
|
33
|
+
- Behaviors: Technology early adopters, SaaS users, [industry-specific]
|
|
34
|
+
- Layered with interests for precision
|
|
35
|
+
|
|
36
|
+
**Segment 3: Retargeting (Hot)**
|
|
37
|
+
- Website visitors (last 30 days) who didn't convert
|
|
38
|
+
- Pricing page visitors (last 14 days)
|
|
39
|
+
- Blog readers (last 60 days)
|
|
40
|
+
|
|
41
|
+
**Segment 4: Lookalike**
|
|
42
|
+
- Based on existing signups/customers
|
|
43
|
+
- 1% lookalike for precision, 3-5% for reach
|
|
44
|
+
|
|
45
|
+
### Step 3: Campaign Structure
|
|
46
|
+
Design campaigns following Meta Ads best practices:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Campaign: [Product] — Conversions
|
|
50
|
+
├── Ad Set: Interest-Based (Cold)
|
|
51
|
+
│ ├── Audience: [interests + demographics]
|
|
52
|
+
│ ├── Placement: Feed + Stories (auto)
|
|
53
|
+
│ └── Budget: $5/day
|
|
54
|
+
├── Ad Set: Retargeting (Hot)
|
|
55
|
+
│ ├── Audience: Website visitors 30d, excl. signups
|
|
56
|
+
│ ├── Placement: Feed + Stories (auto)
|
|
57
|
+
│ └── Budget: $3/day
|
|
58
|
+
└── Ad Set: Lookalike 1%
|
|
59
|
+
├── Audience: Lookalike of signups
|
|
60
|
+
├── Placement: Feed + Stories (auto)
|
|
61
|
+
└── Budget: $5/day
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Step 4: Generate Ad Copy
|
|
65
|
+
For each audience segment, queue copy generation:
|
|
66
|
+
- `/promo-copy ad-meta {audience}` — generates primary text + headline + CTA
|
|
67
|
+
- Match messaging to audience temperature (cold=educate, warm=convince, hot=convert)
|
|
68
|
+
|
|
69
|
+
### Step 5: Creative Format Recommendations
|
|
70
|
+
For each ad set, recommend creative format:
|
|
71
|
+
- **Cold audiences:** Carousel (3-5 feature cards) or short video (15-30s)
|
|
72
|
+
- **Retargeting:** Single image with social proof / testimonial
|
|
73
|
+
- **Lookalike:** Video demo or before/after comparison
|
|
74
|
+
|
|
75
|
+
If video skills are available, queue `/promo-video ad-{topic}` for video creatives.
|
|
76
|
+
|
|
77
|
+
### Step 6: Budget & Schedule
|
|
78
|
+
- **Total daily budget:** $10-15/day starting
|
|
79
|
+
- **Split:** 40% cold, 20% retargeting, 40% lookalike
|
|
80
|
+
- **Schedule:** Run 7 days, then evaluate
|
|
81
|
+
- **Dayparting:** If relevant, focus on business hours for B2B
|
|
82
|
+
|
|
83
|
+
### Step 7: A/B Test Plan
|
|
84
|
+
For each ad set:
|
|
85
|
+
- Test 2-3 ad copy variations
|
|
86
|
+
- Test 2 creative formats (image vs carousel vs video)
|
|
87
|
+
- Measure for 7 days before declaring winner
|
|
88
|
+
- Winning criteria: lowest CPA or highest CTR (depending on objective)
|
|
89
|
+
|
|
90
|
+
### Step 8: Tracking
|
|
91
|
+
- UTM parameters: `utm_source=meta&utm_medium=paid&utm_campaign={campaign-slug}&utm_content={ad-set}`
|
|
92
|
+
- Pixel events: ViewContent, Lead, CompleteRegistration
|
|
93
|
+
- CAPI (Conversions API) setup recommendation if not configured
|
|
94
|
+
|
|
95
|
+
### Step 9: Output
|
|
96
|
+
For each campaign, create an idea in `data/ideas.json` with:
|
|
97
|
+
- Category: "growth"
|
|
98
|
+
- Tags: ["growth", "meta-ads", "{audience-segment}"]
|
|
99
|
+
- Implementation plan with campaign structure
|
|
100
|
+
- Success metrics: impressions, reach, CPM, CPC, CTR, conversions, CPA
|
|
101
|
+
- Budget recommendation
|
|
102
|
+
- Queue `copy-ad-meta-{audience}` tasks
|
|
103
|
+
|
|
104
|
+
## Output Files
|
|
105
|
+
- `data/ideas.json` — new Meta Ads campaign ideas
|
|
106
|
+
- `data/campaigns/` — campaign briefs (optional)
|