vibebusiness 1.2.65 → 1.2.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +19 -19
  3. package/.next/standalone/.next/app-path-routes-manifest.json +1 -1
  4. package/.next/standalone/.next/build-manifest.json +2 -2
  5. package/.next/standalone/.next/prerender-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  7. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  8. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  9. package/.next/standalone/.next/server/app/api/investor-updates/generate/route.js +1 -1
  10. package/.next/standalone/.next/server/app/api/investor-updates/generate/route.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js +1 -1
  12. package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/goals/[id]/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/goals/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/hypotheses/[id]/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/hypotheses/page_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/ideas/[id]/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/roadmap/[id]/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/roadmap/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/settings.html +1 -1
  24. package/.next/standalone/.next/server/app/settings.rsc +1 -1
  25. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/social.html +1 -1
  27. package/.next/standalone/.next/server/app/social.rsc +1 -1
  28. package/.next/standalone/.next/server/app/updates/[id]/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/updates/new/page.js +1 -1
  30. package/.next/standalone/.next/server/app/updates/new/page_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/updates/new.html +1 -1
  32. package/.next/standalone/.next/server/app/updates/new.rsc +2 -2
  33. package/.next/standalone/.next/server/app/updates/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app-paths-manifest.json +13 -13
  35. package/.next/standalone/.next/server/chunks/{7599.js → 3794.js} +33 -25
  36. package/.next/standalone/.next/server/pages/404.html +1 -1
  37. package/.next/standalone/.next/server/pages/500.html +1 -1
  38. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  39. package/.next/standalone/data/business-context.json +1 -1
  40. package/.next/standalone/data/goals.json +93 -12
  41. package/.next/standalone/data/ideas.json +58 -17
  42. package/.next/standalone/data/implementations.json +53 -0
  43. package/.next/standalone/data/social.json +49 -1
  44. package/.next/standalone/package.json +1 -1
  45. package/.next/standalone/scripts/investor-update.ts +249 -12
  46. package/.next/standalone/scripts/skills/social-media.ts +239 -34
  47. package/.next/static/chunks/app/updates/new/page-dcc67ffca587dcc2.js +1 -0
  48. package/dist/scripts/heartbeat.js +205 -30
  49. package/dist/scripts/social-routine.js +205 -30
  50. package/package.json +1 -1
  51. package/.next/standalone/.next/server/chunks/1685.js +0 -6
  52. package/.next/standalone/.next/server/chunks/7564.js +0 -81
  53. package/.next/standalone/scripts/skills/investor-update.ts +0 -476
  54. package/.next/static/chunks/app/updates/new/page-c518fba0d9ffae98.js +0 -1
  55. /package/.next/static/{yXi8K8u58qskYid0oHU5f → Gsf15cMKd-7htpbN5eZHd}/_buildManifest.js +0 -0
  56. /package/.next/static/{yXi8K8u58qskYid0oHU5f → Gsf15cMKd-7htpbN5eZHd}/_ssgManifest.js +0 -0
@@ -14,6 +14,9 @@
14
14
  import * as fs from 'fs';
15
15
  import * as path from 'path';
16
16
  import { execSync } from 'child_process';
17
+ import positioning from '../data/positioning.json' assert { type: 'json' };
18
+ import { fetchNpmStats, type NpmStats } from './lib/data-sources/npm-stats.js';
19
+ import { fetchGitHubStats, type GitHubStats } from './lib/data-sources/github-stats.js';
17
20
 
18
21
  // ─── Types ───────────────────────────────────────────────────────────────────
19
22
 
@@ -57,13 +60,15 @@ interface KPI {
57
60
  id: string;
58
61
  name: string;
59
62
  description: string;
60
- current_value: number | null;
61
- target_value: number | null;
63
+ source?: string; // e.g., 'manual', 'npm', 'github', 'posthog', 'calculated'
64
+ query?: string;
65
+ current_value: number | string | null;
66
+ target_value: number | string | null;
62
67
  unit: string;
63
68
  direction: 'higher_is_better' | 'lower_is_better';
64
69
  history: Array<{
65
70
  date: string;
66
- value: number;
71
+ value: number | string;
67
72
  }>;
68
73
  }
69
74
 
@@ -181,7 +186,8 @@ function detectCompanyStage(goalMetrics: GoalMetrics[]): CompanyStage {
181
186
 
182
187
  const totalUsers = userMetrics.reduce((sum, m) => {
183
188
  const current = m.goal.kpis[0]?.current_value;
184
- return sum + (current ?? 0);
189
+ const numericValue = typeof current === 'number' ? current : 0;
190
+ return sum + numericValue;
185
191
  }, 0);
186
192
 
187
193
  if (totalUsers === 0) return CompanyStage.PreLaunch;
@@ -196,7 +202,8 @@ function shouldIncludeMetric(kpi: KPI, stage: CompanyStage): boolean {
196
202
  const lowerName = kpi.name.toLowerCase();
197
203
 
198
204
  if (internalMetrics.some((m) => lowerName.includes(m))) {
199
- return (kpi.current_value ?? 0) > 0; // Only show if non-zero
205
+ const numericValue = typeof kpi.current_value === 'number' ? kpi.current_value : 0;
206
+ return numericValue > 0; // Only show if non-zero
200
207
  }
201
208
  }
202
209
  return true;
@@ -284,7 +291,7 @@ function inferEpicImpact(epic: Epic, allIdeas: BusinessIdea[]): string {
284
291
 
285
292
  interface GoalMetrics {
286
293
  goal: BusinessGoal;
287
- previous_value: number;
294
+ previous_value: number | string;
288
295
  growth_pct: string;
289
296
  delta: number;
290
297
  }
@@ -305,8 +312,14 @@ function getGoalMetrics(goalsFilePath: string, since: Date): GoalMetrics[] {
305
312
  .sort((a, b) => b.date.localeCompare(a.date))[0];
306
313
 
307
314
  const previous_value = previousEntry?.value ?? kpi.current_value;
308
- const delta = kpi.current_value - previous_value;
309
- const growth_pct = calculateGrowthPct(kpi.current_value, previous_value);
315
+
316
+ // Only calculate numeric deltas and growth
317
+ const currentNumeric = typeof kpi.current_value === 'number' ? kpi.current_value : null;
318
+ const previousNumeric = typeof previous_value === 'number' ? previous_value : null;
319
+ const delta = (currentNumeric !== null && previousNumeric !== null) ? currentNumeric - previousNumeric : 0;
320
+ const growth_pct = (currentNumeric !== null && previousNumeric !== null)
321
+ ? calculateGrowthPct(currentNumeric, previousNumeric)
322
+ : '0';
310
323
 
311
324
  metrics.push({
312
325
  goal: {
@@ -509,24 +522,31 @@ function generateExecutiveSummary(
509
522
  commitCount: number,
510
523
  learnings: string[]
511
524
  ): string {
525
+ // Extract market context from positioning data
526
+ const marketContext = positioning.current;
527
+ const sam = "$1.8-6B"; // From positioning SAM
528
+ const topDifferentiator = "full lifecycle loop: observe → analyze → recommend → implement → ship → verify"; // First differentiator
529
+
512
530
  if (stage === CompanyStage.PreLaunch) {
513
531
  const achievedGoals = goalMetrics.filter((m) => m.goal.status === 'achieved');
514
532
 
515
533
  if (achievedGoals.length > 0) {
534
+ const goalTitle = achievedGoals[0].goal.title.toLowerCase();
516
535
  const topLearning = learnings.length > 0 ? cleanLearningText(learnings[0]) : '';
517
- // Only include learning if it's market/customer focused
518
536
  const learningClause = topLearning && !topLearning.toLowerCase().includes('data file') && !topLearning.toLowerCase().includes('shipped feature')
519
537
  ? ` Key insight: ${topLearning.split('.')[0]}.`
520
538
  : '';
521
539
 
522
- return `Building toward beta launch. This month we ${achievedGoals[0].goal.title.toLowerCase()} and shipped ${commitCount} commits across the core platform.${learningClause}`;
540
+ // Lead with market opportunity, then traction
541
+ return `VibeBusiness is building the first autonomous AI product manager for the ${sam} indie hacker market. Our unique ${topDifferentiator} approach sets us apart. This month we ${goalTitle}, achieving ${epicAccomplishments.length} strategic milestone${epicAccomplishments.length !== 1 ? 's' : ''} with ${commitCount} commits shipped.${learningClause} On track for 20 beta users by Q2 to validate our 10x activation moment.`;
523
542
  }
524
543
 
525
544
  if (epicAccomplishments.length > 0) {
526
- return `Building toward beta launch. This month: ${commitCount} commits shipped, ${epicAccomplishments.length} major feature${epicAccomplishments.length > 1 ? 's' : ''} completed. Learning velocity is high—pivoting quickly based on founder feedback.`;
545
+ return `VibeBusiness is building the first autonomous AI product manager for the ${sam} indie hacker market. This month: ${commitCount} commits shipped, ${epicAccomplishments.length} major feature${epicAccomplishments.length > 1 ? 's' : ''} completed. On track for 20 beta users by Q2 to prove PMF velocity.`;
527
546
  }
528
547
 
529
- return `Building toward beta launch. This month: ${commitCount} commits shipped across the core platform. Focus on foundation and activation improvements.`;
548
+ // Fallback without achieved goals
549
+ return `Building toward beta launch in Q2. We're targeting the ${sam} indie hacker market with a unique ${topDifferentiator} approach. This month: ${commitCount} commits across core platform and activation improvements. Next milestone: 20 beta users to prove PMF velocity.`;
530
550
  }
531
551
 
532
552
  if (stage === CompanyStage.EarlyTraction) {
@@ -812,6 +832,73 @@ function generateMarkdown(data: {
812
832
  }
813
833
  }
814
834
 
835
+ // ─── Investment Thesis ───────────────────────────────────────────────────
836
+
837
+ md += `## 💼 Investment Thesis\n\n`;
838
+
839
+ // Load positioning data
840
+ const marketContext = positioning.current;
841
+
842
+ md += `### Market Opportunity\n`;
843
+ md += `- **TAM:** $80B+ across AI coding tools, agentic AI, and vertical AI for business\n`;
844
+ md += `- **SAM:** $1.8-6B (5-10M software entrepreneurs at $30-50/month)\n`;
845
+ md += `- **Beachhead:** Indie Hackers / Solo Technical Founders (CLI-native, $20-100/mo budgets)\n\n`;
846
+
847
+ md += `### Competitive Moat\n`;
848
+ for (const diff of marketContext.differentiators.slice(0, 4)) {
849
+ const [title, description] = diff.includes(':') ? diff.split(':').map(s => s.trim()) : [diff, ''];
850
+ if (description) {
851
+ md += `- **${title}** — ${description}\n`;
852
+ } else {
853
+ md += `- ${title}\n`;
854
+ }
855
+ }
856
+ md += `\n`;
857
+
858
+ md += `### Why Now / Competitive Window\n`;
859
+ md += `12-18 months before Microsoft/GitHub could replicate full lifecycle approach. Claude Code CLI improves monthly — our implementation quality improves for free.\n\n`;
860
+
861
+ md += `### Traction Milestones\n`;
862
+ const npmVersion = goalMetrics.find(m => m.goal.kpis.some(kpi => kpi.name.includes('npm') && kpi.name.includes('Version')));
863
+ const betaUsers = goalMetrics.find(m => m.goal.kpis.some(kpi => kpi.name.includes('Beta User')));
864
+ const payingUsers = goalMetrics.find(m => m.goal.kpis.some(kpi => kpi.name.includes('Paying Users')));
865
+
866
+ if (npmVersion) {
867
+ const versionKpi = npmVersion.goal.kpis.find(kpi => kpi.name.includes('Version'));
868
+ if (versionKpi) md += `- ✅ Public npm launch (v${versionKpi.current_value})\n`;
869
+ }
870
+ if (betaUsers) {
871
+ const betaKpi = betaUsers.goal.kpis.find(kpi => kpi.name.includes('Beta User'));
872
+ if (betaKpi) md += `- 🎯 Beta users: ${betaKpi.current_value}/${betaKpi.target_value} (targeting Q2)\n`;
873
+ }
874
+ if (payingUsers) {
875
+ const payingKpi = payingUsers.goal.kpis.find(kpi => kpi.name.includes('Paying Users'));
876
+ if (payingKpi) md += `- 🎯 Paying customers: ${payingKpi.current_value}/${payingKpi.target_value} (targeting Q3)\n`;
877
+ }
878
+
879
+ // Add unit economics if available
880
+ const unitEconomics = goalMetrics.find(m => m.goal.id === 'goal-unit-economics');
881
+ if (unitEconomics) {
882
+ md += `\n### Unit Economics (Target)\n`;
883
+ const cacKpi = unitEconomics.goal.kpis.find(kpi => kpi.id === 'kpi-cac');
884
+ const ltvKpi = unitEconomics.goal.kpis.find(kpi => kpi.id === 'kpi-ltv');
885
+ const marginKpi = unitEconomics.goal.kpis.find(kpi => kpi.id === 'kpi-gross-margin');
886
+
887
+ if (cacKpi && ltvKpi) {
888
+ const ltvNum = typeof ltvKpi.target_value === 'number' ? ltvKpi.target_value : null;
889
+ const cacNum = typeof cacKpi.target_value === 'number' ? cacKpi.target_value : null;
890
+ const ratio = (ltvNum && cacNum) ? (ltvNum / cacNum).toFixed(1) : 'N/A';
891
+ md += `- **CAC:** $${cacKpi.target_value} (target)\n`;
892
+ md += `- **LTV:** $${ltvKpi.target_value} (target)\n`;
893
+ md += `- **LTV:CAC Ratio:** ${ratio}:1 (target >3:1 for SaaS)\n`;
894
+ }
895
+ if (marginKpi) {
896
+ md += `- **Gross Margin:** ${marginKpi.target_value}% (BYOK = near-zero COGS)\n`;
897
+ }
898
+ }
899
+
900
+ md += `\n---\n\n`;
901
+
815
902
  // ─── Momentum Indicators ─────────────────────────────────────────────────
816
903
 
817
904
  md += `## 📊 Momentum Indicators\n\n`;
@@ -821,6 +908,26 @@ function generateMarkdown(data: {
821
908
  md += `- **Features Shipped:** ${epicAccomplishments.reduce((sum, e) => sum + e.ideas_shipped, 0)} total across ${epicAccomplishments.length} epic${epicAccomplishments.length > 1 ? 's' : ''}\n`;
822
909
  }
823
910
 
911
+ // Show sparklines for top KPIs with history
912
+ const kpisWithHistory = goalMetrics
913
+ .filter(m => m.goal.kpis[0].history.length > 1)
914
+ .slice(0, 5); // Show top 5
915
+
916
+ if (kpisWithHistory.length > 0) {
917
+ md += `\n**Key Metrics Trends:**\n`;
918
+ for (const metric of kpisWithHistory) {
919
+ const kpi = metric.goal.kpis[0];
920
+ const sparkline = generateAsciiSparkline(kpi.history);
921
+ if (sparkline) {
922
+ const currentVal = typeof kpi.current_value === 'number'
923
+ ? kpi.current_value.toFixed(0)
924
+ : kpi.current_value;
925
+ md += `- **${kpi.name}:** ${sparkline} ${currentVal} ${kpi.unit}\n`;
926
+ }
927
+ }
928
+ md += `\n`;
929
+ }
930
+
824
931
  if (goalMetrics.length > 0) {
825
932
  const avgGrowth = goalMetrics
826
933
  .map((m) => parseFloat(m.growth_pct.replace(/[+%]/g, '')))
@@ -843,6 +950,132 @@ function generateMarkdown(data: {
843
950
  return md;
844
951
  }
845
952
 
953
+ // ─── ASCII Sparkline Generation ──────────────────────────────────────────────
954
+
955
+ /**
956
+ * Generate ASCII sparkline chart for a series of values
957
+ */
958
+ function generateAsciiSparkline(history: Array<{ date: string; value: number | string }>): string {
959
+ if (history.length === 0) return '';
960
+
961
+ // Convert values to numbers, filter out non-numeric
962
+ const numericValues = history
963
+ .map(h => typeof h.value === 'number' ? h.value : parseFloat(String(h.value)))
964
+ .filter(v => !isNaN(v) && isFinite(v));
965
+
966
+ if (numericValues.length < 2) return ''; // Need at least 2 points for a trend
967
+
968
+ const max = Math.max(...numericValues);
969
+ const min = Math.min(...numericValues);
970
+ const range = max - min || 1;
971
+
972
+ const bars = '▁▂▃▄▅▆▇█';
973
+
974
+ return numericValues.map(v => {
975
+ const normalized = (v - min) / range;
976
+ const barIndex = Math.min(Math.floor(normalized * 8), 7);
977
+ return bars[barIndex];
978
+ }).join('');
979
+ }
980
+
981
+ // ─── Live Data Fetching & KPI Updates ────────────────────────────────────────
982
+
983
+ interface LiveData {
984
+ npm?: NpmStats;
985
+ github?: GitHubStats;
986
+ }
987
+
988
+ /**
989
+ * Fetch live data from external sources (npm, GitHub, etc.)
990
+ */
991
+ async function fetchLiveData(repoPath: string, packageName: string = 'vibebusiness'): Promise<LiveData> {
992
+ console.log('📡 Fetching live metrics from npm and GitHub...\n');
993
+
994
+ const [npmResult, githubResult] = await Promise.allSettled([
995
+ fetchNpmStats(packageName),
996
+ fetchGitHubStats(repoPath),
997
+ ]);
998
+
999
+ const data: LiveData = {};
1000
+
1001
+ if (npmResult.status === 'fulfilled') {
1002
+ data.npm = npmResult.value;
1003
+ console.log(` ✓ npm version: ${npmResult.value.version}`);
1004
+ } else {
1005
+ console.warn(` ✗ npm fetch failed: ${npmResult.reason}`);
1006
+ }
1007
+
1008
+ if (githubResult.status === 'fulfilled') {
1009
+ data.github = githubResult.value;
1010
+ console.log(` ✓ GitHub stars: ${githubResult.value.stars}`);
1011
+ } else {
1012
+ console.warn(` ✗ GitHub fetch failed: ${githubResult.reason}`);
1013
+ }
1014
+
1015
+ console.log('');
1016
+ return data;
1017
+ }
1018
+
1019
+ /**
1020
+ * Update KPI values in goals.json with live data
1021
+ */
1022
+ function updateKPIsWithLiveData(goalsFilePath: string, liveData: LiveData): void {
1023
+ const goalsStore = readJsonSafe<{ goals: BusinessGoal[] }>(goalsFilePath, { goals: [] });
1024
+ let updated = false;
1025
+
1026
+ for (const goal of goalsStore.goals) {
1027
+ for (const kpi of goal.kpis) {
1028
+ const today = formatDate(new Date());
1029
+
1030
+ // Update npm-related KPIs
1031
+ if (kpi.source === 'npm' && liveData.npm) {
1032
+ if (kpi.id === 'kpi-npm-version' || kpi.name.includes('npm') && kpi.name.includes('Version')) {
1033
+ const newVersion = liveData.npm.version;
1034
+ if (kpi.current_value !== newVersion) {
1035
+ kpi.current_value = newVersion;
1036
+ // Add to history if not already present for today
1037
+ if (!kpi.history.find(h => h.date === today)) {
1038
+ kpi.history.push({ date: today, value: newVersion as any });
1039
+ }
1040
+ updated = true;
1041
+ }
1042
+ } else if (kpi.id === 'kpi-npm-downloads' || kpi.name.includes('npm') && kpi.name.includes('Downloads')) {
1043
+ const newDownloads = liveData.npm.weeklyDownloads;
1044
+ if (kpi.current_value !== newDownloads) {
1045
+ kpi.current_value = newDownloads;
1046
+ if (!kpi.history.find(h => h.date === today)) {
1047
+ kpi.history.push({ date: today, value: newDownloads });
1048
+ }
1049
+ updated = true;
1050
+ }
1051
+ }
1052
+ }
1053
+
1054
+ // Update GitHub-related KPIs (if we add them in the future)
1055
+ if (kpi.source === 'github' && liveData.github) {
1056
+ if (kpi.name.includes('Stars')) {
1057
+ const newStars = liveData.github.stars;
1058
+ if (kpi.current_value !== newStars) {
1059
+ kpi.current_value = newStars;
1060
+ if (!kpi.history.find(h => h.date === today)) {
1061
+ kpi.history.push({ date: today, value: newStars });
1062
+ }
1063
+ updated = true;
1064
+ }
1065
+ }
1066
+ }
1067
+ }
1068
+ }
1069
+
1070
+ // Write updated goals back to file
1071
+ if (updated) {
1072
+ fs.writeFileSync(goalsFilePath, JSON.stringify({ goals: goalsStore.goals }, null, 2) + '\n');
1073
+ console.log('✅ Updated goals.json with live data\n');
1074
+ } else {
1075
+ console.log('ℹ️ No KPI updates needed\n');
1076
+ }
1077
+ }
1078
+
846
1079
  // ─── Main ────────────────────────────────────────────────────────────────────
847
1080
 
848
1081
  async function main() {
@@ -871,6 +1104,10 @@ async function main() {
871
1104
  if (hasVibeBusinessData) {
872
1105
  console.log('📊 Using VibeBusiness data sources...\n');
873
1106
 
1107
+ // Fetch live data from external sources and update KPIs
1108
+ const liveData = await fetchLiveData(repo);
1109
+ updateKPIsWithLiveData(goalsFilePath, liveData);
1110
+
874
1111
  epicAccomplishments = getEpicAccomplishments(ideasFilePath, roadmapFilePath, since, until);
875
1112
  goalMetrics = getGoalMetrics(goalsFilePath, since);
876
1113
  roadmapEpics = getRoadmapEpics(roadmapFilePath, ideasFilePath);