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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import React from 'react';
|
|
15
|
-
import { AbsoluteFill, Sequence, useCurrentFrame, interpolate
|
|
15
|
+
import { AbsoluteFill, Sequence, useCurrentFrame, interpolate } from 'remotion';
|
|
16
16
|
import { BackgroundMusic } from './BackgroundMusic';
|
|
17
17
|
import type { AudioConfig } from '../renderer';
|
|
18
18
|
|
|
@@ -33,7 +33,6 @@ export interface DemoSlideData {
|
|
|
33
33
|
export interface DemoVideoProps {
|
|
34
34
|
slides: DemoSlideData[];
|
|
35
35
|
format: 'feed' | 'reels';
|
|
36
|
-
variant?: 'fast' | 'dynamic';
|
|
37
36
|
audio?: AudioConfig;
|
|
38
37
|
}
|
|
39
38
|
|
|
@@ -44,56 +43,22 @@ const TEXT = '#ffffff';
|
|
|
44
43
|
const MUTED = 'rgba(255,255,255,0.6)';
|
|
45
44
|
const FONT = '"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
46
45
|
|
|
47
|
-
//
|
|
48
|
-
const FRAME_DURATIONS: Record<string,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
cta: 75, // 2.5s
|
|
59
|
-
},
|
|
60
|
-
dynamic: {
|
|
61
|
-
cover: 75, // 2.5s
|
|
62
|
-
terminal: 105, // 3.5s
|
|
63
|
-
key_point: 75, // 2.5s
|
|
64
|
-
notification: 75, // 2.5s
|
|
65
|
-
steps: 105, // 3.5s (kanban)
|
|
66
|
-
kanban: 105, // 3.5s
|
|
67
|
-
pipeline: 105, // 3.5s
|
|
68
|
-
quote: 105, // 3.5s
|
|
69
|
-
cta: 90, // 3s
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// Variant-specific animation configuration
|
|
74
|
-
const ANIMATION_CONFIG = {
|
|
75
|
-
fast: {
|
|
76
|
-
transitionFrames: 8,
|
|
77
|
-
charsPerFrame: 4,
|
|
78
|
-
kanbanDelay: 5,
|
|
79
|
-
enableBounce: false,
|
|
80
|
-
enableSpring: false,
|
|
81
|
-
enableGlow: false,
|
|
82
|
-
},
|
|
83
|
-
dynamic: {
|
|
84
|
-
transitionFrames: 12,
|
|
85
|
-
charsPerFrame: 3,
|
|
86
|
-
kanbanDelay: 7,
|
|
87
|
-
enableBounce: true,
|
|
88
|
-
enableSpring: true,
|
|
89
|
-
enableGlow: true,
|
|
90
|
-
},
|
|
46
|
+
// Custom frame durations for different scene types
|
|
47
|
+
const FRAME_DURATIONS: Record<string, number> = {
|
|
48
|
+
cover: 90, // 3s
|
|
49
|
+
terminal: 150, // 5s
|
|
50
|
+
key_point: 90, // 3s
|
|
51
|
+
notification: 90, // 3s
|
|
52
|
+
steps: 150, // 5s (kanban)
|
|
53
|
+
kanban: 150, // 5s
|
|
54
|
+
pipeline: 135, // 4.5s
|
|
55
|
+
quote: 135, // 4.5s
|
|
56
|
+
cta: 105, // 3.5s
|
|
91
57
|
};
|
|
92
58
|
|
|
93
59
|
// ─── DemoVideo ──────────────────────────────────────────────────────────────
|
|
94
60
|
|
|
95
|
-
export const DemoVideo: React.FC<DemoVideoProps> = ({ slides, audio
|
|
96
|
-
const durations = FRAME_DURATIONS[variant];
|
|
61
|
+
export const DemoVideo: React.FC<DemoVideoProps> = ({ slides, audio }) => {
|
|
97
62
|
let currentFrame = 0;
|
|
98
63
|
|
|
99
64
|
return (
|
|
@@ -103,13 +68,13 @@ export const DemoVideo: React.FC<DemoVideoProps> = ({ slides, audio, variant = '
|
|
|
103
68
|
}}
|
|
104
69
|
>
|
|
105
70
|
{slides.map((slide, i) => {
|
|
106
|
-
const duration =
|
|
71
|
+
const duration = FRAME_DURATIONS[slide.type] || 90;
|
|
107
72
|
const from = currentFrame;
|
|
108
73
|
currentFrame += duration;
|
|
109
74
|
|
|
110
75
|
return (
|
|
111
76
|
<Sequence key={i} from={from} durationInFrames={duration}>
|
|
112
|
-
<DemoSlide slide={slide}
|
|
77
|
+
<DemoSlide slide={slide} />
|
|
113
78
|
</Sequence>
|
|
114
79
|
);
|
|
115
80
|
})}
|
|
@@ -120,30 +85,10 @@ export const DemoVideo: React.FC<DemoVideoProps> = ({ slides, audio, variant = '
|
|
|
120
85
|
|
|
121
86
|
// ─── DemoSlide ──────────────────────────────────────────────────────────────
|
|
122
87
|
|
|
123
|
-
const DemoSlide: React.FC<{ slide: DemoSlideData
|
|
124
|
-
const config = ANIMATION_CONFIG[variant as keyof typeof ANIMATION_CONFIG];
|
|
88
|
+
const DemoSlide: React.FC<{ slide: DemoSlideData }> = ({ slide }) => {
|
|
125
89
|
const frame = useCurrentFrame();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const opacity = interpolate(frame, [0, config.transitionFrames], [0, 1], { extrapolateRight: 'clamp' });
|
|
129
|
-
|
|
130
|
-
let y = interpolate(frame, [0, config.transitionFrames], [24, 0], { extrapolateRight: 'clamp' });
|
|
131
|
-
|
|
132
|
-
if (config.enableBounce && frame > config.transitionFrames) {
|
|
133
|
-
const overshoot = interpolate(
|
|
134
|
-
frame,
|
|
135
|
-
[config.transitionFrames, config.transitionFrames + 8],
|
|
136
|
-
[0, -4],
|
|
137
|
-
{ extrapolateRight: 'clamp' }
|
|
138
|
-
);
|
|
139
|
-
const settle = interpolate(
|
|
140
|
-
frame,
|
|
141
|
-
[config.transitionFrames + 8, config.transitionFrames + 16],
|
|
142
|
-
[-4, 0],
|
|
143
|
-
{ extrapolateRight: 'clamp' }
|
|
144
|
-
);
|
|
145
|
-
y = frame <= config.transitionFrames + 8 ? overshoot : settle;
|
|
146
|
-
}
|
|
90
|
+
const opacity = interpolate(frame, [0, 15], [0, 1], { extrapolateRight: 'clamp' });
|
|
91
|
+
const y = interpolate(frame, [0, 15], [24, 0], { extrapolateRight: 'clamp' });
|
|
147
92
|
|
|
148
93
|
return (
|
|
149
94
|
<AbsoluteFill
|
|
@@ -159,14 +104,14 @@ const DemoSlide: React.FC<{ slide: DemoSlideData; variant: string }> = ({ slide,
|
|
|
159
104
|
alignItems: 'flex-start',
|
|
160
105
|
}}
|
|
161
106
|
>
|
|
162
|
-
<SlideContent slide={slide}
|
|
107
|
+
<SlideContent slide={slide} />
|
|
163
108
|
</AbsoluteFill>
|
|
164
109
|
);
|
|
165
110
|
};
|
|
166
111
|
|
|
167
112
|
// ─── Slide content by type ──────────────────────────────────────────────────
|
|
168
113
|
|
|
169
|
-
function SlideContent({ slide
|
|
114
|
+
function SlideContent({ slide }: { slide: DemoSlideData }) {
|
|
170
115
|
const frame = useCurrentFrame();
|
|
171
116
|
|
|
172
117
|
switch (slide.type) {
|
|
@@ -194,7 +139,7 @@ function SlideContent({ slide, variant }: { slide: DemoSlideData; variant: strin
|
|
|
194
139
|
);
|
|
195
140
|
|
|
196
141
|
case 'terminal':
|
|
197
|
-
return <TerminalScene title={slide.title} content={slide.content || ''} frame={frame}
|
|
142
|
+
return <TerminalScene title={slide.title} content={slide.content || ''} frame={frame} />;
|
|
198
143
|
|
|
199
144
|
case 'notification':
|
|
200
145
|
return <NotificationScene title={slide.title} content={slide.content || ''} frame={frame} />;
|
|
@@ -222,10 +167,10 @@ function SlideContent({ slide, variant }: { slide: DemoSlideData; variant: strin
|
|
|
222
167
|
|
|
223
168
|
case 'steps':
|
|
224
169
|
case 'kanban':
|
|
225
|
-
return <KanbanScene title={slide.title} items={slide.items || []} frame={frame}
|
|
170
|
+
return <KanbanScene title={slide.title} items={slide.items || []} frame={frame} />;
|
|
226
171
|
|
|
227
172
|
case 'pipeline':
|
|
228
|
-
return <PipelineScene title={slide.title} content={slide.content || ''} label={slide.label} frame={frame}
|
|
173
|
+
return <PipelineScene title={slide.title} content={slide.content || ''} label={slide.label} frame={frame} />;
|
|
229
174
|
|
|
230
175
|
case 'quote':
|
|
231
176
|
return (
|
|
@@ -293,11 +238,10 @@ function SlideContent({ slide, variant }: { slide: DemoSlideData; variant: strin
|
|
|
293
238
|
|
|
294
239
|
// ─── Custom Scene Components ────────────────────────────────────────────────
|
|
295
240
|
|
|
296
|
-
function TerminalScene({ title, content, frame
|
|
241
|
+
function TerminalScene({ title, content, frame }: { title: string; content: string; frame: number }) {
|
|
297
242
|
// Typewriter effect
|
|
298
|
-
const config = ANIMATION_CONFIG[variant as keyof typeof ANIMATION_CONFIG];
|
|
299
243
|
const lines = content.split('\n');
|
|
300
|
-
const charsPerFrame =
|
|
244
|
+
const charsPerFrame = 2;
|
|
301
245
|
const visibleChars = Math.floor(frame * charsPerFrame);
|
|
302
246
|
|
|
303
247
|
let charCount = 0;
|
|
@@ -378,9 +322,7 @@ function NotificationScene({ title, content, frame }: { title: string; content:
|
|
|
378
322
|
);
|
|
379
323
|
}
|
|
380
324
|
|
|
381
|
-
function KanbanScene({ title, items, frame
|
|
382
|
-
const config = ANIMATION_CONFIG[variant as keyof typeof ANIMATION_CONFIG];
|
|
383
|
-
|
|
325
|
+
function KanbanScene({ title, items, frame }: { title: string; items: string[]; frame: number }) {
|
|
384
326
|
return (
|
|
385
327
|
<div style={{ width: '100%' }}>
|
|
386
328
|
<div
|
|
@@ -397,19 +339,9 @@ function KanbanScene({ title, items, frame, variant }: { title: string; items: s
|
|
|
397
339
|
</div>
|
|
398
340
|
<div style={{ display: 'flex', gap: 24 }}>
|
|
399
341
|
{items.map((item, i) => {
|
|
400
|
-
const delay = i *
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
if (config.enableSpring) {
|
|
405
|
-
// Use spring physics
|
|
406
|
-
opacity = spring({ frame: frame - delay, fps: 30, config: { damping: 15, mass: 0.5 } });
|
|
407
|
-
scale = spring({ frame: frame - delay, fps: 30, config: { damping: 12, mass: 0.6 } }) * 0.2 + 0.8;
|
|
408
|
-
} else {
|
|
409
|
-
// Use linear interpolation
|
|
410
|
-
opacity = interpolate(frame, [delay, delay + 15], [0, 1], { extrapolateRight: 'clamp' });
|
|
411
|
-
scale = interpolate(frame, [delay, delay + 15], [0.8, 1], { extrapolateRight: 'clamp' });
|
|
412
|
-
}
|
|
342
|
+
const delay = i * 10;
|
|
343
|
+
const opacity = interpolate(frame, [delay, delay + 15], [0, 1], { extrapolateRight: 'clamp' });
|
|
344
|
+
const scale = interpolate(frame, [delay, delay + 15], [0.8, 1], { extrapolateRight: 'clamp' });
|
|
413
345
|
|
|
414
346
|
return (
|
|
415
347
|
<div
|
|
@@ -436,8 +368,7 @@ function KanbanScene({ title, items, frame, variant }: { title: string; items: s
|
|
|
436
368
|
);
|
|
437
369
|
}
|
|
438
370
|
|
|
439
|
-
function PipelineScene({ title, content, label, frame
|
|
440
|
-
const config = ANIMATION_CONFIG[variant as keyof typeof ANIMATION_CONFIG];
|
|
371
|
+
function PipelineScene({ title, content, label, frame }: { title: string; content: string; label?: string; frame: number }) {
|
|
441
372
|
const steps = content.split(' → ');
|
|
442
373
|
const progress = interpolate(frame, [0, 100], [0, 1], { extrapolateRight: 'clamp' });
|
|
443
374
|
|
|
@@ -456,41 +387,26 @@ function PipelineScene({ title, content, label, frame, variant }: { title: strin
|
|
|
456
387
|
{title}
|
|
457
388
|
</div>
|
|
458
389
|
<div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 32 }}>
|
|
459
|
-
{steps.map((step, i) =>
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
<
|
|
475
|
-
<div
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
borderRadius: 8,
|
|
480
|
-
fontSize: 20,
|
|
481
|
-
fontWeight: 600,
|
|
482
|
-
color: isActive ? '#0f172a' : TEXT,
|
|
483
|
-
boxShadow,
|
|
484
|
-
}}
|
|
485
|
-
>
|
|
486
|
-
{step}
|
|
487
|
-
</div>
|
|
488
|
-
{i < steps.length - 1 && (
|
|
489
|
-
<div style={{ fontSize: 24, color: MUTED }}>→</div>
|
|
490
|
-
)}
|
|
491
|
-
</React.Fragment>
|
|
492
|
-
);
|
|
493
|
-
})}
|
|
390
|
+
{steps.map((step, i) => (
|
|
391
|
+
<React.Fragment key={i}>
|
|
392
|
+
<div
|
|
393
|
+
style={{
|
|
394
|
+
padding: '16px 24px',
|
|
395
|
+
background: i / (steps.length - 1) <= progress ? ACCENT : 'rgba(255,255,255,0.1)',
|
|
396
|
+
borderRadius: 8,
|
|
397
|
+
fontSize: 20,
|
|
398
|
+
fontWeight: 600,
|
|
399
|
+
color: i / (steps.length - 1) <= progress ? '#0f172a' : TEXT,
|
|
400
|
+
transition: 'all 0.3s',
|
|
401
|
+
}}
|
|
402
|
+
>
|
|
403
|
+
{step}
|
|
404
|
+
</div>
|
|
405
|
+
{i < steps.length - 1 && (
|
|
406
|
+
<div style={{ fontSize: 24, color: MUTED }}>→</div>
|
|
407
|
+
)}
|
|
408
|
+
</React.Fragment>
|
|
409
|
+
))}
|
|
494
410
|
</div>
|
|
495
411
|
{label && (
|
|
496
412
|
<div
|
|
@@ -111,30 +111,11 @@ export const RemotionRoot: React.FC = () => {
|
|
|
111
111
|
<Composition
|
|
112
112
|
id="DemoFeed"
|
|
113
113
|
component={DemoComp}
|
|
114
|
-
durationInFrames={
|
|
114
|
+
durationInFrames={810} // 27 seconds at 30fps
|
|
115
115
|
fps={30}
|
|
116
116
|
width={1080}
|
|
117
117
|
height={1080}
|
|
118
|
-
defaultProps={{ slides: defaultDemoSlides, format: 'feed'
|
|
119
|
-
calculateMetadata={({ props }) => {
|
|
120
|
-
const p = props as unknown as DemoVideoProps;
|
|
121
|
-
const variant = p.variant || 'dynamic';
|
|
122
|
-
|
|
123
|
-
// Calculate total duration based on variant and slides
|
|
124
|
-
const durations = variant === 'fast'
|
|
125
|
-
? { cover: 60, terminal: 90, key_point: 60, notification: 60, steps: 90, kanban: 90, pipeline: 90, quote: 90, cta: 75 }
|
|
126
|
-
: { cover: 75, terminal: 105, key_point: 75, notification: 75, steps: 105, kanban: 105, pipeline: 105, quote: 105, cta: 90 };
|
|
127
|
-
|
|
128
|
-
let totalFrames = 0;
|
|
129
|
-
p.slides.forEach(slide => {
|
|
130
|
-
totalFrames += durations[slide.type as keyof typeof durations] || 90;
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
durationInFrames: totalFrames,
|
|
135
|
-
props,
|
|
136
|
-
};
|
|
137
|
-
}}
|
|
118
|
+
defaultProps={{ slides: defaultDemoSlides, format: 'feed' } as DemoVideoProps}
|
|
138
119
|
/>
|
|
139
120
|
</>
|
|
140
121
|
);
|
|
@@ -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)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# /distribution-repurpose — Content Repurposing Pipeline
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
```
|
|
5
|
+
/distribution-repurpose # Repurpose latest shipped idea
|
|
6
|
+
/distribution-repurpose {idea-id} # Repurpose specific shipped idea
|
|
7
|
+
/distribution-repurpose --content="..." # Repurpose arbitrary content
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Input
|
|
11
|
+
- `$ARGUMENTS` — optional: idea ID or content to repurpose
|
|
12
|
+
|
|
13
|
+
## Process
|
|
14
|
+
|
|
15
|
+
### Step 1: Load Source Content
|
|
16
|
+
1. If idea ID provided, read from `data/ideas.json`
|
|
17
|
+
2. If no argument, find the most recently shipped idea
|
|
18
|
+
3. Read `data/positioning.json` — messaging pillars for consistent voice
|
|
19
|
+
4. Read `data/social.json` — understand which platforms are active
|
|
20
|
+
|
|
21
|
+
Extract from source:
|
|
22
|
+
- **Title/headline** — the main hook
|
|
23
|
+
- **Key insight** — what's new/interesting
|
|
24
|
+
- **Target audience** — who cares about this
|
|
25
|
+
- **Technical details** — for dev-focused channels
|
|
26
|
+
- **Business impact** — for business-focused channels
|
|
27
|
+
- **Visual assets** — screenshots, diagrams, ship cards
|
|
28
|
+
|
|
29
|
+
### Step 2: Generate Channel-Specific Adaptations
|
|
30
|
+
|
|
31
|
+
For each active channel, create a tailored version:
|
|
32
|
+
|
|
33
|
+
#### Twitter/X Thread (5-7 tweets)
|
|
34
|
+
- Tweet 1: Hook — the most surprising/valuable insight
|
|
35
|
+
- Tweet 2-5: Story arc — problem → solution → result → detail
|
|
36
|
+
- Tweet 6: Takeaway or lesson learned
|
|
37
|
+
- Tweet 7: CTA with link + UTM
|
|
38
|
+
- Use patterns from `ai-content-generator.ts` (hooks, engagement patterns)
|
|
39
|
+
- Queue: `social-draft-thread-{topic}`
|
|
40
|
+
|
|
41
|
+
#### LinkedIn Post (Professional angle)
|
|
42
|
+
- Opening line: Pattern interrupt or contrarian take
|
|
43
|
+
- Body: "Here's what I learned building [feature]..."
|
|
44
|
+
- Formatting: Short paragraphs, line breaks, no hashtag spam
|
|
45
|
+
- CTA: Soft — "What's your experience with [topic]?"
|
|
46
|
+
- Queue: `copy-social-linkedin`
|
|
47
|
+
|
|
48
|
+
#### Reddit Post (Value-first, subreddit-adapted)
|
|
49
|
+
- Title: Question or insight format (NOT promotional)
|
|
50
|
+
- Body: Genuine story, metrics shared transparently, lessons learned
|
|
51
|
+
- Adapt tone to target subreddit (technical for r/programming, casual for r/SideProject)
|
|
52
|
+
- Link in context only, never as main content
|
|
53
|
+
- Queue: idea with tags ["growth", "reddit", "{subreddit}"]
|
|
54
|
+
|
|
55
|
+
#### Google Ads Keyword Group
|
|
56
|
+
- Map content to search intent keywords
|
|
57
|
+
- If content solves a problem → target "[problem] solution" keywords
|
|
58
|
+
- If content is a comparison → target "[product] vs [competitor]" keywords
|
|
59
|
+
- Queue: `copy-ad-google-{keyword}`
|
|
60
|
+
|
|
61
|
+
#### Meta Retargeting Ad
|
|
62
|
+
- Target: People who visited the content page but didn't convert
|
|
63
|
+
- Creative: Key visual from the content + social proof
|
|
64
|
+
- CTA: Return to complete signup
|
|
65
|
+
- Queue: `copy-ad-meta-retargeting-{content-slug}`
|
|
66
|
+
|
|
67
|
+
#### Email Newsletter Segment
|
|
68
|
+
- Subject line: Hook adapted for email (curiosity gap)
|
|
69
|
+
- Body: Summary with "read more" link
|
|
70
|
+
- Segment: Users interested in [topic]
|
|
71
|
+
- Queue: `email-blast-{campaign-slug}` or include in next digest
|
|
72
|
+
|
|
73
|
+
#### Indie Hackers / Dev.to Post
|
|
74
|
+
- Longer form, more transparent about metrics and journey
|
|
75
|
+
- Include code snippets if technical
|
|
76
|
+
- End with question to encourage discussion
|
|
77
|
+
- Cross-post with canonical URL to own blog
|
|
78
|
+
|
|
79
|
+
### Step 3: UTM Attribution Matrix
|
|
80
|
+
Each adaptation gets consistent tracking:
|
|
81
|
+
|
|
82
|
+
| Channel | utm_source | utm_medium | utm_campaign |
|
|
83
|
+
|---------|-----------|-----------|-------------|
|
|
84
|
+
| Twitter/X | twitter | social | {content-slug} |
|
|
85
|
+
| LinkedIn | linkedin | social | {content-slug} |
|
|
86
|
+
| Reddit | reddit | community | {content-slug} |
|
|
87
|
+
| Google Ads | google | cpc | {content-slug} |
|
|
88
|
+
| Meta Ads | meta | paid | retarget-{content-slug} |
|
|
89
|
+
| Email | email | newsletter | {content-slug} |
|
|
90
|
+
| Indie Hackers | indiehackers | community | {content-slug} |
|
|
91
|
+
| Dev.to | devto | blog | {content-slug} |
|
|
92
|
+
|
|
93
|
+
### Step 4: Publishing Schedule
|
|
94
|
+
Stagger publishing for maximum reach:
|
|
95
|
+
|
|
96
|
+
| Day | Channel | Why |
|
|
97
|
+
|-----|---------|-----|
|
|
98
|
+
| Day 0 | Twitter thread | Immediate, test the hook |
|
|
99
|
+
| Day 1 | LinkedIn post | Business hours reach |
|
|
100
|
+
| Day 2 | Reddit post | Different audience, value-first |
|
|
101
|
+
| Day 3 | Email newsletter | Owned channel, reliable |
|
|
102
|
+
| Day 5 | Dev.to / IH post | Long-form, search indexed |
|
|
103
|
+
| Day 7 | Google Ads | If content validates search intent |
|
|
104
|
+
| Ongoing | Meta retargeting | Runs continuously for page visitors |
|
|
105
|
+
|
|
106
|
+
### Step 5: Output
|
|
107
|
+
Create ideas in `data/ideas.json` for each channel adaptation:
|
|
108
|
+
- Category: "growth"
|
|
109
|
+
- Tags: ["growth", "repurpose", "{channel}", "{source-idea-id}"]
|
|
110
|
+
- Implementation plan with channel-specific content draft
|
|
111
|
+
- Success metrics: channel-specific (impressions, clicks, referral signups)
|
|
112
|
+
- Queue relevant tasks for each channel
|
|
113
|
+
|
|
114
|
+
Print summary:
|
|
115
|
+
- Source content: [title]
|
|
116
|
+
- Adaptations generated: [count]
|
|
117
|
+
- Channels covered: [list]
|
|
118
|
+
- Tasks queued: [list]
|
|
119
|
+
|
|
120
|
+
## Output Files
|
|
121
|
+
- `data/ideas.json` — repurposed content campaign ideas
|