vibefast-cli 1.1.3 → 1.2.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/CHANGELOG.md +32 -0
- package/README.md +63 -169
- package/dist/__tests__/recipes.test.js +25 -3
- package/dist/__tests__/recipes.test.js.map +1 -1
- package/dist/commands/add.d.ts +1 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +547 -543
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/checklist.d.ts +1 -1
- package/dist/commands/checklist.d.ts.map +1 -1
- package/dist/commands/checklist.js +40 -39
- package/dist/commands/checklist.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/doctor.js +22 -22
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env.d.ts +1 -1
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +58 -53
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/health.d.ts +1 -1
- package/dist/commands/health.d.ts.map +1 -1
- package/dist/commands/health.js +101 -93
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +416 -296
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/remove.d.ts +1 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +77 -64
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +15 -14
- package/dist/commands/status.js.map +1 -1
- package/dist/core/__tests__/detect.test.js +68 -34
- package/dist/core/__tests__/detect.test.js.map +1 -1
- package/dist/core/ast.d.ts +14 -0
- package/dist/core/ast.d.ts.map +1 -0
- package/dist/core/ast.js +239 -0
- package/dist/core/ast.js.map +1 -0
- package/dist/core/codemod.d.ts.map +1 -1
- package/dist/core/codemod.js +62 -44
- package/dist/core/codemod.js.map +1 -1
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +51 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/detect.d.ts +8 -2
- package/dist/core/detect.d.ts.map +1 -1
- package/dist/core/detect.js +52 -21
- package/dist/core/detect.js.map +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +9 -8
- package/dist/core/errors.js.map +1 -1
- package/dist/core/exec.d.ts +16 -0
- package/dist/core/exec.d.ts.map +1 -0
- package/dist/core/exec.js +48 -0
- package/dist/core/exec.js.map +1 -0
- package/dist/core/manualSteps.d.ts +7 -0
- package/dist/core/manualSteps.d.ts.map +1 -0
- package/dist/core/manualSteps.js +59 -0
- package/dist/core/manualSteps.js.map +1 -0
- package/dist/core/paths.d.ts +3 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +14 -10
- package/dist/core/paths.js.map +1 -1
- package/dist/core/spinner.d.ts +1 -1
- package/dist/core/spinner.d.ts.map +1 -1
- package/dist/core/spinner.js +38 -8
- package/dist/core/spinner.js.map +1 -1
- package/dist/core/vosk.d.ts.map +1 -1
- package/dist/core/vosk.js +50 -39
- package/dist/core/vosk.js.map +1 -1
- package/docs/manual-testing.md +91 -0
- package/package.json +6 -3
- package/recipes/audio-recorder/apps/native/src/app/audio-recorder/index.tsx +5 -0
- package/recipes/audio-recorder/recipe.json +3 -3
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/index.ts +4 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
- package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +369 -0
- package/recipes/audio-recorder-supabase/packages/backend/supabase/migrations/recordings.sql +70 -0
- package/recipes/audio-recorder-supabase/recipe.json +35 -0
- package/recipes/audio-recorder-supabase@latest.zip +0 -0
- package/recipes/audio-recorder@latest.zip +0 -0
- package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -3
- package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +2 -2
- package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +5 -5
- package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -3
- package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +20 -4
- package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +7 -6
- package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +6 -4
- package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +1 -1
- package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +5 -4
- package/recipes/charts/recipe.json +4 -13
- package/recipes/charts@latest.zip +0 -0
- package/recipes/chatbot/apps/native/src/app/chatbot/index.tsx +1 -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 +86 -53
- package/recipes/chatbot/recipe.json +26 -92
- package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +515 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/app/index.tsx +257 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +59 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-input-bar.tsx +485 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +575 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +223 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +161 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/image-preview-list.tsx +116 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +165 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/index.ts +10 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +129 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-error-boundary.tsx +78 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-list.tsx +170 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/model-selector.tsx +283 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/report-content-modal.tsx +188 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/suggested-messages.tsx +67 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/models.ts +20 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/report-reasons.ts +9 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +142 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-config.ts +458 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +429 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +89 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-conversation.ts +90 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-image-picker.ts +122 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +161 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +213 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/index.ts +86 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/models.ts +162 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/providers.ts +62 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/types.ts +40 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/file-uploader.ts +287 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/message-handler-service.ts +189 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/types/index.ts +70 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/utils/chat-telemetry.ts +91 -0
- package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +243 -0
- package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +327 -0
- package/recipes/chatbot-supabase/packages/backend/supabase/functions/chat-stream/index.ts +347 -0
- package/recipes/chatbot-supabase/packages/backend/supabase/migrations/chatbot.sql +104 -0
- package/recipes/chatbot-supabase/recipe.json +79 -0
- package/recipes/chatbot-supabase@latest.zip +0 -0
- package/recipes/chatbot.zip +0 -0
- package/recipes/chatbot@latest.zip +0 -0
- package/recipes/image-analysis/packages/backend/convex/imageAnalysis/index.ts +2 -2
- package/recipes/image-analysis/packages/backend/convex/{imageAnalysisFunctions.ts → imageAnalysis.ts} +5 -5
- package/recipes/image-analysis/recipe.json +15 -55
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +304 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/camera.tsx +221 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +333 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading-screen.tsx +214 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading.tsx +191 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/results.tsx +137 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/trait-details.tsx +172 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-analysis-data.ts +160 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-results-screen.ts +151 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-badge.tsx +77 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-card.tsx +75 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-unlocked-modal.tsx +162 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievements-section.tsx +44 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/advice-list.tsx +42 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/circular-progress.tsx +233 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/content-card.tsx +38 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/error-state.tsx +42 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/index.ts +9 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/loading-state.tsx +26 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/profile-image.tsx +60 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/results-header.tsx +62 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/score-display.tsx +54 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/share-options-modal.tsx +110 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/traits-grid.tsx +74 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/analysis-config.ts +80 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/master-analysis-config.ts +157 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/index.ts +1 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-analysis.ts +38 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +208 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/analysis-service.ts +262 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/share-service.ts +176 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/trait-details-service.ts +289 -0
- package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +132 -0
- package/recipes/image-analysis-supabase/packages/backend/supabase/functions/analyze-image/index.ts +312 -0
- package/recipes/image-analysis-supabase/packages/backend/supabase/migrations/image_analysis.sql +42 -0
- package/recipes/image-analysis-supabase/recipe.json +57 -0
- package/recipes/image-analysis-supabase@latest.zip +0 -0
- package/recipes/image-analysis@latest.zip +0 -0
- package/recipes/image-generator/apps/native/src/features/image-generator/app/index.tsx +16 -2
- package/recipes/image-generator/apps/native/src/features/image-generator/components/image-model-selector.tsx +11 -5
- package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-generator.ts +11 -5
- package/recipes/image-generator/packages/backend/convex/imageGeneration/index.ts +2 -2
- package/recipes/image-generator/recipe.json +16 -39
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/_layout.tsx +26 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/index.tsx +251 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/gallery-image.tsx +25 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-model-selector.tsx +216 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator.ts +103 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/models/models.ts +66 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-gallery-service.ts +96 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-save-service.ts +120 -0
- package/recipes/image-generator-supabase/packages/backend/supabase/functions/generate-image/index.ts +291 -0
- package/recipes/image-generator-supabase/packages/backend/supabase/migrations/image_generator.sql +71 -0
- package/recipes/image-generator-supabase/recipe.json +59 -0
- package/recipes/image-generator-supabase@latest.zip +0 -0
- package/recipes/image-generator@latest.zip +0 -0
- package/recipes/ios-widget/recipe.json +15 -24
- package/recipes/ios-widget@latest.zip +0 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/analytics/index.ts +9 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding-with-analytics.tsx +141 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding.tsx +173 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/config/onboarding-flow-config.ts +189 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/app/index.tsx +42 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/data.ts +32 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/app/index.tsx +43 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +222 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +133 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +165 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +199 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +154 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +156 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +158 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +139 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +129 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +138 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +190 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +98 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +181 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +110 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +139 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +217 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +58 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/constants.ts +179 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/hooks/use-onboarding-analytics.ts +323 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/services/onboarding-analytics.ts +432 -0
- package/recipes/onboarding/recipe.json +15 -0
- package/recipes/onboarding@latest.zip +0 -0
- package/recipes/payments/recipe.json +28 -61
- package/recipes/payments-supabase/apps/native/src/features/payments/README.md +200 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/app/local-paywall.tsx +194 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/app/remote-paywall.tsx +79 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/payment-initializer.tsx +95 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-error-state.tsx +60 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-local-mode.tsx +116 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-product-card.tsx +133 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-remote-mode.tsx +146 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/hooks/use-entitlement.ts +63 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/index.ts +8 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/services/revenuecat-adapter.ts +407 -0
- package/recipes/payments-supabase/packages/backend/src/services/payments.ts +201 -0
- package/recipes/payments-supabase/packages/backend/supabase/migrations/payments.sql +35 -0
- package/recipes/payments-supabase/recipe.json +51 -0
- package/recipes/payments-supabase@latest.zip +0 -0
- package/recipes/payments@latest.zip +0 -0
- package/recipes/quiz/apps/native/src/features/quiz/index.tsx +1 -2
- package/recipes/quiz/recipe.json +6 -9
- package/recipes/quiz@latest.zip +0 -0
- package/recipes/tracker-app/apps/native/src/features/tracker-app/app/index.tsx +1 -2
- package/recipes/tracker-app/recipe.json +7 -10
- package/recipes/tracker-app@latest.zip +0 -0
- package/recipes/voice-bot/recipe.json +8 -68
- package/recipes/voice-bot.zip +0 -0
- package/recipes/voice-bot@latest.zip +0 -0
- package/recipes/wake-word/recipe.json +10 -9
- package/recipes/wake-word.zip +0 -0
- package/recipes/wake-word@latest.zip +0 -0
- package/recipes/charts/apps/native/src/app/(root)/(protected)/charts/index.tsx +0 -3
- package/recipes/chatbot/packages/backend/convex/lib/rateLimit.ts +0 -100
- package/recipes/chatbot/packages/backend/convex/lib/telemetry.ts +0 -29
- package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +0 -0
- package/recipes/image-analysis/apps/native/assets/features/image-analyzer/front.jpg +0 -0
- package/recipes/image-analysis/apps/native/assets/features/image-analyzer/side.jpg +0 -0
- package/recipes/image-analysis/apps/native/assets/features/image-analyzer/threeQuarter.jpg +0 -0
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/_layout.tsx +0 -5
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/analysis-options.tsx +0 -50
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/camera.tsx +0 -2
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/index.tsx +0 -50
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/loading.tsx +0 -50
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/results.tsx +0 -2
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/trait-details.tsx +0 -3
- package/recipes/image-analysis/packages/backend/convex/lib/ai/imageAnalysisAdapter.ts +0 -200
- package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/index.tsx +0 -74
- package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/local.tsx +0 -25
- package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/remote.tsx +0 -23
- package/recipes/quiz/apps/native/src/app/(root)/(protected)/quiz/index.tsx +0 -47
- package/recipes/tracker-app/apps/native/src/app/(root)/(protected)/tracker-app/index.tsx +0 -1
- package/recipes/voice-bot/apps/native/src/app/(root)/(protected)/voice-bot/index.tsx +0 -27
- package/recipes/voice-bot/packages/backend/convex/router.ts +0 -81
- /package/recipes/{chatbot/apps/native/src/app/(root)/(protected) → chatbot-supabase/apps/native/src/app}/chatbot/index.tsx +0 -0
- /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/gallery.tsx +0 -0
- /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/index.tsx +0 -0
|
@@ -96,44 +96,35 @@
|
|
|
96
96
|
"dependencies": {
|
|
97
97
|
"expo": ["@bacons/apple-targets"]
|
|
98
98
|
},
|
|
99
|
+
"plugins": [
|
|
100
|
+
{
|
|
101
|
+
"name": "@bacons/apple-targets",
|
|
102
|
+
"config": "{\n targets: [\n {\n name: 'VibeFastWidget',\n type: 'widget',\n bundleIdentifier: `${Env.BUNDLE_ID}.widget`,\n entitlements: {\n 'com.apple.security.application-groups': [\n `group.${Env.BUNDLE_ID}.shared`,\n ],\n },\n },\n ],\n }"
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"iosConfig": {
|
|
106
|
+
"appleTeamId": "Env.APPLE_TEAM_ID",
|
|
107
|
+
"entitlements": "{\n 'com.apple.security.application-groups': [`group.${Env.BUNDLE_ID}.shared`],\n }"
|
|
108
|
+
},
|
|
99
109
|
"env": [
|
|
100
110
|
{
|
|
101
111
|
"key": "APPLE_TEAM_ID",
|
|
102
112
|
"description": "Apple Developer Team ID (used to sign widgets).",
|
|
103
113
|
"example": "ABCDE12345",
|
|
104
114
|
"link": "https://developer.apple.com/account/#/membership",
|
|
105
|
-
"file": "apps/native
|
|
115
|
+
"file": "apps/native/env.js"
|
|
106
116
|
}
|
|
107
117
|
],
|
|
108
118
|
"configuration": {
|
|
109
119
|
"env": {
|
|
110
|
-
"constants": [
|
|
111
|
-
"const APPLE_TEAM_ID = 'replace_me';"
|
|
112
|
-
],
|
|
120
|
+
"constants": ["const APPLE_TEAM_ID = 'replace_me';"],
|
|
113
121
|
"buildTime": {
|
|
114
|
-
"schema": [
|
|
115
|
-
|
|
116
|
-
],
|
|
117
|
-
"env": [
|
|
118
|
-
" APPLE_TEAM_ID: process.env.APPLE_TEAM_ID,"
|
|
119
|
-
]
|
|
122
|
+
"schema": [" APPLE_TEAM_ID: z.string(),"],
|
|
123
|
+
"env": [" APPLE_TEAM_ID,"]
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
},
|
|
123
|
-
"manualSteps": [
|
|
124
|
-
{
|
|
125
|
-
"title": "Verify widget plugin",
|
|
126
|
-
"description": "The CLI adds the @bacons/apple-targets plugin automatically. Confirm it exists in app.config.ts.",
|
|
127
|
-
"file": "apps/native/app.config.ts",
|
|
128
|
-
"content": "[\n '@bacons/apple-targets',\n {\n targets: [\n {\n name: 'VibeFastWidget',\n type: 'widget',\n bundleIdentifier: `${Env.BUNDLE_ID}.widget`,\n entitlements: {\n 'com.apple.security.application-groups': [\n 'group.com.vibefast.vibefast',\n ],\n },\n },\n ],\n },\n]"
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"title": "Configure App Groups",
|
|
132
|
-
"description": "Ensure your main app has App Groups entitlements in app.config.ts",
|
|
133
|
-
"file": "apps/native/app.config.ts",
|
|
134
|
-
"content": "ios: {\n entitlements: {\n 'com.apple.security.application-groups': ['group.com.vibefast.shared'],\n },\n}"
|
|
135
|
-
}
|
|
136
|
-
],
|
|
127
|
+
"manualSteps": [],
|
|
137
128
|
"postInstall": {
|
|
138
129
|
"instructions": [
|
|
139
130
|
"Widget target files have been added",
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Export analytics service and types
|
|
2
|
+
|
|
3
|
+
// Export enhanced components
|
|
4
|
+
export * from '../components/onboarding-with-analytics';
|
|
5
|
+
// Export configuration
|
|
6
|
+
export * from '../config/onboarding-flow-config';
|
|
7
|
+
// Export React hooks
|
|
8
|
+
export * from '../hooks/use-onboarding-analytics';
|
|
9
|
+
export * from '../services/onboarding-analytics';
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React, { useCallback, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { MAIN_ONBOARDING_FLOW } from '../config/onboarding-flow-config';
|
|
4
|
+
import { useOnboardingAnalytics } from '../hooks/use-onboarding-analytics';
|
|
5
|
+
import { Onboarding } from './onboarding';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Props for the analytics-enabled onboarding component
|
|
9
|
+
*/
|
|
10
|
+
export type OnboardingWithAnalyticsProps = {
|
|
11
|
+
userType?: 'new' | 'returning' | 'migrated';
|
|
12
|
+
variant?: 'control' | 'experimental';
|
|
13
|
+
onComplete?: () => void;
|
|
14
|
+
onSkip?: () => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Enhanced onboarding component that automatically tracks user progress
|
|
19
|
+
* and behavior through the onboarding flow with PostHog analytics.
|
|
20
|
+
*
|
|
21
|
+
* This component wraps your existing Onboarding component and adds:
|
|
22
|
+
* - Automatic step tracking
|
|
23
|
+
* - Flow completion analytics
|
|
24
|
+
* - User abandonment detection
|
|
25
|
+
* - A/B test variant tracking
|
|
26
|
+
*
|
|
27
|
+
* Usage:
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <OnboardingWithAnalytics
|
|
30
|
+
* userType="new"
|
|
31
|
+
* variant="experimental"
|
|
32
|
+
* onComplete={() => router.push('/home')}
|
|
33
|
+
* />
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function OnboardingWithAnalytics({
|
|
37
|
+
userType = 'new',
|
|
38
|
+
variant,
|
|
39
|
+
onComplete,
|
|
40
|
+
onSkip,
|
|
41
|
+
}: OnboardingWithAnalyticsProps) {
|
|
42
|
+
// Get the appropriate flow configuration
|
|
43
|
+
const flowConfig = variant
|
|
44
|
+
? { ...MAIN_ONBOARDING_FLOW, variant }
|
|
45
|
+
: MAIN_ONBOARDING_FLOW;
|
|
46
|
+
|
|
47
|
+
// Initialize onboarding analytics
|
|
48
|
+
const analytics = useOnboardingAnalytics({
|
|
49
|
+
flowConfig,
|
|
50
|
+
userType,
|
|
51
|
+
autoStart: true, // Automatically start tracking when component mounts
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Track when component mounts (onboarding starts)
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
// Analytics are auto-started, but we can add additional properties
|
|
57
|
+
analytics.startFlow().then((sessionId) => {
|
|
58
|
+
console.log(`Onboarding session started: ${sessionId}`);
|
|
59
|
+
});
|
|
60
|
+
}, [analytics]);
|
|
61
|
+
|
|
62
|
+
// Enhanced completion handler with analytics
|
|
63
|
+
const handleComplete = useCallback(async () => {
|
|
64
|
+
await analytics.completeFlow();
|
|
65
|
+
onComplete?.();
|
|
66
|
+
}, [analytics, onComplete]);
|
|
67
|
+
|
|
68
|
+
// Enhanced skip handler with analytics (unused but kept for future use)
|
|
69
|
+
// const handleSkip = useCallback(async () => {
|
|
70
|
+
// await analytics.abandonFlow('user_skipped');
|
|
71
|
+
// onSkip?.();
|
|
72
|
+
// }, [analytics, onSkip]);
|
|
73
|
+
|
|
74
|
+
// Example handlers for step-level tracking (unused but kept for future use)
|
|
75
|
+
// const handleStepTransition = useCallback(
|
|
76
|
+
// async (stepId: string, action: 'viewed' | 'completed') => {
|
|
77
|
+
// if (action === 'viewed') {
|
|
78
|
+
// await analytics.trackStepViewed(stepId, {
|
|
79
|
+
// timestamp: new Date().toISOString(),
|
|
80
|
+
// user_type: userType,
|
|
81
|
+
// variant: variant || 'default',
|
|
82
|
+
// });
|
|
83
|
+
// } else if (action === 'completed') {
|
|
84
|
+
// await analytics.trackStepCompleted(stepId, {
|
|
85
|
+
// timestamp: new Date().toISOString(),
|
|
86
|
+
// interaction_method: 'button', // Could be 'swipe', 'tap', etc.
|
|
87
|
+
// });
|
|
88
|
+
// }
|
|
89
|
+
// },
|
|
90
|
+
// [analytics, userType, variant]
|
|
91
|
+
// );
|
|
92
|
+
|
|
93
|
+
// Pass enhanced handlers to your existing Onboarding component
|
|
94
|
+
// Note: You'll need to provide the actual onboarding data
|
|
95
|
+
return (
|
|
96
|
+
<Onboarding
|
|
97
|
+
data={
|
|
98
|
+
[
|
|
99
|
+
// Add your actual onboarding data here
|
|
100
|
+
// This is just a placeholder structure
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
onComplete={handleComplete}
|
|
104
|
+
testID="onboarding-with-analytics"
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Example of how to integrate with your demo screens:
|
|
111
|
+
* You can enhance your existing demo-one.tsx and demo-two.tsx files
|
|
112
|
+
* to include step tracking like this:
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
/*
|
|
116
|
+
// In your demo-one.tsx file:
|
|
117
|
+
export default function DemoOneScreen() {
|
|
118
|
+
const { trackStepViewed, trackStepCompleted } = useContext(OnboardingAnalyticsContext);
|
|
119
|
+
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
trackStepViewed('demo_one');
|
|
122
|
+
}, []);
|
|
123
|
+
|
|
124
|
+
const handleContinue = () => {
|
|
125
|
+
trackStepCompleted('demo_one', {
|
|
126
|
+
interaction_method: 'button',
|
|
127
|
+
time_spent_seconds: Math.floor((Date.now() - startTime) / 1000)
|
|
128
|
+
});
|
|
129
|
+
// Navigate to next step
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const handleSkip = () => {
|
|
133
|
+
trackStepSkipped('demo_one', 'user_choice');
|
|
134
|
+
// Skip to end or next step
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
// Your existing UI
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
*/
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import LottieView from 'lottie-react-native';
|
|
2
|
+
import React, { useRef, useState } from 'react';
|
|
3
|
+
import { Dimensions, View, type ViewToken } from 'react-native';
|
|
4
|
+
import Animated, {
|
|
5
|
+
useAnimatedScrollHandler,
|
|
6
|
+
useSharedValue,
|
|
7
|
+
} from 'react-native-reanimated';
|
|
8
|
+
|
|
9
|
+
import { Button, Text } from '@/components/ui';
|
|
10
|
+
import ScrollingPaginationDots from '@/components/ui/core/pagination-dots';
|
|
11
|
+
import { translate } from '@/lib';
|
|
12
|
+
import { useThemeConfig } from '@/lib/use-theme-config';
|
|
13
|
+
|
|
14
|
+
const { width: SCREEN_WIDTH } = Dimensions.get('window');
|
|
15
|
+
|
|
16
|
+
export type OnboardingItem = {
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
description: string;
|
|
20
|
+
lottieAnim: any; // Lottie animation source
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type OnboardingProps = {
|
|
24
|
+
data: OnboardingItem[];
|
|
25
|
+
onComplete: () => void;
|
|
26
|
+
testID?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Reusable Onboarding component with horizontal swipeable screens,
|
|
31
|
+
* Lottie animations, and progress dots
|
|
32
|
+
*/
|
|
33
|
+
export function Onboarding({ data, onComplete, testID }: OnboardingProps) {
|
|
34
|
+
const theme = useThemeConfig();
|
|
35
|
+
const scrollX = useSharedValue(0);
|
|
36
|
+
const flatListRef = useRef<Animated.FlatList<OnboardingItem>>(null);
|
|
37
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
38
|
+
|
|
39
|
+
const handleScroll = useAnimatedScrollHandler((event) => {
|
|
40
|
+
scrollX.value = event.contentOffset.x;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const onViewableItemsChanged = ({
|
|
44
|
+
viewableItems,
|
|
45
|
+
}: {
|
|
46
|
+
viewableItems: ViewToken[];
|
|
47
|
+
}) => {
|
|
48
|
+
if (viewableItems.length > 0) {
|
|
49
|
+
const index = viewableItems[0].index || 0;
|
|
50
|
+
setCurrentIndex(index);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const handleNext = () => {
|
|
55
|
+
if (currentIndex < data.length - 1) {
|
|
56
|
+
flatListRef.current?.scrollToIndex({
|
|
57
|
+
index: currentIndex + 1,
|
|
58
|
+
animated: true,
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
onComplete();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const handleSkip = () => {
|
|
66
|
+
onComplete();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const renderItem = ({ item }: { item: OnboardingItem }) => (
|
|
70
|
+
<View
|
|
71
|
+
style={{ width: SCREEN_WIDTH }}
|
|
72
|
+
className="flex-1 items-center justify-center px-8"
|
|
73
|
+
>
|
|
74
|
+
{/* Lottie Animation */}
|
|
75
|
+
<View className="h-80 w-full items-center justify-center">
|
|
76
|
+
<LottieView
|
|
77
|
+
source={item.lottieAnim}
|
|
78
|
+
autoPlay
|
|
79
|
+
loop
|
|
80
|
+
style={{
|
|
81
|
+
width: 250,
|
|
82
|
+
height: 250,
|
|
83
|
+
}}
|
|
84
|
+
testID={`${testID}-lottie-${item.id}`}
|
|
85
|
+
/>
|
|
86
|
+
</View>
|
|
87
|
+
|
|
88
|
+
{/* Title */}
|
|
89
|
+
<Text
|
|
90
|
+
className="my-4 text-center text-4xl font-bold"
|
|
91
|
+
testID={`${testID}-title-${item.id}`}
|
|
92
|
+
>
|
|
93
|
+
{item.title}
|
|
94
|
+
</Text>
|
|
95
|
+
|
|
96
|
+
{/* Description */}
|
|
97
|
+
<Text
|
|
98
|
+
className="text-center text-lg leading-6"
|
|
99
|
+
style={{ color: theme.colors.mutedForeground }}
|
|
100
|
+
testID={`${testID}-description-${item.id}`}
|
|
101
|
+
>
|
|
102
|
+
{item.description}
|
|
103
|
+
</Text>
|
|
104
|
+
</View>
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const isLastSlide = currentIndex === data.length - 1;
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<View className="flex-1" testID={testID}>
|
|
111
|
+
{/* Main Content */}
|
|
112
|
+
<View className="flex-1">
|
|
113
|
+
<Animated.FlatList
|
|
114
|
+
ref={flatListRef}
|
|
115
|
+
data={data}
|
|
116
|
+
keyExtractor={(item) => item.id}
|
|
117
|
+
renderItem={renderItem}
|
|
118
|
+
horizontal
|
|
119
|
+
pagingEnabled
|
|
120
|
+
showsHorizontalScrollIndicator={false}
|
|
121
|
+
onScroll={handleScroll}
|
|
122
|
+
onViewableItemsChanged={onViewableItemsChanged}
|
|
123
|
+
viewabilityConfig={{
|
|
124
|
+
itemVisiblePercentThreshold: 50,
|
|
125
|
+
}}
|
|
126
|
+
scrollEventThrottle={16}
|
|
127
|
+
testID={`${testID}-flatlist`}
|
|
128
|
+
/>
|
|
129
|
+
</View>
|
|
130
|
+
|
|
131
|
+
{/* Progress Dots */}
|
|
132
|
+
<View className="items-center py-6">
|
|
133
|
+
<ScrollingPaginationDots
|
|
134
|
+
count={data.length}
|
|
135
|
+
scrollX={scrollX}
|
|
136
|
+
slideWidth={SCREEN_WIDTH}
|
|
137
|
+
dotColor={theme.colors.primary}
|
|
138
|
+
inactiveDotColor={theme.colors.mutedForeground}
|
|
139
|
+
dotSize={10}
|
|
140
|
+
spacing={12}
|
|
141
|
+
inactiveDotOpacity={0.3}
|
|
142
|
+
maxVisibleDots={5}
|
|
143
|
+
/>
|
|
144
|
+
</View>
|
|
145
|
+
|
|
146
|
+
{/* Action Buttons */}
|
|
147
|
+
<View className="flex-row items-center justify-between px-8 pb-8">
|
|
148
|
+
<Button
|
|
149
|
+
variant="ghost"
|
|
150
|
+
label={translate('onboarding.skip')}
|
|
151
|
+
onPress={handleSkip}
|
|
152
|
+
testID={`${testID}-skip-button`}
|
|
153
|
+
className="flex-1"
|
|
154
|
+
/>
|
|
155
|
+
|
|
156
|
+
<View className="w-4" />
|
|
157
|
+
|
|
158
|
+
<Button
|
|
159
|
+
label={
|
|
160
|
+
isLastSlide
|
|
161
|
+
? translate('onboarding.get_started')
|
|
162
|
+
: translate('onboarding.next')
|
|
163
|
+
}
|
|
164
|
+
onPress={handleNext}
|
|
165
|
+
testID={`${testID}-${isLastSlide ? 'complete' : 'next'}-button`}
|
|
166
|
+
className="flex-1"
|
|
167
|
+
/>
|
|
168
|
+
</View>
|
|
169
|
+
</View>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export default Onboarding;
|
package/recipes/onboarding/apps/native/src/features/onboarding/config/onboarding-flow-config.ts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { OnboardingFlowConfig } from '../services/onboarding-analytics';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Demo One: Multi-step animated onboarding flow
|
|
5
|
+
* A comprehensive onboarding with multiple screens and Lottie animations
|
|
6
|
+
*/
|
|
7
|
+
export const DEMO_ONE_ONBOARDING_FLOW: OnboardingFlowConfig = {
|
|
8
|
+
flowId: 'demo_one_flow',
|
|
9
|
+
flowName: 'Multi-Step Animated Onboarding',
|
|
10
|
+
version: '1.0',
|
|
11
|
+
steps: [
|
|
12
|
+
{
|
|
13
|
+
id: 'welcome_screen',
|
|
14
|
+
name: 'Welcome to VibeFast',
|
|
15
|
+
index: 0,
|
|
16
|
+
category: 'intro',
|
|
17
|
+
isOptional: false,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'ai_features',
|
|
21
|
+
name: 'AI-Powered Development',
|
|
22
|
+
index: 1,
|
|
23
|
+
category: 'features',
|
|
24
|
+
isOptional: false,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'production_ready',
|
|
28
|
+
name: 'Production Ready',
|
|
29
|
+
index: 2,
|
|
30
|
+
category: 'features',
|
|
31
|
+
isOptional: false,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'developer_experience',
|
|
35
|
+
name: 'Developer Experience',
|
|
36
|
+
index: 3,
|
|
37
|
+
category: 'features',
|
|
38
|
+
isOptional: false,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Demo Two: Simple single-screen onboarding
|
|
45
|
+
* A minimal onboarding with feature highlights and direct CTA
|
|
46
|
+
*/
|
|
47
|
+
export const DEMO_TWO_ONBOARDING_FLOW: OnboardingFlowConfig = {
|
|
48
|
+
flowId: 'demo_two_flow',
|
|
49
|
+
flowName: 'Simple Feature Highlights Onboarding',
|
|
50
|
+
version: '1.0',
|
|
51
|
+
steps: [
|
|
52
|
+
{
|
|
53
|
+
id: 'feature_overview',
|
|
54
|
+
name: 'Feature Overview Screen',
|
|
55
|
+
index: 0,
|
|
56
|
+
category: 'overview',
|
|
57
|
+
isOptional: false,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Feature-specific onboarding flows for different parts of your app
|
|
64
|
+
*/
|
|
65
|
+
export const FEATURE_ONBOARDING_FLOWS = {
|
|
66
|
+
imageAnalyzer: {
|
|
67
|
+
flowId: 'image_analyzer_onboarding',
|
|
68
|
+
flowName: 'Image Analyzer Onboarding',
|
|
69
|
+
version: '1.0',
|
|
70
|
+
steps: [
|
|
71
|
+
{
|
|
72
|
+
id: 'camera_permission',
|
|
73
|
+
name: 'Camera Permission Request',
|
|
74
|
+
index: 0,
|
|
75
|
+
category: 'permissions',
|
|
76
|
+
isOptional: false,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'first_analysis',
|
|
80
|
+
name: 'First Image Analysis',
|
|
81
|
+
index: 1,
|
|
82
|
+
category: 'tutorial',
|
|
83
|
+
isOptional: false,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: 'results_explanation',
|
|
87
|
+
name: 'Understanding Results',
|
|
88
|
+
index: 2,
|
|
89
|
+
category: 'tutorial',
|
|
90
|
+
isOptional: true,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
payments: {
|
|
95
|
+
flowId: 'payments_onboarding',
|
|
96
|
+
flowName: 'Premium Features Onboarding',
|
|
97
|
+
version: '1.0',
|
|
98
|
+
steps: [
|
|
99
|
+
{
|
|
100
|
+
id: 'paywall_intro',
|
|
101
|
+
name: 'Premium Features Introduction',
|
|
102
|
+
index: 0,
|
|
103
|
+
category: 'monetization',
|
|
104
|
+
isOptional: false,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'subscription_selection',
|
|
108
|
+
name: 'Subscription Plan Selection',
|
|
109
|
+
index: 1,
|
|
110
|
+
category: 'monetization',
|
|
111
|
+
isOptional: false,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'payment_completion',
|
|
115
|
+
name: 'Payment Completion',
|
|
116
|
+
index: 2,
|
|
117
|
+
category: 'monetization',
|
|
118
|
+
isOptional: false,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
} as const satisfies Record<string, OnboardingFlowConfig>;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* A/B test variants for different onboarding approaches
|
|
126
|
+
*/
|
|
127
|
+
export const ONBOARDING_VARIANTS = {
|
|
128
|
+
demoOneControl: {
|
|
129
|
+
...DEMO_ONE_ONBOARDING_FLOW,
|
|
130
|
+
variant: 'control',
|
|
131
|
+
},
|
|
132
|
+
demoOneExperimental: {
|
|
133
|
+
...DEMO_ONE_ONBOARDING_FLOW,
|
|
134
|
+
flowId: 'demo_one_flow_experimental',
|
|
135
|
+
variant: 'experimental',
|
|
136
|
+
// Add experimental steps or modify existing ones
|
|
137
|
+
steps: [
|
|
138
|
+
...DEMO_ONE_ONBOARDING_FLOW.steps,
|
|
139
|
+
{
|
|
140
|
+
id: 'personalization_survey',
|
|
141
|
+
name: 'Quick Personalization Survey',
|
|
142
|
+
index: 4,
|
|
143
|
+
category: 'personalization',
|
|
144
|
+
isOptional: true,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
demoTwoControl: {
|
|
149
|
+
...DEMO_TWO_ONBOARDING_FLOW,
|
|
150
|
+
variant: 'control',
|
|
151
|
+
},
|
|
152
|
+
demoTwoExperimental: {
|
|
153
|
+
...DEMO_TWO_ONBOARDING_FLOW,
|
|
154
|
+
flowId: 'demo_two_flow_experimental',
|
|
155
|
+
variant: 'experimental',
|
|
156
|
+
// Could add more steps to test if single-screen vs multi-screen performs better
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Helper function to get onboarding flow config based on choice and variant
|
|
162
|
+
*/
|
|
163
|
+
export function getOnboardingFlowConfig(
|
|
164
|
+
flowType: 'demoOne' | 'demoTwo' | 'imageAnalyzer' | 'payments' = 'demoOne',
|
|
165
|
+
variant?: 'control' | 'experimental',
|
|
166
|
+
): OnboardingFlowConfig {
|
|
167
|
+
if (flowType === 'demoOne') {
|
|
168
|
+
if (variant === 'experimental') {
|
|
169
|
+
return ONBOARDING_VARIANTS.demoOneExperimental;
|
|
170
|
+
}
|
|
171
|
+
return variant
|
|
172
|
+
? ONBOARDING_VARIANTS.demoOneControl
|
|
173
|
+
: DEMO_ONE_ONBOARDING_FLOW;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (flowType === 'demoTwo') {
|
|
177
|
+
if (variant === 'experimental') {
|
|
178
|
+
return ONBOARDING_VARIANTS.demoTwoExperimental;
|
|
179
|
+
}
|
|
180
|
+
return variant
|
|
181
|
+
? ONBOARDING_VARIANTS.demoTwoControl
|
|
182
|
+
: DEMO_TWO_ONBOARDING_FLOW;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return FEATURE_ONBOARDING_FLOWS[flowType];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Export the main flows for easy access
|
|
189
|
+
export const MAIN_ONBOARDING_FLOW = DEMO_ONE_ONBOARDING_FLOW; // Default export for backward compatibility
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useLocalSearchParams, useRouter } from 'expo-router';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { FocusAwareStatusBar, SafeAreaView } from '@/components/ui';
|
|
5
|
+
import { useIsFirstTime } from '@/lib/hooks';
|
|
6
|
+
|
|
7
|
+
import { Onboarding } from '../../components/onboarding';
|
|
8
|
+
import { AppOnboardingData } from '../data';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Demo One Onboarding Screen
|
|
12
|
+
* Displays the new multi-step onboarding flow with animations
|
|
13
|
+
*/
|
|
14
|
+
export default function DemoOneOnboarding() {
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const params = useLocalSearchParams<{ returnTo?: string }>();
|
|
17
|
+
const [, completeOnboarding] = useIsFirstTime();
|
|
18
|
+
|
|
19
|
+
const handleComplete = () => {
|
|
20
|
+
console.log('[DemoOneOnboarding] Completing onboarding…');
|
|
21
|
+
completeOnboarding(); // ← writes flag & flushes
|
|
22
|
+
const returnTo = params.returnTo as string | undefined;
|
|
23
|
+
if (returnTo) {
|
|
24
|
+
console.log(`[DemoOneOnboarding] Returning to ${returnTo}…`);
|
|
25
|
+
router.replace(returnTo as any);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
console.log('[DemoOneOnboarding] Navigating to login…');
|
|
29
|
+
router.replace('/(auth)/login'); // default behavior
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<SafeAreaView className="flex-1">
|
|
34
|
+
<FocusAwareStatusBar />
|
|
35
|
+
<Onboarding
|
|
36
|
+
data={AppOnboardingData}
|
|
37
|
+
onComplete={handleComplete}
|
|
38
|
+
testID="demo-one-onboarding"
|
|
39
|
+
/>
|
|
40
|
+
</SafeAreaView>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { OnboardingItem } from '../components/onboarding';
|
|
2
|
+
|
|
3
|
+
export const AppOnboardingData: OnboardingItem[] = [
|
|
4
|
+
{
|
|
5
|
+
id: '1',
|
|
6
|
+
title: 'Welcome to VibeFast',
|
|
7
|
+
description:
|
|
8
|
+
'Build and ship your React Native apps faster with our production-ready starter kit. Save weeks of development time with our proven architecture.',
|
|
9
|
+
lottieAnim: require('@assets/lottie-animations/onboarding-1.json'),
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: '2',
|
|
13
|
+
title: 'AI-Powered Development',
|
|
14
|
+
description:
|
|
15
|
+
'Leverage cutting-edge AI features built right into your app. From chatbots to image analysis, everything is ready to use out of the box.',
|
|
16
|
+
lottieAnim: require('@assets/lottie-animations/onboarding-2.json'),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: '3',
|
|
20
|
+
title: 'Production Ready',
|
|
21
|
+
description:
|
|
22
|
+
'Complete with authentication, payments, push notifications, and more. Deploy to the App Store and Google Play with confidence.',
|
|
23
|
+
lottieAnim: require('@assets/lottie-animations/onboarding-3.json'),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: '4',
|
|
27
|
+
title: 'Developer Experience',
|
|
28
|
+
description:
|
|
29
|
+
'TypeScript, Testing, Linting, and CI/CD all configured. Focus on building features, not setting up tooling.',
|
|
30
|
+
lottieAnim: require('@assets/lottie-animations/onboarding-4.json'),
|
|
31
|
+
},
|
|
32
|
+
];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expense Tracker Demo Onboarding Screen
|
|
3
|
+
* Entry point that wraps InteractiveOnboarding with navigation handling.
|
|
4
|
+
*/
|
|
5
|
+
import { useLocalSearchParams, useRouter } from 'expo-router';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { View } from 'react-native';
|
|
8
|
+
|
|
9
|
+
import { FocusAwareStatusBar } from '@/components/ui';
|
|
10
|
+
import { useIsFirstTime } from '@/lib/hooks';
|
|
11
|
+
|
|
12
|
+
import { InteractiveOnboarding } from '../components/interactive-onboarding';
|
|
13
|
+
|
|
14
|
+
export default function ExpenseTrackerOnboarding() {
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const params = useLocalSearchParams<{ returnTo?: string }>();
|
|
17
|
+
const [, completeOnboarding] = useIsFirstTime();
|
|
18
|
+
|
|
19
|
+
const handleComplete = () => {
|
|
20
|
+
completeOnboarding();
|
|
21
|
+
const returnTo = params.returnTo as string | undefined;
|
|
22
|
+
if (returnTo) {
|
|
23
|
+
router.replace(returnTo as any);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
router.replace('/(auth)/welcome-signup');
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const handleSignIn = () => {
|
|
30
|
+
completeOnboarding();
|
|
31
|
+
router.replace('/(auth)/login');
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<View className="flex-1 bg-background">
|
|
36
|
+
<FocusAwareStatusBar />
|
|
37
|
+
<InteractiveOnboarding
|
|
38
|
+
onComplete={handleComplete}
|
|
39
|
+
onSignIn={handleSignIn}
|
|
40
|
+
/>
|
|
41
|
+
</View>
|
|
42
|
+
);
|
|
43
|
+
}
|