vibefast-cli 1.2.1 → 1.3.1

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 (348) hide show
  1. package/README.md +30 -95
  2. package/dist/__tests__/recipes.test.js +94 -91
  3. package/dist/__tests__/recipes.test.js.map +1 -1
  4. package/dist/commands/add.d.ts.map +1 -1
  5. package/dist/commands/add.js +301 -125
  6. package/dist/commands/add.js.map +1 -1
  7. package/dist/commands/checklist.d.ts.map +1 -1
  8. package/dist/commands/checklist.js +85 -44
  9. package/dist/commands/checklist.js.map +1 -1
  10. package/dist/commands/health.d.ts.map +1 -1
  11. package/dist/commands/health.js +13 -4
  12. package/dist/commands/health.js.map +1 -1
  13. package/dist/commands/init.d.ts.map +1 -1
  14. package/dist/commands/init.js +118 -26
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/migrate.d.ts +3 -0
  17. package/dist/commands/migrate.d.ts.map +1 -0
  18. package/dist/commands/migrate.js +202 -0
  19. package/dist/commands/migrate.js.map +1 -0
  20. package/dist/commands/remove.d.ts.map +1 -1
  21. package/dist/commands/remove.js +61 -3
  22. package/dist/commands/remove.js.map +1 -1
  23. package/dist/core/auth.d.ts.map +1 -1
  24. package/dist/core/auth.js +20 -18
  25. package/dist/core/auth.js.map +1 -1
  26. package/dist/core/codemod.d.ts +33 -0
  27. package/dist/core/codemod.d.ts.map +1 -1
  28. package/dist/core/codemod.js +116 -0
  29. package/dist/core/codemod.js.map +1 -1
  30. package/dist/core/detect.d.ts.map +1 -1
  31. package/dist/core/detect.js +24 -7
  32. package/dist/core/detect.js.map +1 -1
  33. package/dist/core/journal.d.ts +1 -0
  34. package/dist/core/journal.d.ts.map +1 -1
  35. package/dist/core/journal.js.map +1 -1
  36. package/dist/core/recipes.d.ts.map +1 -1
  37. package/dist/core/recipes.js +25 -7
  38. package/dist/core/recipes.js.map +1 -1
  39. package/dist/index.js +2 -2
  40. package/dist/index.js.map +1 -1
  41. package/docs/architecture.md +50 -0
  42. package/docs/commands.md +78 -0
  43. package/docs/contributing.md +27 -0
  44. package/docs/quickstart.md +50 -0
  45. package/docs/recipes.md +57 -0
  46. package/docs/troubleshooting.md +31 -0
  47. package/package.json +2 -2
  48. package/recipes/0/apps/native/src/components/advanced-ui/timeline/demo.tsx +445 -0
  49. package/recipes/0/apps/native/src/components/advanced-ui/timeline/timeline-view.tsx +355 -0
  50. package/recipes/0/apps/native/src/components/advanced-ui/timeline/types.ts +31 -0
  51. package/recipes/0/recipe.json +18 -0
  52. package/recipes/animated-chip/apps/native/src/components/advanced-ui/chip/demo.tsx +2 -1
  53. package/recipes/animated-chip/recipe.json +5 -2
  54. package/recipes/animated-chip-native@latest.zip +0 -0
  55. package/recipes/animated-chip@latest.zip +0 -0
  56. package/recipes/animated-switch/apps/native/src/components/advanced-ui/switch/demo.tsx +1 -1
  57. package/recipes/animated-switch/recipe.json +5 -2
  58. package/recipes/animated-switch-native@latest.zip +0 -0
  59. package/recipes/animated-switch@latest.zip +0 -0
  60. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
  61. package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -2
  62. package/recipes/audio-recorder/recipe.json +7 -2
  63. package/recipes/audio-recorder-native@latest.zip +0 -0
  64. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
  65. package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -1
  66. package/recipes/audio-recorder-supabase/recipe.json +12 -16
  67. package/recipes/audio-recorder-supabase-native@latest.zip +0 -0
  68. package/recipes/audio-recorder-supabase@latest.zip +0 -0
  69. package/recipes/audio-recorder@latest.zip +0 -0
  70. package/recipes/charts/apps/native/src/app/charts/index.tsx +3 -0
  71. package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -1
  72. package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +3 -1
  73. package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -1
  74. package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +3 -1
  75. package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +3 -1
  76. package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +3 -1
  77. package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +3 -1
  78. package/recipes/charts/recipe.json +13 -4
  79. package/recipes/charts-native@latest.zip +0 -0
  80. package/recipes/charts@latest.zip +0 -0
  81. package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
  82. package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +4 -4
  83. package/recipes/chatbot/recipe.json +3 -40
  84. package/recipes/chatbot-native@latest.zip +0 -0
  85. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +4 -1
  86. package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
  87. package/recipes/chatbot-supabase/recipe.json +3 -42
  88. package/recipes/chatbot-supabase-native@latest.zip +0 -0
  89. package/recipes/chatbot-supabase@latest.zip +0 -0
  90. package/recipes/chatbot@latest.zip +0 -0
  91. package/recipes/glowing-button/recipe.json +6 -2
  92. package/recipes/glowing-button-native@latest.zip +0 -0
  93. package/recipes/glowing-button@latest.zip +0 -0
  94. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
  95. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
  96. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
  97. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/index.tsx +50 -0
  98. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
  99. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/results.tsx +2 -0
  100. package/recipes/image-analysis/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
  101. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +2 -2
  102. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/camera.tsx +72 -65
  103. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +65 -47
  104. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading-screen.tsx +43 -2
  105. package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading.tsx +34 -1
  106. package/recipes/image-analysis/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +83 -2
  107. package/recipes/image-analysis/recipe.json +11 -19
  108. package/recipes/image-analysis-native@latest.zip +0 -0
  109. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
  110. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
  111. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
  112. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/index.tsx +50 -0
  113. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
  114. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/results.tsx +2 -0
  115. package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
  116. package/recipes/image-analysis-supabase/recipe.json +10 -37
  117. package/recipes/image-analysis-supabase-native@latest.zip +0 -0
  118. package/recipes/image-analysis-supabase@latest.zip +0 -0
  119. package/recipes/image-analysis@latest.zip +0 -0
  120. package/recipes/image-analyzer/apps/native/src/app/(root)/(protected)/image-analyzer/index.tsx +2 -0
  121. package/recipes/image-generator/apps/native/src/app/image-generator/gallery.tsx +3 -0
  122. package/recipes/image-generator/apps/native/src/app/image-generator/index.tsx +3 -0
  123. package/recipes/image-generator/recipe.json +8 -18
  124. package/recipes/image-generator-native@latest.zip +0 -0
  125. package/recipes/image-generator-supabase/recipe.json +6 -35
  126. package/recipes/image-generator-supabase-native@latest.zip +0 -0
  127. package/recipes/image-generator-supabase@latest.zip +0 -0
  128. package/recipes/image-generator@latest.zip +0 -0
  129. package/recipes/ios-widget/recipe.json +18 -119
  130. package/recipes/ios-widget-native@latest.zip +0 -0
  131. package/recipes/ios-widget@latest.zip +0 -0
  132. package/recipes/number-stepper/apps/native/src/components/advanced-ui/stepper/demo.tsx +1 -1
  133. package/recipes/number-stepper/recipe.json +5 -2
  134. package/recipes/number-stepper-native@latest.zip +0 -0
  135. package/recipes/number-stepper@latest.zip +0 -0
  136. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +11 -18
  137. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +5 -7
  138. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +9 -7
  139. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +8 -7
  140. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +6 -5
  141. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +4 -3
  142. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +6 -5
  143. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +5 -7
  144. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +7 -6
  145. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +5 -7
  146. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +8 -7
  147. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +6 -5
  148. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +5 -6
  149. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +5 -4
  150. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +5 -7
  151. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +7 -6
  152. package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +4 -3
  153. package/recipes/onboarding/recipe.json +9 -6
  154. package/recipes/onboarding-native@latest.zip +0 -0
  155. package/recipes/onboarding@latest.zip +0 -0
  156. package/recipes/payments/apps/native/src/app/paywall/index.tsx +74 -0
  157. package/recipes/payments/apps/native/src/app/paywall/local.tsx +25 -0
  158. package/recipes/payments/apps/native/src/app/paywall/remote.tsx +23 -0
  159. package/recipes/payments/packages/backend/convex/payments.ts +21 -3
  160. package/recipes/payments/recipe.json +14 -34
  161. package/recipes/payments-native@latest.zip +0 -0
  162. package/recipes/payments-supabase/apps/native/src/app/paywall/index.tsx +74 -0
  163. package/recipes/payments-supabase/apps/native/src/app/paywall/local.tsx +25 -0
  164. package/recipes/payments-supabase/apps/native/src/app/paywall/remote.tsx +23 -0
  165. package/recipes/payments-supabase/recipe.json +16 -23
  166. package/recipes/payments-supabase-native@latest.zip +0 -0
  167. package/recipes/payments-supabase@latest.zip +0 -0
  168. package/recipes/payments@latest.zip +0 -0
  169. package/recipes/posthog/apps/native/src/components/analytics/navigation-tracker.tsx +14 -0
  170. package/recipes/posthog/apps/native/src/lib/hooks/use-navigation-analytics.ts +44 -0
  171. package/recipes/posthog/apps/native/src/providers/posthog-provider.tsx +51 -0
  172. package/recipes/posthog/recipe.json +60 -0
  173. package/recipes/posthog-native@latest.zip +0 -0
  174. package/recipes/progress-circle/apps/native/src/components/advanced-ui/progress-bars/progress-circle-page.tsx +1 -1
  175. package/recipes/progress-circle/recipe.json +5 -2
  176. package/recipes/progress-circle-native@latest.zip +0 -0
  177. package/recipes/progress-circle@latest.zip +0 -0
  178. package/recipes/quiz/apps/native/src/app/quiz/index.tsx +47 -0
  179. package/recipes/quiz/recipe.json +9 -6
  180. package/recipes/quiz-native@latest.zip +0 -0
  181. package/recipes/quiz@latest.zip +0 -0
  182. package/recipes/screen-kits/apps/native/src/app/screen-kits/_layout.tsx +12 -0
  183. package/recipes/screen-kits/apps/native/src/app/screen-kits/index.tsx +114 -0
  184. package/recipes/screen-kits/apps/native/src/features/screen-kits/index.ts +1 -0
  185. package/recipes/screen-kits/apps/native/src/features/screen-kits/types.ts +28 -0
  186. package/recipes/screen-kits/recipe.json +26 -0
  187. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/_layout.tsx +12 -0
  188. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/home.tsx +5 -0
  189. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/index.tsx +5 -0
  190. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-complete.tsx +5 -0
  191. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-fail.tsx +5 -0
  192. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson.tsx +5 -0
  193. package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/skill-tree.tsx +5 -0
  194. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/duo-button.tsx +174 -0
  195. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/skill-button.tsx +186 -0
  196. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/xp-header.tsx +115 -0
  197. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/constants.ts +89 -0
  198. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/index.ts +3 -0
  199. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/home-screen.tsx +225 -0
  200. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-complete-screen.tsx +485 -0
  201. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-fail-screen.tsx +105 -0
  202. package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-screen.tsx +384 -0
  203. package/recipes/screen-kits-duolingo/recipe.json +58 -0
  204. package/recipes/screen-kits-duolingo-native@latest.zip +0 -0
  205. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/_layout.tsx +45 -0
  206. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/asset-detail.tsx +3 -0
  207. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/notifications.tsx +3 -0
  208. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/receive.tsx +3 -0
  209. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/send.tsx +3 -0
  210. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/swap.tsx +3 -0
  211. package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/wallet.tsx +3 -0
  212. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/ActionButtons.tsx +78 -0
  213. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/AssetRow.tsx +94 -0
  214. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/BalanceCard.tsx +118 -0
  215. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/constants.ts +85 -0
  216. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/asset-detail.tsx +378 -0
  217. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/notifications.tsx +210 -0
  218. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/receive-modal.tsx +317 -0
  219. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/send-modal.tsx +420 -0
  220. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/swap-modal.tsx +363 -0
  221. package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/wallet-dashboard.tsx +281 -0
  222. package/recipes/screen-kits-finance/recipe.json +46 -0
  223. package/recipes/screen-kits-finance-native@latest.zip +0 -0
  224. package/recipes/screen-kits-fitness/apps/native/assets/sounds/timer-beep.wav +0 -0
  225. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/_layout.tsx +10 -0
  226. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/index.tsx +6 -0
  227. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/timer.tsx +3 -0
  228. package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/workout.tsx +3 -0
  229. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-components.tsx +500 -0
  230. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-settings-modal.tsx +352 -0
  231. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/workout-card.tsx +105 -0
  232. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/constants.ts +189 -0
  233. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/hooks/use-timer.ts +307 -0
  234. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/index.ts +1 -0
  235. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/timer-screen.tsx +278 -0
  236. package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/workout-dashboard.tsx +350 -0
  237. package/recipes/screen-kits-fitness/recipe.json +63 -0
  238. package/recipes/screen-kits-fitness-native@latest.zip +0 -0
  239. package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/habits.tsx +1 -0
  240. package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/kanban.tsx +1 -0
  241. package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/routes.ts +4 -0
  242. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/AddTaskModal.tsx +246 -0
  243. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/DraggableTaskCard.tsx +92 -0
  244. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/KanbanColumn.tsx +238 -0
  245. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/TaskCard.tsx +144 -0
  246. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/add-habit-modal.tsx +271 -0
  247. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/constants.ts +295 -0
  248. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/kanban-utils.ts +62 -0
  249. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/habit-tracker.tsx +1160 -0
  250. package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/kanban-board.tsx +432 -0
  251. package/recipes/screen-kits-habits/recipe.json +52 -0
  252. package/recipes/screen-kits-habits-native@latest.zip +0 -0
  253. package/recipes/screen-kits-native@latest.zip +0 -0
  254. package/recipes/sentry/apps/native/src/providers/sentry-provider.tsx +64 -0
  255. package/recipes/sentry/recipe.json +39 -0
  256. package/recipes/sentry-native@latest.zip +0 -0
  257. package/recipes/swipe-slider/apps/native/src/components/advanced-ui/sliders/swipe-slider-page.tsx +1 -1
  258. package/recipes/swipe-slider/recipe.json +5 -2
  259. package/recipes/swipe-slider-native@latest.zip +0 -0
  260. package/recipes/swipe-slider@latest.zip +0 -0
  261. package/recipes/timeline/apps/native/src/components/advanced-ui/timeline/demo.tsx +2 -1
  262. package/recipes/timeline/recipe.json +5 -2
  263. package/recipes/timeline-native@latest.zip +0 -0
  264. package/recipes/timeline@latest.zip +0 -0
  265. package/recipes/tracker-app/apps/native/src/app/tracker-app/index.tsx +1 -0
  266. package/recipes/tracker-app/recipe.json +10 -7
  267. package/recipes/tracker-app-native@latest.zip +0 -0
  268. package/recipes/tracker-app@latest.zip +0 -0
  269. package/recipes/upload-all.sh +8 -31
  270. package/recipes/voice-bot/apps/native/src/app/voice-bot/index.tsx +56 -0
  271. package/recipes/voice-bot/recipe.json +31 -7
  272. package/recipes/voice-bot-native@latest.zip +0 -0
  273. package/recipes/voice-bot@latest.zip +0 -0
  274. package/recipes/wake-word/apps/native/src/app/{(root)/(protected)/test-wake-word.tsx → test-wake-word.tsx} +43 -4
  275. package/recipes/wake-word/recipe.json +16 -26
  276. package/recipes/wake-word-native@latest.zip +0 -0
  277. package/recipes/wake-word@latest.zip +0 -0
  278. package/scripts/create-advanced-ui-recipes.sh +46 -19
  279. package/scripts/create-recipes.mjs +471 -117
  280. package/scripts/package-recipes.mjs +76 -0
  281. package/scripts/publish-all.sh +6 -2
  282. package/CHANGELOG.md +0 -198
  283. package/docs/archive/AUTO-DETECT-DEPS.md +0 -607
  284. package/docs/archive/FINAL-PACKAGE-STRATEGY.md +0 -583
  285. package/docs/archive/FINAL-SIMPLE-PLAN.md +0 -487
  286. package/docs/archive/FINAL-STATUS.md +0 -144
  287. package/docs/archive/FLOW-DIAGRAM.md +0 -1629
  288. package/docs/archive/GOTCHAS-AND-RISKS.md +0 -801
  289. package/docs/archive/IMPLEMENTATION-PLAN.md +0 -1360
  290. package/docs/archive/PLAN.md +0 -453
  291. package/docs/archive/PRODUCTION-READINESS.md +0 -684
  292. package/docs/archive/PRODUCTION-TEST-RESULTS.md +0 -465
  293. package/docs/archive/SIMPLIFIED-PLAN.md +0 -578
  294. package/docs/archive/STATUS.md +0 -199
  295. package/docs/archive/SUCCESS.md +0 -259
  296. package/docs/archive/TEST-SUMMARY.md +0 -261
  297. package/docs/archive/TESTING-CHECKLIST.md +0 -450
  298. package/docs/archive/USER-MODIFICATIONS.md +0 -448
  299. package/docs/decisions.md +0 -55
  300. package/docs/manual-testing.md +0 -91
  301. package/docs/next-steps.md +0 -12
  302. package/recipes/README.md +0 -156
  303. package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +0 -369
  304. package/recipes/chatbot/apps/native/src/api-client/chatbot.ts +0 -83
  305. package/recipes/chatbot/packages/backend/convex/agents.ts +0 -115
  306. package/recipes/chatbot/packages/backend/convex/tools/index.ts +0 -18
  307. package/recipes/chatbot/packages/backend/convex/tools/knowledgeRetrieval.ts +0 -97
  308. package/recipes/chatbot/packages/backend/convex/tools/tavilySearch.ts +0 -83
  309. package/recipes/chatbot/packages/backend/convex/tools/userProfile.ts +0 -72
  310. package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +0 -515
  311. package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +0 -243
  312. package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +0 -327
  313. package/recipes/image-analysis/apps/native/src/api-client/image-analyzer.ts +0 -62
  314. package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +0 -132
  315. package/recipes/image-generator/apps/native/src/api-client/image-generator.ts +0 -34
  316. package/recipes/payments/apps/native/src/api-client/payments.ts +0 -44
  317. package/recipes/payments-supabase/packages/backend/src/services/payments.ts +0 -201
  318. package/recipes/posthog.json +0 -47
  319. package/recipes/revenuecat.json +0 -43
  320. package/recipes/sentry.json +0 -47
  321. package/recipes/wake-word/apps/native/assets/vosk-model/README.md +0 -103
  322. package/recipes/wake-word/apps/native/scripts/download-vosk-model.mjs +0 -127
  323. /package/recipes/{audio-recorder/apps/native/src/app/(root)/(protected) → audio-recorder-supabase/apps/native/src/app}/audio-recorder/index.tsx +0 -0
  324. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/AppIntent.swift +0 -0
  325. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png +0 -0
  326. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png +0 -0
  327. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png +0 -0
  328. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png +0 -0
  329. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png +0 -0
  330. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png +0 -0
  331. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png +0 -0
  332. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png +0 -0
  333. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png +0 -0
  334. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png +0 -0
  335. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png +0 -0
  336. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png +0 -0
  337. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png +0 -0
  338. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png +0 -0
  339. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  340. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png +0 -0
  341. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/CalorieTrackerWidget.swift +0 -0
  342. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/HabitTrackerWidget.swift +0 -0
  343. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Info.plist +0 -0
  344. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/WidgetLiveActivity.swift +0 -0
  345. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/expo-target.config.js +0 -0
  346. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/generated.entitlements +0 -0
  347. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/index.swift +0 -0
  348. /package/recipes/ios-widget/{targets → apps/native/targets}/widget/widgets.swift +0 -0
@@ -1,83 +1,302 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { readdir, stat, mkdir, writeFile, cp } from 'fs/promises';
4
- import { join, dirname } from 'path';
5
- import { fileURLToPath } from 'url';
6
- import { exec } from 'child_process';
7
- import { promisify } from 'util';
3
+ import { readdir, stat, mkdir, writeFile, cp, rm } from "fs/promises";
4
+ import { join, dirname } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { exec } from "child_process";
7
+ import { promisify } from "util";
8
8
 
9
9
  const execAsync = promisify(exec);
10
10
  const __dirname = dirname(fileURLToPath(import.meta.url));
11
11
 
12
+ // Paths to sources
13
+ const PATHS = {
14
+ standard: join(__dirname, "../../vibefast-pro"),
15
+ supabase: join(__dirname, "../../vf-supabase"),
16
+ };
17
+
18
+ const recipesDir = join(__dirname, "../recipes");
19
+
12
20
  // Feature definitions
13
21
  const features = [
22
+ // Standard (Convex) Features
14
23
  {
15
- name: 'charts',
16
- label: 'Charts',
17
- icon: '📊',
18
- description: 'Beautiful data visualization with charts',
19
- color: '#6366F1',
24
+ name: "charts",
25
+ label: "Charts",
26
+ icon: "📊",
27
+ description: "Beautiful data visualization with charts",
28
+ color: "#6366F1",
20
29
  dependencies: {
21
- expo: ['@shopify/react-native-skia', 'react-native-svg'],
30
+ expo: ["@shopify/react-native-skia", "react-native-svg"],
22
31
  },
32
+ source: "standard",
23
33
  },
24
34
  {
25
- name: 'chatbot',
26
- label: 'AI Chatbot',
27
- icon: '💬',
28
- description: 'AI-powered chat assistant',
29
- color: '#F43F5E',
35
+ name: "chatbot",
36
+ label: "AI Chatbot",
37
+ icon: "💬",
38
+ description: "AI-powered chat assistant",
39
+ color: "#F43F5E",
30
40
  dependencies: {
31
41
  expo: [
32
- 'convex',
33
- 'expo-clipboard',
34
- 'markdown-it',
35
- 'react-native-markdown-display',
36
- 'react-syntax-highlighter',
37
- 'react-native-reanimated',
38
- 'react-native-safe-area-context',
42
+ "convex",
43
+ "expo-clipboard",
44
+ "markdown-it",
45
+ "react-native-markdown-display",
46
+ "react-syntax-highlighter",
47
+ "react-native-reanimated",
48
+ "react-native-safe-area-context",
39
49
  ],
40
50
  },
51
+ backendFiles: ["chatbotAgent.ts", "chatbotHistory.ts"],
52
+ source: "standard",
41
53
  },
42
54
  {
43
- name: 'voice-bot',
44
- label: 'Voice Assistant',
45
- icon: '🗣️',
46
- description: 'Real-time voice conversations with AI',
47
- color: '#14B8A6',
55
+ name: "voice-bot",
56
+ label: "Voice Assistant",
57
+ icon: "🗣️",
58
+ description: "Real-time voice conversations with AI",
59
+ color: "#14B8A6",
60
+ dependencies: {
61
+ expo: [
62
+ "@config-plugins/react-native-webrtc",
63
+ "@elevenlabs/react-native",
64
+ "@livekit/react-native",
65
+ "@livekit/react-native-expo-plugin",
66
+ "@livekit/react-native-webrtc",
67
+ "livekit-client",
68
+ ],
69
+ },
70
+ manualSteps: [
71
+ {
72
+ title: "Add LiveKit/WebRTC config plugins",
73
+ description:
74
+ "Register @livekit/react-native-expo-plugin and @config-plugins/react-native-webrtc in app config so native WebRTC is configured.",
75
+ file: "apps/native/app.config.ts",
76
+ },
77
+ {
78
+ title: "Set ElevenLabs Agent ID",
79
+ description:
80
+ "Add ELEVENLABS_AGENT_ID to your .env files so the voice bot can connect.",
81
+ file: "apps/native/.env.local",
82
+ },
83
+ {
84
+ title: "Use a development build",
85
+ description:
86
+ "This feature relies on native modules and will not work in Expo Go. Build a dev client before running.",
87
+ file: "apps/native",
88
+ },
89
+ ],
90
+ source: "standard",
48
91
  },
49
92
  {
50
- name: 'image-generator',
51
- label: 'Image Generator',
52
- icon: '🎨',
53
- description: 'AI-powered image generation',
54
- color: '#A855F7',
93
+ name: "image-generator",
94
+ label: "Image Generator",
95
+ icon: "🎨",
96
+ description: "AI-powered image generation",
97
+ color: "#A855F7",
98
+ backendFolder: "imageGeneration",
99
+ backendFiles: ["imageGenerator.ts"],
100
+ source: "standard",
55
101
  },
56
102
  {
57
- name: 'audio-recorder',
58
- label: 'Voice Notes',
59
- icon: '🎤',
60
- description: 'Record and manage voice notes',
61
- color: '#EF4444',
103
+ name: "audio-recorder",
104
+ label: "Voice Notes",
105
+ icon: "🎤",
106
+ description: "Record and manage voice notes",
107
+ color: "#EF4444",
108
+ dependencies: {
109
+ expo: ["expo-audio"],
110
+ },
111
+ source: "standard",
62
112
  },
63
113
  {
64
- name: 'quiz',
65
- label: 'Quiz',
66
- icon: '📱',
67
- description: 'Interactive quiz feature',
68
- color: '#F97316',
114
+ name: "quiz",
115
+ label: "Quiz",
116
+ icon: "📱",
117
+ description: "Interactive quiz feature",
118
+ color: "#F97316",
119
+ source: "standard",
69
120
  },
70
121
  {
71
- name: 'tracker-app',
72
- label: 'Tracker',
73
- icon: '🍎',
74
- description: 'Track habits and activities',
75
- color: '#06B6D4',
122
+ name: "tracker-app",
123
+ label: "Tracker",
124
+ icon: "🍎",
125
+ description: "Track habits and activities",
126
+ color: "#06B6D4",
127
+ source: "standard",
128
+ },
129
+ {
130
+ name: "onboarding",
131
+ label: "Onboarding",
132
+ icon: "🎯",
133
+ description: "User onboarding flow",
134
+ color: "#84CC16",
135
+ source: "standard",
136
+ },
137
+ {
138
+ name: "wake-word",
139
+ label: "Wake Word",
140
+ icon: "🎤",
141
+ description: "Wake word detection",
142
+ color: "#0EA5E9",
143
+ appEntry: "test-wake-word.tsx",
144
+ navRoute: "/(root)/(protected)/test-wake-word",
145
+ dependencies: {
146
+ expo: ["events", "expo-audio", "react-native-vosk"],
147
+ },
148
+ manualSteps: [
149
+ {
150
+ title: "Add Vosk plugin configuration",
151
+ description:
152
+ "Register the react-native-vosk config plugin with the bundled model path and microphone permission text.",
153
+ file: "apps/native/app.config.ts",
154
+ },
155
+ {
156
+ title: "Download Vosk model",
157
+ description:
158
+ "Download the Vosk model and place it at apps/native/assets/vosk-model/model-en-us (must match the path in app config).",
159
+ file: "apps/native/app.config.ts",
160
+ },
161
+ ],
162
+ source: "standard",
163
+ },
164
+ {
165
+ name: "payments",
166
+ label: "Payments",
167
+ icon: "💳",
168
+ description: "In-app purchases and subscriptions",
169
+ color: "#F59E0B",
170
+ appEntry: "paywall",
171
+ navRoute: "/(root)/(protected)/paywall",
172
+ backendFiles: ["payments.ts"],
173
+ dependencies: {
174
+ expo: ["react-native-purchases", "react-native-purchases-ui"],
175
+ },
176
+ manualSteps: [
177
+ {
178
+ title: "Enable RevenueCat initialization",
179
+ description:
180
+ "Uncomment the PaymentInitializer in root providers so the SDK is initialized on app startup.",
181
+ file: "apps/native/src/providers/root-providers.tsx",
182
+ },
183
+ {
184
+ title: "Set RevenueCat API keys",
185
+ description:
186
+ "Update your .env files with REVENUECAT_API_KEY_APPLE and REVENUECAT_API_KEY_GOOGLE values from RevenueCat.",
187
+ file: "apps/native/.env.local",
188
+ },
189
+ ],
190
+ source: "standard",
191
+ },
192
+ {
193
+ name: "image-analysis",
194
+ folderName: "image-analyzer",
195
+ label: "Image Analysis",
196
+ icon: "🔍",
197
+ description: "AI image analysis",
198
+ color: "#22C55E",
199
+ appEntry: "analysis",
200
+ navRoute: "/(root)/(protected)/analysis/face-analysis",
201
+ backendFolder: "imageAnalysis",
202
+ backendFiles: ["imageAnalysis.ts"],
203
+ source: "standard",
76
204
  },
77
- ];
78
205
 
79
- const monorepoPath = join(__dirname, '../../vibefast-monorepo');
80
- const recipesDir = join(__dirname, '../recipes');
206
+ // Supabase Variants
207
+ {
208
+ name: "chatbot-supabase",
209
+ folderName: "chatbot",
210
+ label: "AI Chatbot (Supabase)",
211
+ icon: "💬",
212
+ description: "AI-powered chat assistant with Supabase",
213
+ color: "#F43F5E",
214
+ source: "supabase",
215
+ suffix: "-supabase",
216
+ dependencies: {
217
+ expo: [
218
+ "expo-clipboard",
219
+ "markdown-it",
220
+ "react-native-markdown-display",
221
+ "react-syntax-highlighter",
222
+ "react-native-reanimated",
223
+ "react-native-safe-area-context",
224
+ ],
225
+ },
226
+ supabaseFunction: "chat-stream",
227
+ supabaseMigration: "chatbot.sql",
228
+ },
229
+ {
230
+ name: "image-generator-supabase",
231
+ folderName: "image-generator",
232
+ label: "Image Generator (Supabase)",
233
+ icon: "🎨",
234
+ description: "AI image generation with Supabase",
235
+ color: "#A855F7",
236
+ source: "supabase",
237
+ suffix: "-supabase",
238
+ supabaseFunction: "generate-image",
239
+ supabaseMigration: "image_generator.sql",
240
+ },
241
+ {
242
+ name: "audio-recorder-supabase",
243
+ folderName: "audio-recorder",
244
+ label: "Voice Notes (Supabase)",
245
+ icon: "🎤",
246
+ description: "Voice notes with Supabase",
247
+ color: "#EF4444",
248
+ source: "supabase",
249
+ suffix: "-supabase",
250
+ dependencies: {
251
+ expo: ["expo-audio"],
252
+ },
253
+ supabaseMigration: "recordings.sql",
254
+ },
255
+ {
256
+ name: "payments-supabase",
257
+ folderName: "payments",
258
+ label: "Payments (Supabase)",
259
+ icon: "💳",
260
+ description: "Payments with Supabase",
261
+ color: "#F59E0B",
262
+ source: "supabase",
263
+ suffix: "-supabase",
264
+ appEntry: "paywall",
265
+ navRoute: "/(root)/(protected)/paywall",
266
+ dependencies: {
267
+ expo: ["react-native-purchases", "react-native-purchases-ui"],
268
+ },
269
+ manualSteps: [
270
+ {
271
+ title: "Enable RevenueCat initialization",
272
+ description:
273
+ "Uncomment the PaymentInitializer in root providers so the SDK is initialized on app startup.",
274
+ file: "apps/native/src/providers/root-providers.tsx",
275
+ },
276
+ {
277
+ title: "Set RevenueCat API keys",
278
+ description:
279
+ "Update your .env files with REVENUECAT_API_KEY_APPLE and REVENUECAT_API_KEY_GOOGLE values from RevenueCat.",
280
+ file: "apps/native/.env.local",
281
+ },
282
+ ],
283
+ supabaseMigration: "payments.sql",
284
+ },
285
+ {
286
+ name: "image-analysis-supabase",
287
+ folderName: "image-analyzer",
288
+ label: "Image Analysis (Supabase)",
289
+ icon: "🔍",
290
+ description: "Image analysis with Supabase",
291
+ color: "#22C55E",
292
+ source: "supabase",
293
+ suffix: "-supabase",
294
+ appEntry: "analysis",
295
+ navRoute: "/(root)/(protected)/analysis/face-analysis",
296
+ supabaseFunction: "analyze-image",
297
+ supabaseMigration: "image_analysis.sql",
298
+ },
299
+ ];
81
300
 
82
301
  async function exists(path) {
83
302
  try {
@@ -90,132 +309,267 @@ async function exists(path) {
90
309
 
91
310
  async function createRecipe(feature) {
92
311
  console.log(`\n📦 Creating recipe for ${feature.name}...`);
93
-
312
+
313
+ const sourcePath = PATHS[feature.source];
314
+ if (!(await exists(sourcePath))) {
315
+ console.warn(` ⚠️ Source path not found: ${sourcePath}`);
316
+ return null;
317
+ }
318
+
94
319
  const recipeDir = join(recipesDir, feature.name);
320
+ if (await exists(recipeDir)) {
321
+ await rm(recipeDir, { recursive: true, force: true });
322
+ }
95
323
  await mkdir(recipeDir, { recursive: true });
96
-
324
+
325
+ const featureFolder =
326
+ feature.folderName || feature.name.replace(feature.suffix || "", "");
327
+ const appEntry = feature.appEntry || featureFolder;
328
+ const navRoute =
329
+ feature.navRoute ||
330
+ `/(root)/(protected)/${appEntry.replace(/\.tsx$/, "")}`;
331
+ const backendFolder = feature.backendFolder || featureFolder;
332
+
97
333
  // Paths to copy
98
- const appPath = join(monorepoPath, 'apps/native/src/app/(root)/(protected)', feature.name);
99
- const featurePath = join(monorepoPath, 'apps/native/src/features', feature.name);
100
-
334
+ const appPath = join(
335
+ sourcePath,
336
+ "apps/native/src/app/(root)/(protected)",
337
+ appEntry
338
+ );
339
+ const featurePath = join(
340
+ sourcePath,
341
+ "apps/native/src/features",
342
+ featureFolder
343
+ );
344
+
101
345
  const copySpecs = [];
102
-
103
- // Check if app route exists
346
+
347
+ // 1. App route
104
348
  if (await exists(appPath)) {
105
- const destAppPath = join(recipeDir, 'apps/native/src/app', feature.name);
349
+ const destAppPath = join(recipeDir, "apps/native/src/app", appEntry);
106
350
  await mkdir(dirname(destAppPath), { recursive: true });
107
- await cp(appPath, destAppPath, { recursive: true });
351
+ const appStat = await stat(appPath);
352
+ if (appStat.isDirectory()) {
353
+ await cp(appPath, destAppPath, { recursive: true });
354
+ } else {
355
+ await cp(appPath, destAppPath);
356
+ }
108
357
  copySpecs.push({
109
- from: `apps/native/src/app/${feature.name}`,
110
- to: `apps/native/src/app/(root)/(protected)/${feature.name}`,
358
+ from: `apps/native/src/app/${appEntry}`,
359
+ to: `apps/native/src/app/(root)/(protected)/${appEntry}`,
111
360
  });
112
361
  console.log(` ✓ Copied app route`);
113
362
  }
114
363
 
115
- // Check if feature components exist
364
+ // 2. Feature components
116
365
  if (await exists(featurePath)) {
117
- const destFeaturePath = join(recipeDir, 'apps/native/src/features', feature.name);
366
+ const destFeaturePath = join(
367
+ recipeDir,
368
+ "apps/native/src/features",
369
+ featureFolder
370
+ );
118
371
  await mkdir(dirname(destFeaturePath), { recursive: true });
119
372
  await cp(featurePath, destFeaturePath, { recursive: true });
120
373
  copySpecs.push({
121
- from: `apps/native/src/features/${feature.name}`,
122
- to: `apps/native/src/features/${feature.name}`,
374
+ from: `apps/native/src/features/${featureFolder}`,
375
+ to: `apps/native/src/features/${featureFolder}`,
123
376
  });
124
377
  console.log(` ✓ Copied feature components`);
125
378
  }
126
-
127
- // Check if Convex backend exists for this feature
128
- const convexPath = join(monorepoPath, 'packages/backend/convex', feature.name);
129
- if (await exists(convexPath)) {
130
- const destConvexPath = join(recipeDir, 'packages/backend/convex', feature.name);
131
- await mkdir(dirname(destConvexPath), { recursive: true });
132
- await cp(convexPath, destConvexPath, { recursive: true });
133
- copySpecs.push({
134
- from: `packages/backend/convex/${feature.name}`,
135
- to: `packages/backend/convex/${feature.name}`,
136
- });
137
- console.log(` ✓ Copied Convex backend`);
379
+
380
+ // 3. Backend
381
+ if (feature.source === "standard") {
382
+ // Convex
383
+ const convexPath = join(
384
+ sourcePath,
385
+ "packages/backend/convex",
386
+ backendFolder
387
+ );
388
+ if (await exists(convexPath)) {
389
+ const destConvexPath = join(
390
+ recipeDir,
391
+ "packages/backend/convex",
392
+ backendFolder
393
+ );
394
+ await mkdir(dirname(destConvexPath), { recursive: true });
395
+ await cp(convexPath, destConvexPath, { recursive: true });
396
+ copySpecs.push({
397
+ from: `packages/backend/convex/${backendFolder}`,
398
+ to: `packages/backend/convex/${backendFolder}`,
399
+ });
400
+ console.log(` ✓ Copied Convex backend`);
401
+ }
402
+
403
+ if (feature.backendFiles?.length) {
404
+ for (const fileName of feature.backendFiles) {
405
+ const fileSource = join(sourcePath, "packages/backend/convex", fileName);
406
+ if (await exists(fileSource)) {
407
+ const destFile = join(recipeDir, "packages/backend/convex", fileName);
408
+ await mkdir(dirname(destFile), { recursive: true });
409
+ await cp(fileSource, destFile);
410
+ copySpecs.push({
411
+ from: `packages/backend/convex/${fileName}`,
412
+ to: `packages/backend/convex/${fileName}`,
413
+ });
414
+ console.log(` ✓ Copied Convex file: ${fileName}`);
415
+ } else {
416
+ console.warn(` ⚠️ Convex file not found: ${fileName}`);
417
+ }
418
+ }
419
+ }
420
+ } else if (feature.source === "supabase") {
421
+ // Supabase
422
+
423
+ // Functions
424
+ if (feature.supabaseFunction) {
425
+ const funcName = feature.supabaseFunction;
426
+ const funcSource = join(
427
+ sourcePath,
428
+ "packages/backend/supabase/functions",
429
+ funcName
430
+ );
431
+ if (await exists(funcSource)) {
432
+ const destFunc = join(
433
+ recipeDir,
434
+ "packages/backend/supabase/functions",
435
+ funcName
436
+ );
437
+ await mkdir(dirname(destFunc), { recursive: true });
438
+ await cp(funcSource, destFunc, { recursive: true });
439
+ copySpecs.push({
440
+ from: `packages/backend/supabase/functions/${funcName}`,
441
+ to: `packages/backend/supabase/functions/${funcName}`,
442
+ });
443
+ console.log(` ✓ Copied Supabase function: ${funcName}`);
444
+ } else {
445
+ console.warn(` ⚠️ Supabase function not found: ${funcName}`);
446
+ }
447
+ }
448
+
449
+ // Migrations
450
+ if (feature.supabaseMigration) {
451
+ const migName = feature.supabaseMigration;
452
+ // Look in feature-migrations
453
+ const migSource = join(
454
+ sourcePath,
455
+ "packages/backend/supabase/feature-migrations",
456
+ migName
457
+ );
458
+ if (await exists(migSource)) {
459
+ // Copy to standard migrations folder in recipe?
460
+ // Or keep feature-migrations?
461
+ // Standard recipes usually have "migrations/xxx.sql".
462
+ // We will copy to packages/backend/supabase/migrations/xxx.sql for easier consumption
463
+ const destMig = join(
464
+ recipeDir,
465
+ "packages/backend/supabase/migrations",
466
+ migName
467
+ );
468
+ await mkdir(dirname(destMig), { recursive: true });
469
+ await cp(migSource, destMig);
470
+ copySpecs.push({
471
+ from: `packages/backend/supabase/migrations/${migName}`,
472
+ to: `packages/backend/supabase/migrations/${migName}`,
473
+ });
474
+ console.log(` ✓ Copied Supabase migration: ${migName}`);
475
+ } else {
476
+ console.warn(` ⚠️ Supabase migration not found: ${migName}`);
477
+ }
478
+ }
479
+ }
480
+
481
+ // 4. Extra copies (assets/config)
482
+ if (feature.extraCopies?.length) {
483
+ for (const extra of feature.extraCopies) {
484
+ const srcExtra = join(sourcePath, extra.from);
485
+ if (!(await exists(srcExtra))) {
486
+ console.warn(` ⚠️ Extra copy source missing: ${extra.from}`);
487
+ continue;
488
+ }
489
+ const destExtra = join(recipeDir, extra.from);
490
+ await mkdir(dirname(destExtra), { recursive: true });
491
+ await cp(srcExtra, destExtra, { recursive: true });
492
+ copySpecs.push({
493
+ from: extra.from,
494
+ to: extra.to || extra.from,
495
+ });
496
+ console.log(` ✓ Copied extra: ${extra.from}`);
497
+ }
138
498
  }
139
-
499
+
140
500
  if (copySpecs.length === 0) {
141
501
  console.log(` ⚠️ No files found for ${feature.name}, skipping...`);
142
502
  return null;
143
503
  }
144
-
504
+
145
505
  // Create recipe.json
146
506
  const manifest = {
147
507
  name: feature.name,
148
- version: '1.0.0',
508
+ version: "1.0.0",
149
509
  description: feature.description,
150
510
  copy: copySpecs,
151
511
  nav: {
152
- href: `/(root)/(protected)/${feature.name}`,
512
+ href: navRoute,
153
513
  label: feature.label,
154
514
  icon: feature.icon,
155
515
  color: feature.color,
156
516
  },
157
- target: 'native',
517
+ target: "native",
158
518
  };
159
-
519
+
160
520
  // Add dependencies if defined
161
521
  if (feature.dependencies) {
162
522
  manifest.dependencies = feature.dependencies;
163
523
  }
164
-
524
+
525
+ if (feature.manualSteps) {
526
+ manifest.manualSteps = feature.manualSteps;
527
+ }
528
+
165
529
  await writeFile(
166
- join(recipeDir, 'recipe.json'),
530
+ join(recipeDir, "recipe.json"),
167
531
  JSON.stringify(manifest, null, 2)
168
532
  );
169
533
  console.log(` ✓ Created recipe.json`);
170
-
534
+
171
535
  // Create zip
172
- const zipName = `${feature.name}@latest.zip`;
536
+ const zipName = `${feature.name}-${manifest.target}@latest.zip`;
173
537
  const zipPath = join(recipesDir, zipName);
174
-
538
+
175
539
  await execAsync(`cd "${recipeDir}" && zip -r "../${zipName}" .`);
176
540
  console.log(` ✓ Created ${zipName}`);
177
-
178
- return zipPath;
541
+
542
+ return zipName;
179
543
  }
180
544
 
181
545
  async function main() {
182
- console.log('🚀 VibeFast Recipe Generator\n');
183
- console.log(`Monorepo: ${monorepoPath}`);
546
+ console.log("🚀 VibeFast Recipe Generator (Pro + Supabase)\n");
547
+ console.log(`Standard Source: ${PATHS.standard}`);
548
+ console.log(`Supabase Source: ${PATHS.supabase}`);
184
549
  console.log(`Output: ${recipesDir}\n`);
185
-
550
+
186
551
  await mkdir(recipesDir, { recursive: true });
187
-
552
+
188
553
  const created = [];
189
-
554
+
190
555
  for (const feature of features) {
191
556
  try {
192
- const zipPath = await createRecipe(feature);
193
- if (zipPath) {
194
- created.push({ name: feature.name, zipPath });
557
+ const zipName = await createRecipe(feature);
558
+ if (zipName) {
559
+ created.push({ name: feature.name, zipName });
195
560
  }
196
561
  } catch (err) {
197
562
  console.error(` ✗ Error creating ${feature.name}:`, err.message);
198
563
  }
199
564
  }
200
-
201
- console.log('\n✅ Recipe creation complete!\n');
202
- console.log('Created recipes:');
203
- created.forEach(({ name, zipPath }) => {
204
- console.log(` • ${name}@latest.zip`);
205
- });
206
-
207
- console.log('\n📤 Upload to R2 with:');
208
- console.log('cd ../recipes');
209
- created.forEach(({ name }) => {
210
- console.log(`wrangler r2 object put vibefast-recipes/${name}@latest.zip --file=${name}@latest.zip --remote`);
211
- });
212
-
213
- console.log('\n🧪 Test with:');
214
- console.log('cd ../../vibefast-monorepo');
215
- console.log('export VIBEFAST_WORKER_URL=https://vibefast-cli-worker.mzafar611.workers.dev');
216
- created.forEach(({ name }) => {
217
- console.log(`vf add ${name}`);
565
+
566
+ console.log("\n✅ Recipe creation complete!\n");
567
+ console.log("Created recipes:");
568
+ created.forEach(({ zipName }) => {
569
+ console.log(` • ${zipName}`);
218
570
  });
571
+
572
+ console.log("\nTo upload to R2, run: ./scripts/publish-all.sh");
219
573
  }
220
574
 
221
575
  main().catch(console.error);