vibefast-cli 1.3.0 → 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 +8 -9
  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 +271 -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 -33
  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 -69
  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 -70
  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 -62
  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 -44
  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,1629 +0,0 @@
1
- # 🔄 VibeFast CLI - Complete Flow Diagram
2
-
3
- A comprehensive visual guide to understanding how VibeFast CLI works from start to finish.
4
-
5
- ---
6
-
7
- ## 📋 Table of Contents
8
-
9
- 1. [System Architecture](#system-architecture)
10
- 2. [Command Flow Overview](#command-flow-overview)
11
- 3. [Authentication Flow](#authentication-flow)
12
- 4. [Feature Installation Flow](#feature-installation-flow)
13
- 5. [Feature Removal Flow](#feature-removal-flow)
14
- 6. [Device Management Flow](#device-management-flow)
15
- 7. [Data Flow Diagram](#data-flow-diagram)
16
- 8. [Component Interaction](#component-interaction)
17
-
18
- ---
19
-
20
- ## 🏗️ System Architecture
21
-
22
- ```
23
- ┌─────────────────────────────────────────────────────────────────┐
24
- │ VIBEFAST ECOSYSTEM │
25
- ├─────────────────────────────────────────────────────────────────┤
26
- │ │
27
- │ ┌────────────────────────────────────────────────────────┐ │
28
- │ │ CLOUDFLARE INFRASTRUCTURE │ │
29
- │ │ │ │
30
- │ │ ┌──────────────────────────────────────────────────┐ │ │
31
- │ │ │ Worker API │ │ │
32
- │ │ │ vibefast-cli-worker.mzafar611.workers.dev │ │ │
33
- │ │ │ │ │ │
34
- │ │ │ Endpoints: │ │ │
35
- │ │ │ • POST /api/recipe/fetch │ │ │
36
- │ │ │ • GET /api/recipes/list │ │ │
37
- │ │ │ • GET /api/devices/list │ │ │
38
- │ │ │ • POST /api/devices/deactivate │ │ │
39
- │ │ └──────────────────────────────────────────────────┘ │ │
40
- │ │ │ │ │ │
41
- │ │ ▼ ▼ │ │
42
- │ │ ┌─────────────────┐ ┌─────────────────┐ │ │
43
- │ │ │ KV Storage │ │ R2 Storage │ │ │
44
- │ │ │ │ │ │ │ │
45
- │ │ │ License Data: │ │ Recipe Zips: │ │ │
46
- │ │ │ • lic:hash123 │ │ • charts.zip │ │ │
47
- │ │ │ • lic:hash456 │ │ • chatbot.zip │ │ │
48
- │ │ │ • lic:hash789 │ │ • voice.zip │ │ │
49
- │ │ │ • Device slots │ │ • mini.zip │ │ │
50
- │ │ │ • Status │ │ • etc... │ │ │
51
- │ │ └─────────────────┘ └─────────────────┘ │ │
52
- │ └────────────────────────────────────────────────────────┘ │
53
- │ │
54
- │ ▲ │
55
- │ │ HTTPS │
56
- │ │ │
57
- └───────────────────────────┼──────────────────────────────────────┘
58
-
59
-
60
- ┌───────────────────────────┼──────────────────────────────────────┐
61
- │ │ │
62
- │ ▼ │
63
- │ ┌────────────────────────────────────────────────────────┐ │
64
- │ │ CUSTOMER'S MACHINE │ │
65
- │ │ │ │
66
- │ │ ┌──────────────────────────────────────────────────┐ │ │
67
- │ │ │ VibeFast CLI (Node.js Package) │ │ │
68
- │ │ │ npm: vibefast-cli │ │ │
69
- │ │ │ │ │ │
70
- │ │ │ Entry Point: src/index.ts │ │ │
71
- │ │ │ ├── Commands: │ │ │
72
- │ │ │ │ ├── login.ts │ │ │
73
- │ │ │ │ ├── logout.ts │ │ │
74
- │ │ │ │ ├── doctor.ts │ │ │
75
- │ │ │ │ ├── list.ts │ │ │
76
- │ │ │ │ ├── add.ts │ │ │
77
- │ │ │ │ ├── remove.ts │ │ │
78
- │ │ │ │ └── devices.ts │ │ │
79
- │ │ │ └── Core Modules: │ │ │
80
- │ │ │ ├── auth.ts (token & device) │ │ │
81
- │ │ │ ├── http.ts (API calls) │ │ │
82
- │ │ │ ├── archive.ts (zip handling) │ │ │
83
- │ │ │ ├── journal.ts (install tracking) │ │ │
84
- │ │ │ ├── codemod.ts (nav injection) │ │ │
85
- │ │ │ ├── fsx.ts (file operations) │ │ │
86
- │ │ │ ├── validate.ts (repo validation) │ │ │
87
- │ │ │ └── paths.ts (path resolution) │ │ │
88
- │ │ └──────────────────────────────────────────────────┘ │ │
89
- │ │ │ │ │
90
- │ │ ▼ │ │
91
- │ │ ┌──────────────────────────────────────────────────┐ │ │
92
- │ │ │ ~/.vibefast/config.json │ │ │
93
- │ │ │ { │ │ │
94
- │ │ │ "token": "TOKEN_ABC123", │ │ │
95
- │ │ │ "deviceId": "user-machine-os-uuid" │ │ │
96
- │ │ │ } │ │ │
97
- │ │ └──────────────────────────────────────────────────┘ │ │
98
- │ │ │ │ │
99
- │ │ ▼ │ │
100
- │ │ ┌──────────────────────────────────────────────────┐ │ │
101
- │ │ │ Customer's VibeFast Project │ │ │
102
- │ │ │ /path/to/my-vibefast-app/ │ │ │
103
- │ │ │ │ │ │
104
- │ │ │ .vibefast/ │ │ │
105
- │ │ │ ├── starter.json (repo identifier) │ │ │
106
- │ │ │ └── journal.json (install history) │ │ │
107
- │ │ │ │ │ │
108
- │ │ │ apps/ │ │ │
109
- │ │ │ ├── native/src/ │ │ │
110
- │ │ │ │ ├── app/(root)/(protected)/ │ │ │
111
- │ │ │ │ │ ├── charts/ ← CLI installs here │ │ │
112
- │ │ │ │ │ └── chatbot/ ← CLI installs here │ │ │
113
- │ │ │ │ ├── features/ │ │ │
114
- │ │ │ │ │ ├── charts/ ← CLI installs here │ │ │
115
- │ │ │ │ │ └── chatbot/ ← CLI installs here │ │ │
116
- │ │ │ │ └── app/(root)/(protected)/(tabs)/ │ │ │
117
- │ │ │ │ └── index.tsx ← CLI modifies nav │ │ │
118
- │ │ │ └── web/src/ │ │ │
119
- │ │ │ ├── app/ │ │ │
120
- │ │ │ └── components/ │ │ │
121
- │ │ └──────────────────────────────────────────────────┘ │ │
122
- │ └────────────────────────────────────────────────────────┘ │
123
- └─────────────────────────────────────────────────────────────────┘
124
- ```
125
-
126
- ---
127
-
128
- ## 🎯 Command Flow Overview
129
-
130
- ```
131
- ┌──────────────────────────────────────────────────────────────────┐
132
- │ CLI COMMAND STRUCTURE │
133
- └──────────────────────────────────────────────────────────────────┘
134
-
135
- vf (main)
136
-
137
- ┌──────────────┼──────────────┐
138
- │ │ │
139
- ▼ ▼ ▼
140
- ┌──────────┐ ┌──────────┐ ┌──────────┐
141
- │ Auth │ │ Feature │ │ Info │
142
- │ Commands │ │ Commands │ │ Commands │
143
- └──────────┘ └──────────┘ └──────────┘
144
- │ │ │
145
- ┌─────────┼─────────┐ │ ┌─────────┼─────────┐
146
- ▼ ▼ ▼ │ ▼ ▼ ▼
147
- login logout devices │ doctor list
148
-
149
- ┌────────┼────────┐
150
- ▼ ▼
151
- add remove
152
- ```
153
-
154
- ### Command Dependencies
155
-
156
- ```
157
- vf login
158
- └─> Stores token in ~/.vibefast/config.json
159
- └─> Required for: add, remove, list, devices
160
-
161
- vf doctor
162
- └─> Validates:
163
- ├─> VibeFast repo (.vibefast/starter.json exists)
164
- ├─> Auth status (token present)
165
- ├─> Navigation markers (for add/remove)
166
- └─> Project structure
167
-
168
- vf add <feature>
169
- └─> Requires:
170
- ├─> Valid token (vf login)
171
- ├─> VibeFast repo (doctor check)
172
- └─> Feature not already installed
173
- └─> Creates:
174
- ├─> Feature files in project
175
- ├─> Navigation link
176
- └─> Journal entry
177
-
178
- vf remove <feature>
179
- └─> Requires:
180
- ├─> VibeFast repo
181
- └─> Feature installed (journal entry exists)
182
- └─> Deletes:
183
- ├─> All tracked files
184
- ├─> Navigation link
185
- └─> Journal entry
186
- ```
187
-
188
- ---
189
-
190
- ## 🔐 Authentication Flow
191
-
192
- ```
193
- ┌─────────────────────────────────────────────────────────────────┐
194
- │ AUTHENTICATION FLOW │
195
- └─────────────────────────────────────────────────────────────────┘
196
-
197
- Step 1: Customer Receives License
198
- ┌──────────────────────────────┐
199
- │ LemonSqueezy Purchase │
200
- │ Receipt Email: │
201
- │ "Your token: TOKEN_ABC123" │
202
- └──────────────┬───────────────┘
203
-
204
-
205
- Step 2: Customer Runs Login
206
- ┌──────────────────────────────┐
207
- │ $ vf login --token TOKEN_ABC123
208
- │ │
209
- │ CLI Process: │
210
- │ 1. Validate token format │
211
- │ 2. Generate device ID │
212
- │ 3. Save to config file │
213
- └──────────────┬───────────────┘
214
-
215
-
216
- Step 3: Generate Device ID
217
- ┌──────────────────────────────┐
218
- │ Device ID Components: │
219
- │ • username │
220
- │ • hostname │
221
- │ • os (darwin/linux/win32) │
222
- │ • random UUID │
223
- │ │
224
- │ Result: │
225
- │ "john-macbook-darwin-a1b2" │
226
- └──────────────┬───────────────┘
227
-
228
-
229
- Step 4: Save Configuration
230
- ┌──────────────────────────────┐
231
- │ ~/.vibefast/config.json │
232
- │ { │
233
- │ "token": "TOKEN_ABC123", │
234
- │ "deviceId": "john-..." │
235
- │ } │
236
- └──────────────┬───────────────┘
237
-
238
-
239
- Step 5: First API Call
240
- ┌──────────────────────────────┐
241
- │ Any command (add/list/etc) │
242
- │ sends: │
243
- │ { │
244
- │ token: "TOKEN_ABC123", │
245
- │ device: { │
246
- │ id: "john-macbook...", │
247
- │ os: "darwin", │
248
- │ arch: "arm64" │
249
- │ } │
250
- │ } │
251
- └──────────────┬───────────────┘
252
-
253
-
254
- Step 6: Worker Validates
255
- ┌──────────────────────────────┐
256
- │ 1. Hash token (SHA-256) │
257
- │ TOKEN_ABC123 → d64c32... │
258
- │ │
259
- │ 2. Lookup in KV: │
260
- │ Key: "lic:d64c32..." │
261
- │ │
262
- │ 3. Check device slots: │
263
- │ devices: ["john-..."] │
264
- │ max_devices: 2 │
265
- │ │
266
- │ 4. Register device if new │
267
- │ (if slots available) │
268
- └──────────────┬───────────────┘
269
-
270
-
271
- Step 7: Response
272
- ┌──────────────────────────────┐
273
- │ Success: │
274
- │ { ok: true, ... } │
275
- │ │
276
- │ OR Error: │
277
- │ { ok: false, │
278
- │ error: "Device limit" } │
279
- └──────────────────────────────┘
280
- ```
281
-
282
- ---
283
-
284
- ## 📦 Feature Installation Flow (vf add)
285
-
286
- ```
287
- ┌─────────────────────────────────────────────────────────────────┐
288
- │ FEATURE INSTALLATION FLOW │
289
- │ vf add charts --target native │
290
- └─────────────────────────────────────────────────────────────────┘
291
-
292
- PHASE 1: PRE-FLIGHT CHECKS
293
- ┌──────────────────────────────────────────────────────────────┐
294
- │ 1. Validate Repository │
295
- │ ├─> Check .vibefast/starter.json exists │
296
- │ ├─> Parse config (name, version, targets) │
297
- │ └─> Validate target (native/web) is supported │
298
- │ │
299
- │ 2. Check Authentication │
300
- │ ├─> Read ~/.vibefast/config.json │
301
- │ ├─> Verify token exists │
302
- │ └─> Load device ID │
303
- │ │
304
- │ 3. Check Installation Status │
305
- │ ├─> Read .vibefast/journal.json │
306
- │ ├─> Look for existing entry (feature + target) │
307
- │ └─> Exit if exists (unless --force) │
308
- └──────────────────────────────────────────────────────────────┘
309
-
310
-
311
- PHASE 2: FETCH RECIPE FROM API
312
- ┌──────────────────────────────────────────────────────────────┐
313
- │ POST /api/recipe/fetch │
314
- │ │
315
- │ Request Body: │
316
- │ { │
317
- │ "token": "TOKEN_ABC123", │
318
- │ "device": { │
319
- │ "id": "john-macbook-darwin-uuid", │
320
- │ "os": "darwin", │
321
- │ "arch": "arm64", │
322
- │ "version": "0.1.4" │
323
- │ }, │
324
- │ "feature": "charts", │
325
- │ "target": "native", │
326
- │ "starter": { │
327
- │ "name": "vibefast", │
328
- │ "version": "1.0.0" │
329
- │ } │
330
- │ } │
331
- └──────────────────────────────────────────────────────────────┘
332
-
333
-
334
- PHASE 3: WORKER PROCESSING
335
- ┌──────────────────────────────────────────────────────────────┐
336
- │ Worker Actions: │
337
- │ │
338
- │ 1. Validate Token │
339
- │ ├─> Hash token (SHA-256) │
340
- │ ├─> Lookup in KV: "lic:hash" │
341
- │ └─> Check status: active/expired │
342
- │ │
343
- │ 2. Validate Device │
344
- │ ├─> Check if device already registered │
345
- │ ├─> If new: check slots (current < max_devices) │
346
- │ └─> Register device if slot available │
347
- │ │
348
- │ 3. Fetch Recipe from R2 │
349
- │ ├─> Key: "charts@latest.zip" │
350
- │ ├─> Read zip file into memory │
351
- │ └─> Convert to base64 (for JSON transport) │
352
- │ │
353
- │ 4. Generate Watermark │
354
- │ ├─> Take first 8 chars of token hash │
355
- │ ├─> Take first part of device ID │
356
- │ └─> Combine: "d64c3203-john" │
357
- └──────────────────────────────────────────────────────────────┘
358
-
359
-
360
- PHASE 4: WORKER RESPONSE
361
- ┌──────────────────────────────────────────────────────────────┐
362
- │ Response: │
363
- │ { │
364
- │ "ok": true, │
365
- │ "zipData": "UEsDBBQAAAAIAO+H...", // base64 zip │
366
- │ "watermark": "d64c3203-john", │
367
- │ "expiresIn": 180 │
368
- │ } │
369
- │ │
370
- │ OR Error Response: │
371
- │ { │
372
- │ "ok": false, │
373
- │ "error": "Device limit reached", │
374
- │ "message": "You have 2/2 devices..." │
375
- │ } │
376
- └──────────────────────────────────────────────────────────────┘
377
-
378
-
379
- PHASE 5: DOWNLOAD & EXTRACT
380
- ┌──────────────────────────────────────────────────────────────┐
381
- │ 1. Decode Base64 │
382
- │ └─> Convert base64 string → binary buffer │
383
- │ │
384
- │ 2. Save to Temp Directory │
385
- │ ├─> Create: /tmp/vibefast/<uuid>/ │
386
- │ └─> Write: recipe.zip │
387
- │ │
388
- │ 3. Extract Zip (Safe Extraction) │
389
- │ ├─> Validate all paths (no ../ escapes) │
390
- │ ├─> Extract to: /tmp/vibefast/<uuid>/ │
391
- │ └─> Result: │
392
- │ ├── recipe.json │
393
- │ └── apps/ │
394
- │ └── native/ │
395
- │ ├── src/app/charts/ │
396
- │ └── src/features/charts/ │
397
- └──────────────────────────────────────────────────────────────┘
398
-
399
-
400
- PHASE 6: READ RECIPE MANIFEST
401
- ┌──────────────────────────────────────────────────────────────┐
402
- │ Read: /tmp/vibefast/<uuid>/recipe.json │
403
- │ │
404
- │ { │
405
- │ "name": "charts", │
406
- │ "version": "1.0.0", │
407
- │ "description": "Beautiful data visualization", │
408
- │ "target": "native", │
409
- │ "copy": [ │
410
- │ { │
411
- │ "from": "apps/native/src/app/charts", │
412
- │ "to": "apps/native/src/app/(root)/(protected)/charts"│
413
- │ }, │
414
- │ { │
415
- │ "from": "apps/native/src/features/charts", │
416
- │ "to": "apps/native/src/features/charts" │
417
- │ } │
418
- │ ], │
419
- │ "nav": { │
420
- │ "href": "/(root)/(protected)/charts", │
421
- │ "label": "Charts", │
422
- │ "icon": "📊", │
423
- │ "color": "#6366F1" │
424
- │ } │
425
- │ } │
426
- │ │
427
- │ Validate: manifest.target === requested target │
428
- └──────────────────────────────────────────────────────────────┘
429
-
430
-
431
- PHASE 7: COPY FILES
432
- ┌──────────────────────────────────────────────────────────────┐
433
- │ For each "copy" instruction in manifest: │
434
- │ │
435
- │ Copy 1: │
436
- │ ├─> Source: /tmp/.../apps/native/src/app/charts/ │
437
- │ ├─> Dest: /project/apps/native/src/app/(root)/(protected)/charts/
438
- │ ├─> Validate paths (security check) │
439
- │ ├─> Create destination directories │
440
- │ ├─> Copy all files recursively │
441
- │ └─> Track copied file paths │
442
- │ │
443
- │ Copy 2: │
444
- │ ├─> Source: /tmp/.../apps/native/src/features/charts/ │
445
- │ ├─> Dest: /project/apps/native/src/features/charts/ │
446
- │ └─> Copy all files recursively │
447
- │ │
448
- │ Result: 17 files copied │
449
- └──────────────────────────────────────────────────────────────┘
450
-
451
-
452
- PHASE 8: ADD WATERMARKS
453
- ┌──────────────────────────────────────────────────────────────┐
454
- │ For each copied file (.ts, .tsx, .js, .jsx): │
455
- │ │
456
- │ Original file content: │
457
- │ ┌────────────────────────────────────────────────────────┐ │
458
- │ │ import ChartPreviewScreen from '@/features/charts'; │ │
459
- │ │ │ │
460
- │ │ export default function ChartsPage() { │ │
461
- │ │ return <ChartPreviewScreen />; │ │
462
- │ │ } │ │
463
- │ └────────────────────────────────────────────────────────┘ │
464
- │ │
465
- │ After watermark: │
466
- │ ┌────────────────────────────────────────────────────────┐ │
467
- │ │ // vibefast license: d64c3203-john │ │
468
- │ │ import ChartPreviewScreen from '@/features/charts'; │ │
469
- │ │ │ │
470
- │ │ export default function ChartsPage() { │ │
471
- │ │ return <ChartPreviewScreen />; │ │
472
- │ │ } │ │
473
- │ └────────────────────────────────────────────────────────┘ │
474
- └──────────────────────────────────────────────────────────────┘
475
-
476
-
477
- PHASE 9: UPDATE NAVIGATION
478
- ┌──────────────────────────────────────────────────────────────┐
479
- │ Target File (Native): │
480
- │ apps/native/src/app/(root)/(protected)/(tabs)/index.tsx │
481
- │ │
482
- │ Find markers: │
483
- │ // --- @vibefast:navigation:start --- │
484
- │ // --- @vibefast:navigation:end --- │
485
- │ │
486
- │ Insert navigation object: │
487
- │ { │
488
- │ id: 'charts', │
489
- │ title: 'Charts', │
490
- │ icon: '📊', │
491
- │ color: '#6366F1', │
492
- │ description: 'Charts feature', │
493
- │ route: '/charts', │
494
- │ testID: 'charts-button', │
495
- │ } │
496
- │ │
497
- │ Result: Navigation link added ✓ │
498
- └──────────────────────────────────────────────────────────────┘
499
-
500
-
501
- PHASE 10: UPDATE JOURNAL
502
- ┌──────────────────────────────────────────────────────────────┐
503
- │ File: .vibefast/journal.json │
504
- │ │
505
- │ Add entry: │
506
- │ { │
507
- │ "entries": [ │
508
- │ { │
509
- │ "feature": "charts", │
510
- │ "target": "native", │
511
- │ "files": [ │
512
- │ "/full/path/to/apps/native/src/app/.../index.tsx", │
513
- │ "/full/path/to/apps/native/src/features/charts/...",│
514
- │ ... (15 more files) │
515
- │ ], │
516
- │ "insertedNav": true, │
517
- │ "navHref": "/(root)/(protected)/charts", │
518
- │ "navLabel": "Charts", │
519
- │ "ts": 1762912823535 │
520
- │ } │
521
- │ ] │
522
- │ } │
523
- │ │
524
- │ Purpose: Track installation for future removal │
525
- └──────────────────────────────────────────────────────────────┘
526
-
527
-
528
- PHASE 11: CLEANUP & SUCCESS
529
- ┌──────────────────────────────────────────────────────────────┐
530
- │ 1. Delete temp directory │
531
- │ └─> rm -rf /tmp/vibefast/<uuid>/ │
532
- │ │
533
- │ 2. Display success message │
534
- │ ✓ charts installed successfully! │
535
- │ ℹ Files added: 17 │
536
- │ ℹ Next steps: │
537
- │ 1. Review the changes in your repo │
538
- │ 2. Run your dev server to test │
539
- │ 3. Navigate to the new feature │
540
- └──────────────────────────────────────────────────────────────┘
541
- ```
542
-
543
- ---
544
-
545
- ## 🗑️ Feature Removal Flow (vf remove)
546
-
547
- ```
548
- ┌─────────────────────────────────────────────────────────────────┐
549
- │ FEATURE REMOVAL FLOW │
550
- │ vf remove charts --target native │
551
- └─────────────────────────────────────────────────────────────────┘
552
-
553
- PHASE 1: VALIDATION
554
- ┌──────────────────────────────────────────────────────────────┐
555
- │ 1. Validate Repository │
556
- │ ├─> Check .vibefast/starter.json exists │
557
- │ └─> Validate target (native/web) │
558
- │ │
559
- │ 2. Check Journal │
560
- │ ├─> Read .vibefast/journal.json │
561
- │ ├─> Find entry for (feature + target) │
562
- │ └─> Exit if not found │
563
- └──────────────────────────────────────────────────────────────┘
564
-
565
-
566
- PHASE 2: READ JOURNAL ENTRY
567
- ┌──────────────────────────────────────────────────────────────┐
568
- │ Entry found: │
569
- │ { │
570
- │ "feature": "charts", │
571
- │ "target": "native", │
572
- │ "files": [ │
573
- │ "/path/to/apps/native/src/app/.../index.tsx", │
574
- │ "/path/to/apps/native/src/app/.../chart-card.tsx", │
575
- │ "/path/to/apps/native/src/features/charts/index.ts", │
576
- │ ... (14 more files) │
577
- │ ], │
578
- │ "insertedNav": true, │
579
- │ "navHref": "/(root)/(protected)/charts", │
580
- │ "navLabel": "Charts" │
581
- │ } │
582
- └──────────────────────────────────────────────────────────────┘
583
-
584
-
585
- PHASE 3: DELETE FILES
586
- ┌──────────────────────────────────────────────────────────────┐
587
- │ For each file in entry.files: │
588
- │ │
589
- │ 1. /path/to/apps/native/src/app/.../index.tsx │
590
- │ └─> fs.unlink() → Deleted ✓ │
591
- │ │
592
- │ 2. /path/to/apps/native/src/app/.../chart-card.tsx │
593
- │ └─> fs.unlink() → Deleted ✓ │
594
- │ │
595
- │ ... (continue for all 17 files) │
596
- │ │
597
- │ Result: 17 files deleted │
598
- └──────────────────────────────────────────────────────────────┘
599
-
600
-
601
- PHASE 4: REMOVE NAVIGATION LINK
602
- ┌──────────────────────────────────────────────────────────────┐
603
- │ If entry.insertedNav === true: │
604
- │ │
605
- │ Target File: │
606
- │ apps/native/src/app/(root)/(protected)/(tabs)/index.tsx │
607
- │ │
608
- │ Find and remove navigation object: │
609
- │ { │
610
- │ id: 'charts', │
611
- │ title: 'Charts', │
612
- │ icon: '📊', │
613
- │ ... │
614
- │ } │
615
- │ │
616
- │ Match by: entry.navHref or feature name │
617
- │ Result: Navigation link removed ✓ │
618
- └──────────────────────────────────────────────────────────────┘
619
-
620
-
621
- PHASE 5: UPDATE JOURNAL
622
- ┌──────────────────────────────────────────────────────────────┐
623
- │ Remove entry from journal: │
624
- │ │
625
- │ Before: │
626
- │ { │
627
- │ "entries": [ │
628
- │ { "feature": "charts", ... }, │
629
- │ { "feature": "chatbot", ... } │
630
- │ ] │
631
- │ } │
632
- │ │
633
- │ After: │
634
- │ { │
635
- │ "entries": [ │
636
- │ { "feature": "chatbot", ... } │
637
- │ ] │
638
- │ } │
639
- └──────────────────────────────────────────────────────────────┘
640
-
641
-
642
- PHASE 6: SUCCESS
643
- ┌──────────────────────────────────────────────────────────────┐
644
- │ ✓ charts removed successfully! │
645
- │ ℹ Files deleted: 17 │
646
- └──────────────────────────────────────────────────────────────┘
647
- ```
648
-
649
- ---
650
-
651
- ## 📱 Device Management Flow
652
-
653
- ```
654
- ┌─────────────────────────────────────────────────────────────────┐
655
- │ DEVICE MANAGEMENT FLOW │
656
- └─────────────────────────────────────────────────────────────────┘
657
-
658
- LIST DEVICES (vf devices)
659
- ┌──────────────────────────────────────────────────────────────┐
660
- │ 1. Read token from ~/.vibefast/config.json │
661
- │ │
662
- │ 2. GET /api/devices/list │
663
- │ Request: { token: "TOKEN_ABC123" } │
664
- │ │
665
- │ 3. Worker Response: │
666
- │ { │
667
- │ "ok": true, │
668
- │ "devices": [ │
669
- │ { │
670
- │ "id": "john-macbook-darwin-a1b2", │
671
- │ "os": "darwin", │
672
- │ "arch": "arm64", │
673
- │ "firstSeen": 1762912823535, │
674
- │ "lastSeen": 1762999999999 │
675
- │ }, │
676
- │ { │
677
- │ "id": "john-work-laptop-linux-c3d4", │
678
- │ "os": "linux", │
679
- │ "arch": "x64", │
680
- │ "firstSeen": 1762800000000, │
681
- │ "lastSeen": 1762900000000 │
682
- │ } │
683
- │ ], │
684
- │ "maxDevices": 2, │
685
- │ "currentCount": 2 │
686
- │ } │
687
- │ │
688
- │ 4. Display: │
689
- │ Active devices (2/2): │
690
- │ • john-macbook-darwin-a1b2 (darwin/arm64) │
691
- │ • john-work-laptop-linux-c3d4 (linux/x64) │
692
- └──────────────────────────────────────────────────────────────┘
693
-
694
- DEACTIVATE DEVICE (vf devices --deactivate <id>)
695
- ┌──────────────────────────────────────────────────────────────┐
696
- │ 1. Read token from config │
697
- │ │
698
- │ 2. POST /api/devices/deactivate │
699
- │ Request: { │
700
- │ token: "TOKEN_ABC123", │
701
- │ deviceId: "john-work-laptop-linux-c3d4" │
702
- │ } │
703
- │ │
704
- │ 3. Worker Process: │
705
- │ ├─> Validate token │
706
- │ ├─> Find device in license.devices[] │
707
- │ ├─> Remove device from array │
708
- │ └─> Update KV storage │
709
- │ │
710
- │ 4. Response: │
711
- │ { │
712
- │ "ok": true, │
713
- │ "message": "Device deactivated" │
714
- │ } │
715
- │ │
716
- │ 5. Display: │
717
- │ ✓ Device deactivated successfully │
718
- │ ℹ You now have 1/2 device slots used │
719
- └──────────────────────────────────────────────────────────────┘
720
- ```
721
-
722
- ---
723
-
724
- ## 🔄 Data Flow Diagram
725
-
726
- ```
727
- ┌─────────────────────────────────────────────────────────────────┐
728
- │ COMPLETE DATA FLOW │
729
- └─────────────────────────────────────────────────────────────────┘
730
-
731
- USER ACTION
732
-
733
-
734
- ┌─────────────────┐
735
- │ vf add charts │
736
- └────────┬────────┘
737
-
738
-
739
- ┌─────────────────────────────────────────────────────────────┐
740
- │ CLI: Pre-flight Checks │
741
- │ ┌────────────────────────────────────────────────────────┐ │
742
- │ │ 1. Read .vibefast/starter.json │ │
743
- │ │ → { name, version, targets } │ │
744
- │ │ │ │
745
- │ │ 2. Read ~/.vibefast/config.json │ │
746
- │ │ → { token, deviceId } │ │
747
- │ │ │ │
748
- │ │ 3. Read .vibefast/journal.json │ │
749
- │ │ → Check if already installed │ │
750
- │ └────────────────────────────────────────────────────────┘ │
751
- └─────────────────────────────────────────────────────────────┘
752
-
753
-
754
- ┌─────────────────────────────────────────────────────────────┐
755
- │ CLI → Worker: HTTP Request │
756
- │ ┌────────────────────────────────────────────────────────┐ │
757
- │ │ POST /api/recipe/fetch │ │
758
- │ │ │ │
759
- │ │ Headers: │ │
760
- │ │ Content-Type: application/json │ │
761
- │ │ │ │
762
- │ │ Body: │ │
763
- │ │ { │ │
764
- │ │ token: "TOKEN_ABC123", │ │
765
- │ │ device: { │ │
766
- │ │ id: "john-macbook-darwin-uuid", │ │
767
- │ │ os: "darwin", │ │
768
- │ │ arch: "arm64", │ │
769
- │ │ version: "0.1.4" │ │
770
- │ │ }, │ │
771
- │ │ feature: "charts", │ │
772
- │ │ target: "native", │ │
773
- │ │ starter: { name: "vibefast", version: "1.0.0" } │ │
774
- │ │ } │ │
775
- │ └────────────────────────────────────────────────────────┘ │
776
- └─────────────────────────────────────────────────────────────┘
777
-
778
-
779
- ┌─────────────────────────────────────────────────────────────┐
780
- │ Worker: Token Validation │
781
- │ ┌────────────────────────────────────────────────────────┐ │
782
- │ │ 1. Hash token │ │
783
- │ │ TOKEN_ABC123 │ │
784
- │ │ → SHA-256 │ │
785
- │ │ → d64c32038ffc94ff7d18644b15364bf9935d8faba2f4... │ │
786
- │ │ │ │
787
- │ │ 2. Query KV │ │
788
- │ │ Key: "lic:d64c32038ffc94ff..." │ │
789
- │ │ Value: { │ │
790
- │ │ status: "active", │ │
791
- │ │ maxDevices: 2, │ │
792
- │ │ devices: ["john-macbook-darwin-uuid"], │ │
793
- │ │ createdAt: 1762800000000 │ │
794
- │ │ } │ │
795
- │ └────────────────────────────────────────────────────────┘ │
796
- └─────────────────────────────────────────────────────────────┘
797
-
798
-
799
- ┌─────────────────────────────────────────────────────────────┐
800
- │ Worker: Device Validation │
801
- │ ┌────────────────────────────────────────────────────────┐ │
802
- │ │ Check: Is "john-macbook-darwin-uuid" in devices[]? │ │
803
- │ │ │ │
804
- │ │ YES → Allow request │ │
805
- │ │ │ │
806
- │ │ NO → Check slots: │ │
807
- │ │ devices.length < maxDevices? │ │
808
- │ │ YES → Add device, allow request │ │
809
- │ │ NO → Reject (device limit reached) │ │
810
- │ └────────────────────────────────────────────────────────┘ │
811
- └─────────────────────────────────────────────────────────────┘
812
-
813
-
814
- ┌─────────────────────────────────────────────────────────────┐
815
- │ Worker: Fetch Recipe from R2 │
816
- │ ┌────────────────────────────────────────────────────────┐ │
817
- │ │ 1. Construct key: "charts@latest.zip" │ │
818
- │ │ │ │
819
- │ │ 2. R2.get("charts@latest.zip") │ │
820
- │ │ → Binary zip data │ │
821
- │ │ │ │
822
- │ │ 3. Convert to base64 │ │
823
- │ │ → "UEsDBBQAAAAIAO+H..." │ │
824
- │ │ │ │
825
- │ │ 4. Generate watermark │ │
826
- │ │ tokenHash.slice(0,8) + "-" + deviceId.split("-")[0]│ │
827
- │ │ → "d64c3203-john" │ │
828
- │ └────────────────────────────────────────────────────────┘ │
829
- └─────────────────────────────────────────────────────────────┘
830
-
831
-
832
- ┌─────────────────────────────────────────────────────────────┐
833
- │ Worker → CLI: HTTP Response │
834
- │ ┌────────────────────────────────────────────────────────┐ │
835
- │ │ Status: 200 OK │ │
836
- │ │ │ │
837
- │ │ Body: │ │
838
- │ │ { │ │
839
- │ │ ok: true, │ │
840
- │ │ zipData: "UEsDBBQAAAAIAO+H...", │ │
841
- │ │ watermark: "d64c3203-john", │ │
842
- │ │ expiresIn: 180 │ │
843
- │ │ } │ │
844
- │ └────────────────────────────────────────────────────────┘ │
845
- └─────────────────────────────────────────────────────────────┘
846
-
847
-
848
- ┌─────────────────────────────────────────────────────────────┐
849
- │ CLI: Process Recipe │
850
- │ ┌────────────────────────────────────────────────────────┐ │
851
- │ │ 1. Decode base64 → binary │ │
852
- │ │ │ │
853
- │ │ 2. Save to temp │ │
854
- │ │ /tmp/vibefast/uuid123/recipe.zip │ │
855
- │ │ │ │
856
- │ │ 3. Extract zip │ │
857
- │ │ /tmp/vibefast/uuid123/ │ │
858
- │ │ ├── recipe.json │ │
859
- │ │ └── apps/native/src/... │ │
860
- │ │ │ │
861
- │ │ 4. Read recipe.json │ │
862
- │ │ → Parse manifest │ │
863
- │ │ │ │
864
- │ │ 5. Copy files per manifest.copy[] │ │
865
- │ │ → Track all copied file paths │ │
866
- │ │ │ │
867
- │ │ 6. Add watermark to each file │ │
868
- │ │ → Prepend: // vibefast license: d64c3203-john │ │
869
- │ │ │ │
870
- │ │ 7. Insert navigation link │ │
871
- │ │ → Modify nav file between markers │ │
872
- │ └────────────────────────────────────────────────────────┘ │
873
- └─────────────────────────────────────────────────────────────┘
874
-
875
-
876
- ┌─────────────────────────────────────────────────────────────┐
877
- │ CLI: Update Journal │
878
- │ ┌────────────────────────────────────────────────────────┐ │
879
- │ │ Write to .vibefast/journal.json: │ │
880
- │ │ │ │
881
- │ │ { │ │
882
- │ │ "entries": [ │ │
883
- │ │ { │ │
884
- │ │ "feature": "charts", │ │
885
- │ │ "target": "native", │ │
886
- │ │ "files": [ │ │
887
- │ │ "/abs/path/to/file1.tsx", │ │
888
- │ │ "/abs/path/to/file2.tsx", │ │
889
- │ │ ... (15 more) │ │
890
- │ │ ], │ │
891
- │ │ "insertedNav": true, │ │
892
- │ │ "navHref": "/(root)/(protected)/charts", │ │
893
- │ │ "navLabel": "Charts", │ │
894
- │ │ "ts": 1762912823535 │ │
895
- │ │ } │ │
896
- │ │ ] │ │
897
- │ │ } │ │
898
- │ └────────────────────────────────────────────────────────┘ │
899
- └─────────────────────────────────────────────────────────────┘
900
-
901
-
902
- ┌─────────────────────────────────────────────────────────────┐
903
- │ CLI: Success Output │
904
- │ ┌────────────────────────────────────────────────────────┐ │
905
- │ │ ✓ charts installed successfully! │ │
906
- │ │ ℹ Files added: 17 │ │
907
- │ │ ℹ Next steps: │ │
908
- │ │ 1. Review the changes in your repo │ │
909
- │ │ 2. Run your dev server to test │ │
910
- │ │ 3. Navigate to the new feature │ │
911
- │ └────────────────────────────────────────────────────────┘ │
912
- └─────────────────────────────────────────────────────────────┘
913
- ```
914
-
915
- ---
916
-
917
- ## 🧩 Component Interaction
918
-
919
- ```
920
- ┌─────────────────────────────────────────────────────────────────┐
921
- │ CLI INTERNAL ARCHITECTURE │
922
- └─────────────────────────────────────────────────────────────────┘
923
-
924
- src/index.ts
925
- (Entry Point)
926
-
927
- ┌────────────┼────────────┐
928
- │ │ │
929
- ▼ ▼ ▼
930
- ┌──────────┐ ┌──────────┐ ┌──────────┐
931
- │ Commands │ │ Commands │ │ Commands │
932
- │ Layer │ │ Layer │ │ Layer │
933
- └──────────┘ └──────────┘ └──────────┘
934
- │ │ │
935
- ┌─────────┼────────────┼────────────┼─────────┐
936
- │ │ │ │ │
937
- ▼ ▼ ▼ ▼ ▼
938
- ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
939
- │ login │ │ doctor │ │ add │ │ remove │ │devices │
940
- │ .ts │ │ .ts │ │ .ts │ │ .ts │ │ .ts │
941
- └────────┘ └────────┘ └────────┘ └────────┘ └────────┘
942
- │ │ │ │ │
943
- └─────────┴────────────┴────────────┴─────────┘
944
-
945
-
946
- ┌────────────────────────┐
947
- │ Core Modules │
948
- └────────────────────────┘
949
-
950
- ┌──────────────────┼──────────────────┐
951
- │ │ │
952
- ▼ ▼ ▼
953
- ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
954
- │ auth.ts │ │ http.ts │ │ archive.ts │
955
- │ │ │ │ │ │
956
- │ • getToken() │ │ • fetchRecipe│ │ • extractZip │
957
- │ • getDevice │ │ • download │ │ • validate │
958
- │ Info() │ │ Zip() │ │ paths │
959
- └──────────────┘ └──────────────┘ └──────────────┘
960
-
961
- ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
962
- │ journal.ts │ │ codemod.ts │ │ fsx.ts │
963
- │ │ │ │ │ │
964
- │ • addEntry() │ │ • insertNav │ │ • copyTree() │
965
- │ • getEntry() │ │ LinkNative │ │ • readFile │
966
- │ • remove │ │ • removeNav │ │ Content() │
967
- │ Entry() │ │ LinkNative │ │ • writeFile │
968
- └──────────────┘ └──────────────┘ └──────────────┘
969
-
970
- ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
971
- │ validate.ts │ │ paths.ts │ │ pathGuard.ts │
972
- │ │ │ │ │ │
973
- │ • validate │ │ • getPaths() │ │ • ensure │
974
- │ Signature()│ │ • resolve │ │ WithinBase │
975
- │ • validate │ │ paths │ │ • security │
976
- │ Target() │ │ │ │ checks │
977
- └──────────────┘ └──────────────┘ └──────────────┘
978
-
979
- ┌──────────────┐
980
- │ log.ts │
981
- │ │
982
- │ • log.info() │
983
- │ • log.error()│
984
- │ • log. │
985
- │ success() │
986
- └──────────────┘
987
- ```
988
-
989
- ### Module Dependencies
990
-
991
- ```
992
- add.ts depends on:
993
- ├── log (logging)
994
- ├── paths (path resolution)
995
- ├── validate (repo & target validation)
996
- ├── auth (token & device info)
997
- ├── http (API communication)
998
- ├── journal (install tracking)
999
- ├── fsx (file operations)
1000
- ├── codemod (navigation injection)
1001
- ├── pathGuard (security)
1002
- └── archive (zip extraction)
1003
-
1004
- remove.ts depends on:
1005
- ├── log
1006
- ├── paths
1007
- ├── validate
1008
- ├── journal
1009
- ├── fsx
1010
- └── codemod
1011
-
1012
- login.ts depends on:
1013
- ├── log
1014
- ├── auth
1015
- └── fsx
1016
-
1017
- doctor.ts depends on:
1018
- ├── log
1019
- ├── paths
1020
- ├── validate
1021
- └── auth
1022
-
1023
- devices.ts depends on:
1024
- ├── log
1025
- ├── auth
1026
- └── http
1027
- ```
1028
-
1029
- ---
1030
-
1031
- ## 🔐 Security & Watermarking Flow
1032
-
1033
- ```
1034
- ┌─────────────────────────────────────────────────────────────────┐
1035
- │ SECURITY MECHANISMS │
1036
- └─────────────────────────────────────────────────────────────────┘
1037
-
1038
- TOKEN HASHING
1039
- ┌──────────────────────────────────────────────────────────────┐
1040
- │ Customer Token (Plain Text): │
1041
- │ "TOKEN_ABC123" │
1042
- │ │
1043
- │ ↓ SHA-256 Hash │
1044
- │ │
1045
- │ Token Hash: │
1046
- │ "d64c32038ffc94ff7d18644b15364bf9935d8faba2f4ff2ee3b72367..." │
1047
- │ │
1048
- │ ↓ Store in KV │
1049
- │ │
1050
- │ KV Key: │
1051
- │ "lic:d64c32038ffc94ff7d18644b15364bf9935d8faba2f4ff2ee3..." │
1052
- │ │
1053
- │ Purpose: │
1054
- │ • Never store plain tokens │
1055
- │ • Secure lookup mechanism │
1056
- │ • One-way encryption │
1057
- └──────────────────────────────────────────────────────────────┘
1058
-
1059
- DEVICE ID GENERATION
1060
- ┌──────────────────────────────────────────────────────────────┐
1061
- │ Components: │
1062
- │ ┌────────────────────────────────────────────────────────┐ │
1063
- │ │ username: "john" │ │
1064
- │ │ hostname: "macbook" │ │
1065
- │ │ os: "darwin" │ │
1066
- │ │ uuid: "a1b2c3d4" │ │
1067
- │ └────────────────────────────────────────────────────────┘ │
1068
- │ │
1069
- │ ↓ Combine │
1070
- │ │
1071
- │ Device ID: │
1072
- │ "john-macbook-darwin-a1b2c3d4" │
1073
- │ │
1074
- │ Properties: │
1075
- │ • Stable across CLI runs │
1076
- │ • Unique per machine │
1077
- │ • Human-readable │
1078
- │ • Stored in ~/.vibefast/config.json │
1079
- └──────────────────────────────────────────────────────────────┘
1080
-
1081
- WATERMARK GENERATION
1082
- ┌──────────────────────────────────────────────────────────────┐
1083
- │ Input: │
1084
- │ • Token Hash: "d64c32038ffc94ff..." │
1085
- │ • Device ID: "john-macbook-darwin-a1b2c3d4" │
1086
- │ │
1087
- │ ↓ Process │
1088
- │ │
1089
- │ 1. Take first 8 chars of token hash │
1090
- │ "d64c32038ffc94ff..." → "d64c3203" │
1091
- │ │
1092
- │ 2. Take first part of device ID (before first dash) │
1093
- │ "john-macbook-darwin-a1b2c3d4" → "john" │
1094
- │ │
1095
- │ 3. Combine with dash │
1096
- │ "d64c3203" + "-" + "john" → "d64c3203-john" │
1097
- │ │
1098
- │ ↓ Apply to files │
1099
- │ │
1100
- │ Watermark: │
1101
- │ "d64c3203-john" │
1102
- │ │
1103
- │ Usage: │
1104
- │ • Prepended to every code file │
1105
- │ • Format: // vibefast license: d64c3203-john │
1106
- │ • Enables leak tracing │
1107
- └──────────────────────────────────────────────────────────────┘
1108
-
1109
- WATERMARK APPLICATION
1110
- ┌──────────────────────────────────────────────────────────────┐
1111
- │ Original File (index.tsx): │
1112
- │ ┌────────────────────────────────────────────────────────┐ │
1113
- │ │ import { View } from 'react-native'; │ │
1114
- │ │ import ChartPreview from '@/features/charts'; │ │
1115
- │ │ │ │
1116
- │ │ export default function ChartsPage() { │ │
1117
- │ │ return ( │ │
1118
- │ │ <View> │ │
1119
- │ │ <ChartPreview /> │ │
1120
- │ │ </View> │ │
1121
- │ │ ); │ │
1122
- │ │ } │ │
1123
- │ └────────────────────────────────────────────────────────┘ │
1124
- │ │
1125
- │ ↓ Add Watermark │
1126
- │ │
1127
- │ Watermarked File: │
1128
- │ ┌────────────────────────────────────────────────────────┐ │
1129
- │ │ // vibefast license: d64c3203-john │ │
1130
- │ │ import { View } from 'react-native'; │ │
1131
- │ │ import ChartPreview from '@/features/charts'; │ │
1132
- │ │ │ │
1133
- │ │ export default function ChartsPage() { │ │
1134
- │ │ return ( │ │
1135
- │ │ <View> │ │
1136
- │ │ <ChartPreview /> │ │
1137
- │ │ </View> │ │
1138
- │ │ ); │ │
1139
- │ │ } │ │
1140
- │ └────────────────────────────────────────────────────────┘ │
1141
- │ │
1142
- │ Applied to: │
1143
- │ • .ts files │
1144
- │ • .tsx files │
1145
- │ • .js files │
1146
- │ • .jsx files │
1147
- └──────────────────────────────────────────────────────────────┘
1148
-
1149
- PATH SECURITY
1150
- ┌──────────────────────────────────────────────────────────────┐
1151
- │ All file operations use pathGuard.ensureWithinBase() │
1152
- │ │
1153
- │ Example: │
1154
- │ ┌────────────────────────────────────────────────────────┐ │
1155
- │ │ Base: /Users/john/project/ │ │
1156
- │ │ │ │
1157
- │ │ Valid paths: │ │
1158
- │ │ ✓ /Users/john/project/apps/native/src/app/charts/ │ │
1159
- │ │ ✓ /Users/john/project/apps/web/src/components/ │ │
1160
- │ │ │ │
1161
- │ │ Invalid paths (rejected): │ │
1162
- │ │ ✗ /Users/john/project/../../../etc/passwd │ │
1163
- │ │ ✗ /tmp/malicious/ │ │
1164
- │ │ ✗ /Users/john/other-project/ │ │
1165
- │ └────────────────────────────────────────────────────────┘ │
1166
- │ │
1167
- │ Protection against: │
1168
- │ • Directory traversal attacks │
1169
- │ • Writing outside project │
1170
- │ • Malicious zip entries │
1171
- └──────────────────────────────────────────────────────────────┘
1172
-
1173
- DEVICE SLOT ENFORCEMENT
1174
- ┌──────────────────────────────────────────────────────────────┐
1175
- │ License Data in KV: │
1176
- │ { │
1177
- │ "status": "active", │
1178
- │ "maxDevices": 2, │
1179
- │ "devices": [ │
1180
- │ { │
1181
- │ "id": "john-macbook-darwin-a1b2", │
1182
- │ "firstSeen": 1762800000000, │
1183
- │ "lastSeen": 1762999999999 │
1184
- │ }, │
1185
- │ { │
1186
- │ "id": "john-work-laptop-linux-c3d4", │
1187
- │ "firstSeen": 1762850000000, │
1188
- │ "lastSeen": 1762900000000 │
1189
- │ } │
1190
- │ ] │
1191
- │ } │
1192
- │ │
1193
- │ Validation Logic: │
1194
- │ ┌────────────────────────────────────────────────────────┐ │
1195
- │ │ if (device in devices[]) { │ │
1196
- │ │ // Device already registered → Allow │ │
1197
- │ │ return true; │ │
1198
- │ │ } │ │
1199
- │ │ │ │
1200
- │ │ if (devices.length < maxDevices) { │ │
1201
- │ │ // Slot available → Register & Allow │ │
1202
- │ │ devices.push(newDevice); │ │
1203
- │ │ return true; │ │
1204
- │ │ } │ │
1205
- │ │ │ │
1206
- │ │ // No slots available → Reject │ │
1207
- │ │ return false; │ │
1208
- │ └────────────────────────────────────────────────────────┘ │
1209
- └──────────────────────────────────────────────────────────────┘
1210
- ```
1211
-
1212
- ---
1213
-
1214
- ## 📊 State Management
1215
-
1216
- ```
1217
- ┌─────────────────────────────────────────────────────────────────┐
1218
- │ STATE PERSISTENCE │
1219
- └─────────────────────────────────────────────────────────────────┘
1220
-
1221
- USER CONFIG (~/.vibefast/config.json)
1222
- ┌──────────────────────────────────────────────────────────────┐
1223
- │ Location: User's home directory │
1224
- │ Purpose: Store authentication credentials │
1225
- │ │
1226
- │ Structure: │
1227
- │ { │
1228
- │ "token": "TOKEN_ABC123", │
1229
- │ "deviceId": "john-macbook-darwin-a1b2c3d4" │
1230
- │ } │
1231
- │ │
1232
- │ Operations: │
1233
- │ • Created by: vf login │
1234
- │ • Read by: All commands (except login) │
1235
- │ • Deleted by: vf logout │
1236
- │ • Modified by: vf login (overwrite) │
1237
- └──────────────────────────────────────────────────────────────┘
1238
-
1239
- PROJECT SIGNATURE (.vibefast/starter.json)
1240
- ┌──────────────────────────────────────────────────────────────┐
1241
- │ Location: Project root │
1242
- │ Purpose: Identify VibeFast repository │
1243
- │ │
1244
- │ Structure: │
1245
- │ { │
1246
- │ "name": "vibefast", │
1247
- │ "version": "1.0.0", │
1248
- │ "targets": ["native", "web"] │
1249
- │ } │
1250
- │ │
1251
- │ Operations: │
1252
- │ • Created by: VibeFast starter template │
1253
- │ • Read by: All commands (validation) │
1254
- │ • Never modified by CLI │
1255
- └──────────────────────────────────────────────────────────────┘
1256
-
1257
- INSTALLATION JOURNAL (.vibefast/journal.json)
1258
- ┌──────────────────────────────────────────────────────────────┐
1259
- │ Location: Project root │
1260
- │ Purpose: Track installed features │
1261
- │ │
1262
- │ Structure: │
1263
- │ { │
1264
- │ "entries": [ │
1265
- │ { │
1266
- │ "feature": "charts", │
1267
- │ "target": "native", │
1268
- │ "files": [ │
1269
- │ "/abs/path/to/file1.tsx", │
1270
- │ "/abs/path/to/file2.tsx", │
1271
- │ ... │
1272
- │ ], │
1273
- │ "insertedNav": true, │
1274
- │ "navHref": "/(root)/(protected)/charts", │
1275
- │ "navLabel": "Charts", │
1276
- │ "ts": 1762912823535 │
1277
- │ }, │
1278
- │ { │
1279
- │ "feature": "chatbot", │
1280
- │ "target": "web", │
1281
- │ "files": [...], │
1282
- │ "insertedNav": true, │
1283
- │ "navHref": "/chatbot", │
1284
- │ "navLabel": "Chatbot", │
1285
- │ "ts": 1762999999999 │
1286
- │ } │
1287
- │ ] │
1288
- │ } │
1289
- │ │
1290
- │ Operations: │
1291
- │ • Created by: First vf add │
1292
- │ • Read by: vf add (check existing), vf remove │
1293
- │ • Modified by: vf add (append), vf remove (delete entry) │
1294
- │ • Purpose: Enable clean removal of features │
1295
- └──────────────────────────────────────────────────────────────┘
1296
-
1297
- CLOUDFLARE KV (License Storage)
1298
- ┌──────────────────────────────────────────────────────────────┐
1299
- │ Location: Cloudflare KV namespace │
1300
- │ Purpose: Store license and device data │
1301
- │ │
1302
- │ Key Format: "lic:<token_hash>" │
1303
- │ │
1304
- │ Value Structure: │
1305
- │ { │
1306
- │ "status": "active" | "expired" | "revoked", │
1307
- │ "maxDevices": 2, │
1308
- │ "devices": [ │
1309
- │ { │
1310
- │ "id": "john-macbook-darwin-a1b2", │
1311
- │ "os": "darwin", │
1312
- │ "arch": "arm64", │
1313
- │ "firstSeen": 1762800000000, │
1314
- │ "lastSeen": 1762999999999 │
1315
- │ } │
1316
- │ ], │
1317
- │ "createdAt": 1762800000000, │
1318
- │ "expiresAt": null │
1319
- │ } │
1320
- │ │
1321
- │ Operations: │
1322
- │ • Created by: License activation (manual/webhook) │
1323
- │ • Read by: All API endpoints │
1324
- │ • Modified by: Device registration/deactivation │
1325
- └──────────────────────────────────────────────────────────────┘
1326
-
1327
- CLOUDFLARE R2 (Recipe Storage)
1328
- ┌──────────────────────────────────────────────────────────────┐
1329
- │ Location: Cloudflare R2 bucket │
1330
- │ Purpose: Store feature zip files │
1331
- │ │
1332
- │ Key Format: "<feature>@<version>.zip" │
1333
- │ Examples: │
1334
- │ • charts@latest.zip │
1335
- │ • charts@1.0.0.zip │
1336
- │ • chatbot@latest.zip │
1337
- │ • voice@2.1.0.zip │
1338
- │ │
1339
- │ Zip Contents: │
1340
- │ ├── recipe.json (manifest) │
1341
- │ └── apps/ │
1342
- │ ├── native/src/... (native code) │
1343
- │ └── web/src/... (web code) │
1344
- │ │
1345
- │ Operations: │
1346
- │ • Created by: Manual upload or CI/CD │
1347
- │ • Read by: Worker (on recipe fetch) │
1348
- │ • Never modified by CLI │
1349
- └──────────────────────────────────────────────────────────────┘
1350
- ```
1351
-
1352
- ---
1353
-
1354
- ## 🎯 Error Handling Flow
1355
-
1356
- ```
1357
- ┌─────────────────────────────────────────────────────────────────┐
1358
- │ ERROR SCENARIOS │
1359
- └─────────────────────────────────────────────────────────────────┘
1360
-
1361
- ERROR 1: Not a VibeFast Repo
1362
- ┌──────────────────────────────────────────────────────────────┐
1363
- │ Trigger: .vibefast/starter.json not found │
1364
- │ │
1365
- │ Flow: │
1366
- │ vf add charts │
1367
- │ ↓ │
1368
- │ validate.validateSignature() │
1369
- │ ↓ │
1370
- │ fs.readFile('.vibefast/starter.json') │
1371
- │ ↓ │
1372
- │ Error: ENOENT (file not found) │
1373
- │ ↓ │
1374
- │ log.error('Not a VibeFast repository') │
1375
- │ process.exit(1) │
1376
- │ │
1377
- │ User sees: │
1378
- │ ✗ Not a VibeFast repository │
1379
- │ ℹ Make sure you're in the root of your VibeFast project │
1380
- └──────────────────────────────────────────────────────────────┘
1381
-
1382
- ERROR 2: Not Logged In
1383
- ┌──────────────────────────────────────────────────────────────┐
1384
- │ Trigger: ~/.vibefast/config.json not found or no token │
1385
- │ │
1386
- │ Flow: │
1387
- │ vf add charts │
1388
- │ ↓ │
1389
- │ auth.getToken() │
1390
- │ ↓ │
1391
- │ fs.readFile('~/.vibefast/config.json') │
1392
- │ ↓ │
1393
- │ Error: ENOENT or token === null │
1394
- │ ↓ │
1395
- │ log.error('Not logged in') │
1396
- │ log.info('Run "vf login --token <TOKEN>" first') │
1397
- │ process.exit(1) │
1398
- │ │
1399
- │ User sees: │
1400
- │ ✗ Not logged in │
1401
- │ ℹ Run "vf login --token <TOKEN>" first │
1402
- └──────────────────────────────────────────────────────────────┘
1403
-
1404
- ERROR 3: Device Limit Reached
1405
- ┌──────────────────────────────────────────────────────────────┐
1406
- │ Trigger: License has max devices registered │
1407
- │ │
1408
- │ Flow: │
1409
- │ vf add charts │
1410
- │ ↓ │
1411
- │ http.fetchRecipe() │
1412
- │ ↓ │
1413
- │ Worker validates device │
1414
- │ ↓ │
1415
- │ devices.length >= maxDevices && device not in list │
1416
- │ ↓ │
1417
- │ Response: { ok: false, error: "Device limit reached" } │
1418
- │ ↓ │
1419
- │ log.error('Device limit reached (2/2)') │
1420
- │ log.info('Run "vf devices" to manage devices') │
1421
- │ process.exit(1) │
1422
- │ │
1423
- │ User sees: │
1424
- │ ✗ Device limit reached (2/2) │
1425
- │ ℹ Run "vf devices" to see active devices │
1426
- │ ℹ Use "vf devices --deactivate <id>" to free a slot │
1427
- └──────────────────────────────────────────────────────────────┘
1428
-
1429
- ERROR 4: Feature Already Installed
1430
- ┌──────────────────────────────────────────────────────────────┐
1431
- │ Trigger: Journal has entry for feature+target │
1432
- │ │
1433
- │ Flow: │
1434
- │ vf add charts │
1435
- │ ↓ │
1436
- │ journal.getEntry('charts', 'native') │
1437
- │ ↓ │
1438
- │ Entry found │
1439
- │ ↓ │
1440
- │ log.warn('charts is already installed for native') │
1441
- │ log.info('Use --force to reinstall') │
1442
- │ return (no exit) │
1443
- │ │
1444
- │ User sees: │
1445
- │ ⚠ charts is already installed for native │
1446
- │ ℹ Use --force to reinstall │
1447
- └──────────────────────────────────────────────────────────────┘
1448
-
1449
- ERROR 5: Feature Not Installed (Remove)
1450
- ┌──────────────────────────────────────────────────────────────┐
1451
- │ Trigger: Trying to remove non-existent feature │
1452
- │ │
1453
- │ Flow: │
1454
- │ vf remove charts │
1455
- │ ↓ │
1456
- │ journal.getEntry('charts', 'native') │
1457
- │ ↓ │
1458
- │ Entry not found │
1459
- │ ↓ │
1460
- │ log.warn('charts is not installed for native') │
1461
- │ log.info('Run "vf list" to see installed features') │
1462
- │ return (no exit) │
1463
- │ │
1464
- │ User sees: │
1465
- │ ⚠ charts is not installed for native │
1466
- │ ℹ Run "vf list" to see installed features │
1467
- └──────────────────────────────────────────────────────────────┘
1468
-
1469
- ERROR 6: Invalid Token
1470
- ┌──────────────────────────────────────────────────────────────┐
1471
- │ Trigger: Token not found in KV or status != "active" │
1472
- │ │
1473
- │ Flow: │
1474
- │ vf add charts │
1475
- │ ↓ │
1476
- │ http.fetchRecipe() │
1477
- │ ↓ │
1478
- │ Worker validates token │
1479
- │ ↓ │
1480
- │ KV.get('lic:hash') → null or status === "expired" │
1481
- │ ↓ │
1482
- │ Response: { ok: false, error: "Invalid or expired token" } │
1483
- │ ↓ │
1484
- │ log.error('Invalid or expired token') │
1485
- │ log.info('Contact support@vibefast.pro') │
1486
- │ process.exit(1) │
1487
- │ │
1488
- │ User sees: │
1489
- │ ✗ Invalid or expired token │
1490
- │ ℹ Contact support@vibefast.pro │
1491
- └──────────────────────────────────────────────────────────────┘
1492
- ```
1493
-
1494
- ---
1495
-
1496
- ## 🎬 Complete User Journey
1497
-
1498
- ```
1499
- ┌─────────────────────────────────────────────────────────────────┐
1500
- │ END-TO-END USER JOURNEY │
1501
- └─────────────────────────────────────────────────────────────────┘
1502
-
1503
- DAY 1: Purchase & Setup
1504
- ┌──────────────────────────────────────────────────────────────┐
1505
- │ 1. Customer buys VibeFast license │
1506
- │ └─> Receives email with TOKEN_ABC123 │
1507
- │ │
1508
- │ 2. Customer clones VibeFast starter │
1509
- │ $ git clone https://github.com/vibefast/starter.git │
1510
- │ $ cd starter │
1511
- │ │
1512
- │ 3. Customer installs CLI │
1513
- │ $ npm install -g vibefast-cli │
1514
- │ │
1515
- │ 4. Customer logs in │
1516
- │ $ vf login --token TOKEN_ABC123 │
1517
- │ ✓ Logged in successfully │
1518
- │ │
1519
- │ 5. Customer verifies setup │
1520
- │ $ vf doctor │
1521
- │ ✓ VibeFast repository detected │
1522
- │ ✓ Authenticated │
1523
- │ ✓ Navigation markers found │
1524
- │ ✓ All checks passed! │
1525
- └──────────────────────────────────────────────────────────────┘
1526
-
1527
- DAY 1: Install First Feature
1528
- ┌──────────────────────────────────────────────────────────────┐
1529
- │ 6. Customer lists available features │
1530
- │ $ vf list │
1531
- │ Available features: │
1532
- │ • charts - Data visualization │
1533
- │ • chatbot - AI assistant │
1534
- │ • voice - Voice commands │
1535
- │ │
1536
- │ 7. Customer installs charts │
1537
- │ $ vf add charts │
1538
- │ ℹ Fetching charts for native... │
1539
- │ ℹ Downloading recipe... │
1540
- │ ℹ Installing charts v1.0.0... │
1541
- │ ℹ Copying files... │
1542
- │ ℹ Adding navigation link... │
1543
- │ ✓ charts installed successfully! │
1544
- │ ℹ Files added: 17 │
1545
- │ │
1546
- │ 8. Customer tests the feature │
1547
- │ $ npm run dev │
1548
- │ → Opens app, sees Charts in navigation │
1549
- │ → Clicks Charts, feature works! 🎉 │
1550
- └──────────────────────────────────────────────────────────────┘
1551
-
1552
- DAY 30: Install More Features
1553
- ┌──────────────────────────────────────────────────────────────┐
1554
- │ 9. Customer installs chatbot for web │
1555
- │ $ vf add chatbot --target web │
1556
- │ ✓ chatbot installed successfully! │
1557
- │ ℹ Files added: 23 │
1558
- │ │
1559
- │ 10. Customer installs voice for native │
1560
- │ $ vf add voice │
1561
- │ ✓ voice installed successfully! │
1562
- │ ℹ Files added: 31 │
1563
- └──────────────────────────────────────────────────────────────┘
1564
-
1565
- DAY 60: Remove Unused Feature
1566
- ┌──────────────────────────────────────────────────────────────┐
1567
- │ 11. Customer decides not to use charts │
1568
- │ $ vf remove charts │
1569
- │ ℹ Removing charts from native... │
1570
- │ ℹ Deleting files... │
1571
- │ ℹ Removing navigation link... │
1572
- │ ✓ charts removed successfully! │
1573
- │ ℹ Files deleted: 17 │
1574
- └──────────────────────────────────────────────────────────────┘
1575
-
1576
- DAY 90: New Computer
1577
- ┌──────────────────────────────────────────────────────────────┐
1578
- │ 12. Customer gets new laptop │
1579
- │ $ npm install -g vibefast-cli │
1580
- │ $ vf login --token TOKEN_ABC123 │
1581
- │ ✓ Logged in successfully │
1582
- │ (Device 2/2 registered) │
1583
- │ │
1584
- │ 13. Customer tries to use on 3rd computer │
1585
- │ $ vf add mini │
1586
- │ ✗ Device limit reached (2/2) │
1587
- │ ℹ Run "vf devices" to manage devices │
1588
- │ │
1589
- │ 14. Customer checks devices │
1590
- │ $ vf devices │
1591
- │ Active devices (2/2): │
1592
- │ • john-macbook-darwin-a1b2 (darwin/arm64) │
1593
- │ • john-laptop-linux-c3d4 (linux/x64) │
1594
- │ │
1595
- │ 15. Customer deactivates old device │
1596
- │ $ vf devices --deactivate john-macbook-darwin-a1b2 │
1597
- │ ✓ Device deactivated successfully │
1598
- │ ℹ You now have 1/2 device slots used │
1599
- │ │
1600
- │ 16. Customer can now use 3rd computer │
1601
- │ $ vf add mini │
1602
- │ ✓ mini installed successfully! │
1603
- └──────────────────────────────────────────────────────────────┘
1604
- ```
1605
-
1606
- ---
1607
-
1608
- ## 📚 Summary
1609
-
1610
- The VibeFast CLI is a sophisticated yet user-friendly tool that:
1611
-
1612
- 1. **Authenticates** users with license tokens
1613
- 2. **Validates** device limits (2 per license)
1614
- 3. **Fetches** feature recipes from Cloudflare R2
1615
- 4. **Installs** features into monorepo projects
1616
- 5. **Tracks** installations in a journal
1617
- 6. **Watermarks** all code files for leak prevention
1618
- 7. **Manages** navigation injection automatically
1619
- 8. **Enables** clean removal of features
1620
- 9. **Enforces** security through path validation
1621
- 10. **Provides** excellent error messages and UX
1622
-
1623
- All of this happens seamlessly with simple commands like `vf add charts` and `vf remove charts`.
1624
-
1625
- ---
1626
-
1627
- **Created:** 2024
1628
- **Version:** 0.1.4
1629
- **Author:** VibeFast Team