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.
- package/README.md +30 -95
- package/dist/__tests__/recipes.test.js +8 -9
- package/dist/__tests__/recipes.test.js.map +1 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +271 -125
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/checklist.d.ts.map +1 -1
- package/dist/commands/checklist.js +85 -44
- package/dist/commands/checklist.js.map +1 -1
- package/dist/commands/health.d.ts.map +1 -1
- package/dist/commands/health.js +13 -4
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +118 -26
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +202 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +61 -3
- package/dist/commands/remove.js.map +1 -1
- package/dist/core/auth.d.ts.map +1 -1
- package/dist/core/auth.js +20 -18
- package/dist/core/auth.js.map +1 -1
- package/dist/core/codemod.d.ts +33 -0
- package/dist/core/codemod.d.ts.map +1 -1
- package/dist/core/codemod.js +116 -0
- package/dist/core/codemod.js.map +1 -1
- package/dist/core/detect.d.ts.map +1 -1
- package/dist/core/detect.js +24 -7
- package/dist/core/detect.js.map +1 -1
- package/dist/core/journal.d.ts +1 -0
- package/dist/core/journal.d.ts.map +1 -1
- package/dist/core/journal.js.map +1 -1
- package/dist/core/recipes.d.ts.map +1 -1
- package/dist/core/recipes.js +25 -7
- package/dist/core/recipes.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/architecture.md +50 -0
- package/docs/commands.md +78 -0
- package/docs/contributing.md +27 -0
- package/docs/quickstart.md +50 -0
- package/docs/recipes.md +57 -0
- package/docs/troubleshooting.md +31 -0
- package/package.json +2 -2
- package/recipes/0/apps/native/src/components/advanced-ui/timeline/demo.tsx +445 -0
- package/recipes/0/apps/native/src/components/advanced-ui/timeline/timeline-view.tsx +355 -0
- package/recipes/0/apps/native/src/components/advanced-ui/timeline/types.ts +31 -0
- package/recipes/0/recipe.json +18 -0
- package/recipes/animated-chip/apps/native/src/components/advanced-ui/chip/demo.tsx +2 -1
- package/recipes/animated-chip/recipe.json +5 -2
- package/recipes/animated-chip-native@latest.zip +0 -0
- package/recipes/animated-chip@latest.zip +0 -0
- package/recipes/animated-switch/apps/native/src/components/advanced-ui/switch/demo.tsx +1 -1
- package/recipes/animated-switch/recipe.json +5 -2
- package/recipes/animated-switch-native@latest.zip +0 -0
- package/recipes/animated-switch@latest.zip +0 -0
- package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
- package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -2
- package/recipes/audio-recorder/recipe.json +7 -2
- package/recipes/audio-recorder-native@latest.zip +0 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -1
- package/recipes/audio-recorder-supabase/recipe.json +12 -33
- package/recipes/audio-recorder-supabase-native@latest.zip +0 -0
- package/recipes/audio-recorder-supabase@latest.zip +0 -0
- package/recipes/audio-recorder@latest.zip +0 -0
- package/recipes/charts/apps/native/src/app/charts/index.tsx +3 -0
- package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +3 -1
- package/recipes/charts/recipe.json +13 -4
- package/recipes/charts-native@latest.zip +0 -0
- package/recipes/charts@latest.zip +0 -0
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
- package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +4 -4
- package/recipes/chatbot/recipe.json +3 -40
- package/recipes/chatbot-native@latest.zip +0 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +4 -1
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
- package/recipes/chatbot-supabase/recipe.json +3 -69
- package/recipes/chatbot-supabase-native@latest.zip +0 -0
- package/recipes/chatbot-supabase@latest.zip +0 -0
- package/recipes/chatbot@latest.zip +0 -0
- package/recipes/glowing-button/recipe.json +6 -2
- package/recipes/glowing-button-native@latest.zip +0 -0
- package/recipes/glowing-button@latest.zip +0 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/index.tsx +50 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/results.tsx +2 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +2 -2
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/camera.tsx +72 -65
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +65 -47
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading-screen.tsx +43 -2
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading.tsx +34 -1
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +83 -2
- package/recipes/image-analysis/recipe.json +11 -19
- package/recipes/image-analysis-native@latest.zip +0 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/index.tsx +50 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/results.tsx +2 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
- package/recipes/image-analysis-supabase/recipe.json +10 -70
- package/recipes/image-analysis-supabase-native@latest.zip +0 -0
- package/recipes/image-analysis-supabase@latest.zip +0 -0
- package/recipes/image-analysis@latest.zip +0 -0
- package/recipes/image-analyzer/apps/native/src/app/(root)/(protected)/image-analyzer/index.tsx +2 -0
- package/recipes/image-generator/apps/native/src/app/image-generator/gallery.tsx +3 -0
- package/recipes/image-generator/apps/native/src/app/image-generator/index.tsx +3 -0
- package/recipes/image-generator/recipe.json +8 -18
- package/recipes/image-generator-native@latest.zip +0 -0
- package/recipes/image-generator-supabase/recipe.json +6 -62
- package/recipes/image-generator-supabase-native@latest.zip +0 -0
- package/recipes/image-generator-supabase@latest.zip +0 -0
- package/recipes/image-generator@latest.zip +0 -0
- package/recipes/ios-widget/recipe.json +18 -119
- package/recipes/ios-widget-native@latest.zip +0 -0
- package/recipes/ios-widget@latest.zip +0 -0
- package/recipes/number-stepper/apps/native/src/components/advanced-ui/stepper/demo.tsx +1 -1
- package/recipes/number-stepper/recipe.json +5 -2
- package/recipes/number-stepper-native@latest.zip +0 -0
- package/recipes/number-stepper@latest.zip +0 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +11 -18
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +9 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +8 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +6 -5
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +4 -3
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +6 -5
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +7 -6
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +8 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +6 -5
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +5 -6
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +5 -4
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +7 -6
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +4 -3
- package/recipes/onboarding/recipe.json +9 -6
- package/recipes/onboarding-native@latest.zip +0 -0
- package/recipes/onboarding@latest.zip +0 -0
- package/recipes/payments/apps/native/src/app/paywall/index.tsx +74 -0
- package/recipes/payments/apps/native/src/app/paywall/local.tsx +25 -0
- package/recipes/payments/apps/native/src/app/paywall/remote.tsx +23 -0
- package/recipes/payments/packages/backend/convex/payments.ts +21 -3
- package/recipes/payments/recipe.json +14 -34
- package/recipes/payments-native@latest.zip +0 -0
- package/recipes/payments-supabase/apps/native/src/app/paywall/index.tsx +74 -0
- package/recipes/payments-supabase/apps/native/src/app/paywall/local.tsx +25 -0
- package/recipes/payments-supabase/apps/native/src/app/paywall/remote.tsx +23 -0
- package/recipes/payments-supabase/recipe.json +16 -44
- package/recipes/payments-supabase-native@latest.zip +0 -0
- package/recipes/payments-supabase@latest.zip +0 -0
- package/recipes/payments@latest.zip +0 -0
- package/recipes/posthog/apps/native/src/components/analytics/navigation-tracker.tsx +14 -0
- package/recipes/posthog/apps/native/src/lib/hooks/use-navigation-analytics.ts +44 -0
- package/recipes/posthog/apps/native/src/providers/posthog-provider.tsx +51 -0
- package/recipes/posthog/recipe.json +60 -0
- package/recipes/posthog-native@latest.zip +0 -0
- package/recipes/progress-circle/apps/native/src/components/advanced-ui/progress-bars/progress-circle-page.tsx +1 -1
- package/recipes/progress-circle/recipe.json +5 -2
- package/recipes/progress-circle-native@latest.zip +0 -0
- package/recipes/progress-circle@latest.zip +0 -0
- package/recipes/quiz/apps/native/src/app/quiz/index.tsx +47 -0
- package/recipes/quiz/recipe.json +9 -6
- package/recipes/quiz-native@latest.zip +0 -0
- package/recipes/quiz@latest.zip +0 -0
- package/recipes/screen-kits/apps/native/src/app/screen-kits/_layout.tsx +12 -0
- package/recipes/screen-kits/apps/native/src/app/screen-kits/index.tsx +114 -0
- package/recipes/screen-kits/apps/native/src/features/screen-kits/index.ts +1 -0
- package/recipes/screen-kits/apps/native/src/features/screen-kits/types.ts +28 -0
- package/recipes/screen-kits/recipe.json +26 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/_layout.tsx +12 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/home.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/index.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-complete.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-fail.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/skill-tree.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/duo-button.tsx +174 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/skill-button.tsx +186 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/xp-header.tsx +115 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/constants.ts +89 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/index.ts +3 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/home-screen.tsx +225 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-complete-screen.tsx +485 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-fail-screen.tsx +105 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-screen.tsx +384 -0
- package/recipes/screen-kits-duolingo/recipe.json +58 -0
- package/recipes/screen-kits-duolingo-native@latest.zip +0 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/_layout.tsx +45 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/asset-detail.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/notifications.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/receive.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/send.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/swap.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/wallet.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/ActionButtons.tsx +78 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/AssetRow.tsx +94 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/BalanceCard.tsx +118 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/constants.ts +85 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/asset-detail.tsx +378 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/notifications.tsx +210 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/receive-modal.tsx +317 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/send-modal.tsx +420 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/swap-modal.tsx +363 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/wallet-dashboard.tsx +281 -0
- package/recipes/screen-kits-finance/recipe.json +46 -0
- package/recipes/screen-kits-finance-native@latest.zip +0 -0
- package/recipes/screen-kits-fitness/apps/native/assets/sounds/timer-beep.wav +0 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/_layout.tsx +10 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/index.tsx +6 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/timer.tsx +3 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/workout.tsx +3 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-components.tsx +500 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-settings-modal.tsx +352 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/workout-card.tsx +105 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/constants.ts +189 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/hooks/use-timer.ts +307 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/index.ts +1 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/timer-screen.tsx +278 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/workout-dashboard.tsx +350 -0
- package/recipes/screen-kits-fitness/recipe.json +63 -0
- package/recipes/screen-kits-fitness-native@latest.zip +0 -0
- package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/habits.tsx +1 -0
- package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/kanban.tsx +1 -0
- package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/routes.ts +4 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/AddTaskModal.tsx +246 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/DraggableTaskCard.tsx +92 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/KanbanColumn.tsx +238 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/TaskCard.tsx +144 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/add-habit-modal.tsx +271 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/constants.ts +295 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/kanban-utils.ts +62 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/habit-tracker.tsx +1160 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/kanban-board.tsx +432 -0
- package/recipes/screen-kits-habits/recipe.json +52 -0
- package/recipes/screen-kits-habits-native@latest.zip +0 -0
- package/recipes/screen-kits-native@latest.zip +0 -0
- package/recipes/sentry/apps/native/src/providers/sentry-provider.tsx +64 -0
- package/recipes/sentry/recipe.json +39 -0
- package/recipes/sentry-native@latest.zip +0 -0
- package/recipes/swipe-slider/apps/native/src/components/advanced-ui/sliders/swipe-slider-page.tsx +1 -1
- package/recipes/swipe-slider/recipe.json +5 -2
- package/recipes/swipe-slider-native@latest.zip +0 -0
- package/recipes/swipe-slider@latest.zip +0 -0
- package/recipes/timeline/apps/native/src/components/advanced-ui/timeline/demo.tsx +2 -1
- package/recipes/timeline/recipe.json +5 -2
- package/recipes/timeline-native@latest.zip +0 -0
- package/recipes/timeline@latest.zip +0 -0
- package/recipes/tracker-app/apps/native/src/app/tracker-app/index.tsx +1 -0
- package/recipes/tracker-app/recipe.json +10 -7
- package/recipes/tracker-app-native@latest.zip +0 -0
- package/recipes/tracker-app@latest.zip +0 -0
- package/recipes/upload-all.sh +8 -31
- package/recipes/voice-bot/apps/native/src/app/voice-bot/index.tsx +56 -0
- package/recipes/voice-bot/recipe.json +31 -7
- package/recipes/voice-bot-native@latest.zip +0 -0
- package/recipes/voice-bot@latest.zip +0 -0
- package/recipes/wake-word/apps/native/src/app/{(root)/(protected)/test-wake-word.tsx → test-wake-word.tsx} +43 -4
- package/recipes/wake-word/recipe.json +16 -26
- package/recipes/wake-word-native@latest.zip +0 -0
- package/recipes/wake-word@latest.zip +0 -0
- package/scripts/create-advanced-ui-recipes.sh +46 -19
- package/scripts/create-recipes.mjs +471 -117
- package/scripts/package-recipes.mjs +76 -0
- package/scripts/publish-all.sh +6 -2
- package/CHANGELOG.md +0 -198
- package/docs/archive/AUTO-DETECT-DEPS.md +0 -607
- package/docs/archive/FINAL-PACKAGE-STRATEGY.md +0 -583
- package/docs/archive/FINAL-SIMPLE-PLAN.md +0 -487
- package/docs/archive/FINAL-STATUS.md +0 -144
- package/docs/archive/FLOW-DIAGRAM.md +0 -1629
- package/docs/archive/GOTCHAS-AND-RISKS.md +0 -801
- package/docs/archive/IMPLEMENTATION-PLAN.md +0 -1360
- package/docs/archive/PLAN.md +0 -453
- package/docs/archive/PRODUCTION-READINESS.md +0 -684
- package/docs/archive/PRODUCTION-TEST-RESULTS.md +0 -465
- package/docs/archive/SIMPLIFIED-PLAN.md +0 -578
- package/docs/archive/STATUS.md +0 -199
- package/docs/archive/SUCCESS.md +0 -259
- package/docs/archive/TEST-SUMMARY.md +0 -261
- package/docs/archive/TESTING-CHECKLIST.md +0 -450
- package/docs/archive/USER-MODIFICATIONS.md +0 -448
- package/docs/decisions.md +0 -55
- package/docs/manual-testing.md +0 -91
- package/docs/next-steps.md +0 -12
- package/recipes/README.md +0 -156
- package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +0 -369
- package/recipes/chatbot/apps/native/src/api-client/chatbot.ts +0 -83
- package/recipes/chatbot/packages/backend/convex/agents.ts +0 -115
- package/recipes/chatbot/packages/backend/convex/tools/index.ts +0 -18
- package/recipes/chatbot/packages/backend/convex/tools/knowledgeRetrieval.ts +0 -97
- package/recipes/chatbot/packages/backend/convex/tools/tavilySearch.ts +0 -83
- package/recipes/chatbot/packages/backend/convex/tools/userProfile.ts +0 -72
- package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +0 -515
- package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +0 -243
- package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +0 -327
- package/recipes/image-analysis/apps/native/src/api-client/image-analyzer.ts +0 -62
- package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +0 -132
- package/recipes/image-generator/apps/native/src/api-client/image-generator.ts +0 -34
- package/recipes/payments/apps/native/src/api-client/payments.ts +0 -44
- package/recipes/payments-supabase/packages/backend/src/services/payments.ts +0 -201
- package/recipes/posthog.json +0 -47
- package/recipes/revenuecat.json +0 -43
- package/recipes/sentry.json +0 -47
- package/recipes/wake-word/apps/native/assets/vosk-model/README.md +0 -103
- package/recipes/wake-word/apps/native/scripts/download-vosk-model.mjs +0 -127
- /package/recipes/{audio-recorder/apps/native/src/app/(root)/(protected) → audio-recorder-supabase/apps/native/src/app}/audio-recorder/index.tsx +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/AppIntent.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/CalorieTrackerWidget.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/HabitTrackerWidget.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Info.plist +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/WidgetLiveActivity.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/expo-target.config.js +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/generated.entitlements +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/index.swift +0 -0
- /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
|