@funnelsgrove/cli 0.1.14 → 0.1.18
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/contracts/step-contract-v2.json +733 -0
- package/dist/analyticsOutput.d.ts +30 -15
- package/dist/analyticsOutput.js +45 -28
- package/dist/apiClient.d.ts +85 -0
- package/dist/apiClient.js +225 -8
- package/dist/cli.d.ts +149 -1
- package/dist/cli.js +1232 -71
- package/dist/diagnosticOutput.d.ts +42 -0
- package/dist/diagnosticOutput.js +83 -0
- package/dist/docsOutput.d.ts +19 -0
- package/dist/docsOutput.js +73 -0
- package/dist/docsTransaction.d.ts +81 -0
- package/dist/docsTransaction.js +1755 -0
- package/dist/funnelValidation.d.ts +14 -0
- package/dist/funnelValidation.js +297 -0
- package/dist/localSync.d.ts +79 -0
- package/dist/localSync.js +428 -53
- package/dist/projectValidator.d.ts +27 -0
- package/dist/projectValidator.js +208 -0
- package/dist/reskin.js +27 -1
- package/dist/stepContractMigration.d.ts +71 -0
- package/dist/stepContractMigration.js +1323 -0
- package/dist/templateDocs.js +8 -25
- package/docs-release-history.json +66 -0
- package/legacy-docs-catalog.json +1012 -0
- package/package.json +13 -4
- package/template_docs/.funnelsgrove-docs.json +144 -0
- package/template_docs/AGENTS.md +30 -58
- package/template_docs/CLAUDE.md +0 -2
- package/template_docs/docs/funnelsgrove/START-HERE.md +73 -0
- package/template_docs/docs/funnelsgrove/contracts/analytics-events.md +59 -0
- package/template_docs/docs/funnelsgrove/contracts/content-answers.md +44 -0
- package/template_docs/docs/funnelsgrove/contracts/flow-routing.md +41 -0
- package/template_docs/docs/funnelsgrove/contracts/payments.md +42 -0
- package/template_docs/docs/funnelsgrove/contracts/step-metadata.md +57 -0
- package/template_docs/docs/funnelsgrove/migrations/step-contract-v3.md +39 -0
- package/template_docs/docs/funnelsgrove/qa/analytics.md +43 -0
- package/template_docs/docs/funnelsgrove/qa/local.md +42 -0
- package/template_docs/docs/funnelsgrove/qa/paywall-checkout.md +55 -0
- package/template_docs/docs/funnelsgrove/qa/publish.md +32 -0
- package/template_docs/docs/funnelsgrove/recipes/add-experiment.md +34 -0
- package/template_docs/docs/funnelsgrove/recipes/add-step.md +33 -0
- package/template_docs/docs/funnelsgrove/recipes/edit-step.md +31 -0
- package/template_docs/docs/funnelsgrove/steps/INDEX.md +26 -0
- package/template_docs/docs/funnelsgrove/steps/cancellation_offer.md +112 -0
- package/template_docs/docs/funnelsgrove/steps/checkout.md +120 -0
- package/template_docs/docs/funnelsgrove/steps/form_input.md +115 -0
- package/template_docs/docs/funnelsgrove/steps/intro_hero.md +110 -0
- package/template_docs/docs/funnelsgrove/steps/multi_select_choice.md +123 -0
- package/template_docs/docs/funnelsgrove/steps/paywall_offer.md +115 -0
- package/template_docs/docs/funnelsgrove/steps/progress_interstitial.md +111 -0
- package/template_docs/docs/funnelsgrove/steps/purchase_completed.md +117 -0
- package/template_docs/docs/funnelsgrove/steps/single_step_choice.md +122 -0
- package/template_docs/docs/funnelsgrove/steps/single_step_choice_emoji.md +122 -0
- package/template_docs/docs/funnelsgrove/steps/social_proof.md +110 -0
- package/template_docs/docs/funnelsgrove/steps/subscription_handoff.md +113 -0
- package/template_docs/docs/funnelsgrove/steps/subscription_management.md +112 -0
- package/template_docs/docs/funnelsgrove/steps/summary_confirmation.md +110 -0
- package/template_docs/docs/funnelsgrove/steps/upsell_offer.md +112 -0
- package/template_docs/docs/funnelsgrove/steps/value_prop_story.md +110 -0
- package/template_docs/funnel-docs.config.json +43 -0
- package/template_scaffold/.env.example +41 -0
- package/template_scaffold/.funnelsgrove-contract-tools.json +19 -0
- package/template_scaffold/.funnelsgrove-docs.json +144 -0
- package/template_scaffold/.funnelsgrove-scaffold.json +1078 -0
- package/template_scaffold/AGENTS.md +42 -0
- package/template_scaffold/CLAUDE.md +1 -0
- package/template_scaffold/PLAN.md +81 -0
- package/template_scaffold/PRODUCT_SENSE.md +28 -0
- package/template_scaffold/context/build-context.md +34 -0
- package/template_scaffold/docs/AGENT_FUNNEL_IMPLEMENTATION_SPEC.md +5 -0
- package/template_scaffold/docs/ARCHITECTURE.md +5 -0
- package/template_scaffold/docs/FLOW_CONFIG_AND_ROUTING.md +5 -0
- package/template_scaffold/docs/PAYWALL_AND_PAYMENTS.md +5 -0
- package/template_scaffold/docs/README.md +5 -0
- package/template_scaffold/docs/funnelsgrove/START-HERE.md +73 -0
- package/template_scaffold/docs/funnelsgrove/contracts/analytics-events.md +59 -0
- package/template_scaffold/docs/funnelsgrove/contracts/content-answers.md +44 -0
- package/template_scaffold/docs/funnelsgrove/contracts/flow-routing.md +41 -0
- package/template_scaffold/docs/funnelsgrove/contracts/payments.md +42 -0
- package/template_scaffold/docs/funnelsgrove/contracts/step-metadata.md +57 -0
- package/template_scaffold/docs/funnelsgrove/migrations/step-contract-v3.md +39 -0
- package/template_scaffold/docs/funnelsgrove/qa/analytics.md +43 -0
- package/template_scaffold/docs/funnelsgrove/qa/local.md +42 -0
- package/template_scaffold/docs/funnelsgrove/qa/paywall-checkout.md +55 -0
- package/template_scaffold/docs/funnelsgrove/qa/publish.md +32 -0
- package/template_scaffold/docs/funnelsgrove/recipes/add-experiment.md +34 -0
- package/template_scaffold/docs/funnelsgrove/recipes/add-step.md +33 -0
- package/template_scaffold/docs/funnelsgrove/recipes/edit-step.md +31 -0
- package/template_scaffold/docs/funnelsgrove/steps/INDEX.md +26 -0
- package/template_scaffold/docs/funnelsgrove/steps/cancellation_offer.md +112 -0
- package/template_scaffold/docs/funnelsgrove/steps/checkout.md +120 -0
- package/template_scaffold/docs/funnelsgrove/steps/form_input.md +115 -0
- package/template_scaffold/docs/funnelsgrove/steps/intro_hero.md +110 -0
- package/template_scaffold/docs/funnelsgrove/steps/multi_select_choice.md +123 -0
- package/template_scaffold/docs/funnelsgrove/steps/paywall_offer.md +115 -0
- package/template_scaffold/docs/funnelsgrove/steps/progress_interstitial.md +111 -0
- package/template_scaffold/docs/funnelsgrove/steps/purchase_completed.md +117 -0
- package/template_scaffold/docs/funnelsgrove/steps/single_step_choice.md +122 -0
- package/template_scaffold/docs/funnelsgrove/steps/single_step_choice_emoji.md +122 -0
- package/template_scaffold/docs/funnelsgrove/steps/social_proof.md +110 -0
- package/template_scaffold/docs/funnelsgrove/steps/subscription_handoff.md +113 -0
- package/template_scaffold/docs/funnelsgrove/steps/subscription_management.md +112 -0
- package/template_scaffold/docs/funnelsgrove/steps/summary_confirmation.md +110 -0
- package/template_scaffold/docs/funnelsgrove/steps/upsell_offer.md +112 -0
- package/template_scaffold/docs/funnelsgrove/steps/value_prop_story.md +110 -0
- package/template_scaffold/docs/references/funnel-sdk-user-answers.md +5 -0
- package/template_scaffold/eslint.config.mjs +16 -0
- package/template_scaffold/funnel-agent-docs.test.ts +699 -0
- package/template_scaffold/funnel-docs.config.json +43 -0
- package/template_scaffold/funnel.config.json +5 -0
- package/template_scaffold/gitignore.template +5 -0
- package/template_scaffold/next-env.d.ts +6 -0
- package/template_scaffold/next.config.ts +53 -0
- package/template_scaffold/package-lock.json +7737 -0
- package/template_scaffold/package.json +37 -0
- package/template_scaffold/package.test.ts +23 -0
- package/template_scaffold/public/claimbee/bee.png +0 -0
- package/template_scaffold/public/claimbee/device-iphone.png +0 -0
- package/template_scaffold/public/claimbee/device-macbook.png +0 -0
- package/template_scaffold/public/claimbee/device-none.png +0 -0
- package/template_scaffold/public/claimbee/device-watch.png +0 -0
- package/template_scaffold/public/claimbee/glow.svg +3 -0
- package/template_scaffold/public/claimbee/steps-sprite-alt.png +0 -0
- package/template_scaffold/public/claimbee/steps-sprite-default.png +0 -0
- package/template_scaffold/public/claimbee/testimonial-avatar.png +0 -0
- package/template_scaffold/public/claimbee/testimonial-star.svg +3 -0
- package/template_scaffold/public/paywall/ai-claim-assistant.png +0 -0
- package/template_scaffold/public/paywall/claim-history.png +0 -0
- package/template_scaffold/public/paywall/clear-progress.png +0 -0
- package/template_scaffold/public/paywall/hero.png +0 -0
- package/template_scaffold/public/paywall/money-alerts.png +0 -0
- package/template_scaffold/public/paywall/money-back-badge.png +0 -0
- package/template_scaffold/public/paywall/paywall-image.png +0 -0
- package/template_scaffold/public/paywall/r1.png +0 -0
- package/template_scaffold/public/paywall/r2.png +0 -0
- package/template_scaffold/public/paywall/r3.png +0 -0
- package/template_scaffold/public/paywall/r4.png +0 -0
- package/template_scaffold/public/paywall/r5.png +0 -0
- package/template_scaffold/public/paywall/r6.png +0 -0
- package/template_scaffold/public/paywall/special-offer-gift.png +0 -0
- package/template_scaffold/public/please/bee.png +0 -0
- package/template_scaffold/public/please/device-iphone.png +0 -0
- package/template_scaffold/public/please/device-macbook.png +0 -0
- package/template_scaffold/public/please/device-none.png +0 -0
- package/template_scaffold/public/please/device-watch.png +0 -0
- package/template_scaffold/public/please/glow.svg +3 -0
- package/template_scaffold/public/please/steps-sprite-alt.png +0 -0
- package/template_scaffold/public/please/steps-sprite-default.png +0 -0
- package/template_scaffold/public/please/testimonial-avatar.png +0 -0
- package/template_scaffold/public/please/testimonial-star.svg +3 -0
- package/template_scaffold/public/upsell/upgrade-hero.png +0 -0
- package/template_scaffold/src/app/[stepId]/page.test.tsx +59 -0
- package/template_scaffold/src/app/[stepId]/page.tsx +62 -0
- package/template_scaffold/src/app/globals.css +49 -0
- package/template_scaffold/src/app/layout.test.ts +26 -0
- package/template_scaffold/src/app/layout.tsx +61 -0
- package/template_scaffold/src/app/page.tsx +8 -0
- package/template_scaffold/src/app/sdk/page.tsx +673 -0
- package/template_scaffold/src/app/subscription-dashboard/page.tsx +274 -0
- package/template_scaffold/src/assets/claimbee/bee.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-iphone.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-macbook.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-none.png +0 -0
- package/template_scaffold/src/assets/claimbee/device-watch.png +0 -0
- package/template_scaffold/src/assets/claimbee/glow.svg +3 -0
- package/template_scaffold/src/assets/claimbee/steps-sprite-alt.png +0 -0
- package/template_scaffold/src/assets/claimbee/steps-sprite-default.png +0 -0
- package/template_scaffold/src/assets/claimbee/testimonial-avatar.png +0 -0
- package/template_scaffold/src/assets/claimbee/testimonial-star.svg +3 -0
- package/template_scaffold/src/components/FunnelEditorPanel.tsx +194 -0
- package/template_scaffold/src/components/FunnelFlow.test.tsx +17 -0
- package/template_scaffold/src/components/FunnelFlow.tsx +114 -0
- package/template_scaffold/src/components/FunnelStepImage.test.ts +15 -0
- package/template_scaffold/src/components/FunnelStepImage.tsx +28 -0
- package/template_scaffold/src/components/step/FunnelStepHeader.tsx +35 -0
- package/template_scaffold/src/config/billing.plans.test.ts +143 -0
- package/template_scaffold/src/config/billing.plans.ts +69 -0
- package/template_scaffold/src/config/billing.test.plans.ts +32 -0
- package/template_scaffold/src/config/experiments.generated.ts +4 -0
- package/template_scaffold/src/config/experiments.test.ts +12 -0
- package/template_scaffold/src/config/experiments.ts +9 -0
- package/template_scaffold/src/config/funnel.config.ts +12 -0
- package/template_scaffold/src/config/funnel.manifest.test.ts +166 -0
- package/template_scaffold/src/config/funnel.manifest.ts +139 -0
- package/template_scaffold/src/config/offer-sets.generated.ts +4 -0
- package/template_scaffold/src/contract/funnel-project.validation.test.ts +80 -0
- package/template_scaffold/src/contract/funnel-project.validation.ts +44 -0
- package/template_scaffold/src/contract/funnel-validator.vite.config.ts +11 -0
- package/template_scaffold/src/contract/golden/cancellation_offer.fixture.ts +29 -0
- package/template_scaffold/src/contract/golden/checkout.fixture.ts +37 -0
- package/template_scaffold/src/contract/golden/form_input.fixture.ts +28 -0
- package/template_scaffold/src/contract/golden/golden-fixtures.test.ts +190 -0
- package/template_scaffold/src/contract/golden/intro_hero.fixture.ts +27 -0
- package/template_scaffold/src/contract/golden/multi_select_choice.fixture.ts +37 -0
- package/template_scaffold/src/contract/golden/paywall_offer.fixture.ts +30 -0
- package/template_scaffold/src/contract/golden/progress_interstitial.fixture.ts +28 -0
- package/template_scaffold/src/contract/golden/purchase_completed.fixture.ts +33 -0
- package/template_scaffold/src/contract/golden/single_step_choice.fixture.ts +36 -0
- package/template_scaffold/src/contract/golden/single_step_choice_emoji.fixture.ts +36 -0
- package/template_scaffold/src/contract/golden/social_proof.fixture.ts +27 -0
- package/template_scaffold/src/contract/golden/subscription_handoff.fixture.ts +30 -0
- package/template_scaffold/src/contract/golden/subscription_management.fixture.ts +29 -0
- package/template_scaffold/src/contract/golden/summary_confirmation.fixture.ts +27 -0
- package/template_scaffold/src/contract/golden/upsell_offer.fixture.ts +29 -0
- package/template_scaffold/src/contract/golden/value_prop_story.fixture.ts +27 -0
- package/template_scaffold/src/contract/validate-funnel.cli.test.ts +180 -0
- package/template_scaffold/src/contract/validate-funnel.cli.ts +199 -0
- package/template_scaffold/src/runtime/checkout-runtime-config.test.ts +60 -0
- package/template_scaffold/src/runtime/checkout-runtime-config.ts +26 -0
- package/template_scaffold/src/runtime/funnel-runtime.test.ts +25 -0
- package/template_scaffold/src/runtime/funnel-runtime.ts +118 -0
- package/template_scaffold/src/runtime/step-content-context.test.ts +38 -0
- package/template_scaffold/src/runtime/step-content-context.ts +65 -0
- package/template_scaffold/src/runtime/step-registry.ts +66 -0
- package/template_scaffold/src/runtime/step-variable-values.ts +31 -0
- package/template_scaffold/src/runtime/use-funnel-flow-controller.integration.test.ts +203 -0
- package/template_scaffold/src/runtime/use-funnel-flow-controller.test.ts +76 -0
- package/template_scaffold/src/runtime/use-funnel-flow-controller.ts +53 -0
- package/template_scaffold/src/steps/content/email-capture.content.ts +29 -0
- package/template_scaffold/src/steps/content/manage-subscription.content.ts +62 -0
- package/template_scaffold/src/steps/content/paywall.content.ts +191 -0
- package/template_scaffold/src/steps/content/step-01.content.ts +23 -0
- package/template_scaffold/src/steps/content/step-02.content.ts +77 -0
- package/template_scaffold/src/steps/content/step-03.content.ts +40 -0
- package/template_scaffold/src/steps/content/step-04.content.ts +49 -0
- package/template_scaffold/src/steps/content/step-32-paywall.content.ts +352 -0
- package/template_scaffold/src/steps/content/subscription-started.content.ts +68 -0
- package/template_scaffold/src/steps/editor/email-capture.editor.ts +58 -0
- package/template_scaffold/src/steps/editor/manage-subscription.editor.ts +179 -0
- package/template_scaffold/src/steps/editor/paywall.editor.ts +232 -0
- package/template_scaffold/src/steps/editor/step-01.editor.ts +22 -0
- package/template_scaffold/src/steps/editor/step-02.editor.ts +41 -0
- package/template_scaffold/src/steps/editor/step-03.editor.ts +58 -0
- package/template_scaffold/src/steps/editor/step-04.editor.ts +98 -0
- package/template_scaffold/src/steps/editor/step-32-paywall.editor.ts +478 -0
- package/template_scaffold/src/steps/editor/subscription-started.editor.ts +131 -0
- package/template_scaffold/src/steps/index.ts +25 -0
- package/template_scaffold/src/steps/paywall-checkout-options.test.ts +104 -0
- package/template_scaffold/src/steps/paywall-checkout-options.ts +130 -0
- package/template_scaffold/src/steps/pricing/paywall-b.pricing.ts +12 -0
- package/template_scaffold/src/steps/pricing/paywall.pricing.ts +12 -0
- package/template_scaffold/src/steps/pricing/shared-plan-order.ts +17 -0
- package/template_scaffold/src/steps/pricing/upsell-form.pricing.ts +16 -0
- package/template_scaffold/src/steps/shared-header-contract.test.ts +27 -0
- package/template_scaffold/src/steps/step-01.test.ts +38 -0
- package/template_scaffold/src/steps/step-01.tsx +108 -0
- package/template_scaffold/src/steps/step-02.test.ts +43 -0
- package/template_scaffold/src/steps/step-02.tsx +140 -0
- package/template_scaffold/src/steps/step-03.test.ts +15 -0
- package/template_scaffold/src/steps/step-03.tsx +262 -0
- package/template_scaffold/src/steps/step-04.test.ts +32 -0
- package/template_scaffold/src/steps/step-04.tsx +673 -0
- package/template_scaffold/src/steps/step-31-email-capture.test.ts +22 -0
- package/template_scaffold/src/steps/step-31-email-capture.tsx +195 -0
- package/template_scaffold/src/steps/step-32-paywall.test.ts +770 -0
- package/template_scaffold/src/steps/step-32-paywall.tsx +2253 -0
- package/template_scaffold/src/steps/step-32b-paywall-b.tsx +35 -0
- package/template_scaffold/src/steps/step-33-subscription-started.test.ts +26 -0
- package/template_scaffold/src/steps/step-33-subscription-started.tsx +86 -0
- package/template_scaffold/src/steps/step-34-upsell-form.test.ts +27 -0
- package/template_scaffold/src/steps/step-35-manage-subscription.tsx +46 -0
- package/template_scaffold/src/steps/step-content.registry.ts +45 -0
- package/template_scaffold/src/steps/step-image-migration.test.ts +20 -0
- package/template_scaffold/src/steps/styles/index.css +2 -0
- package/template_scaffold/src/steps/styles/shared/final-flow-shared.css +55 -0
- package/template_scaffold/src/steps/styles/shared/funnel-base.css +543 -0
- package/template_scaffold/src/steps/styles/shared/info-shared.css +139 -0
- package/template_scaffold/src/steps/styles/shared/progress-shared.css +117 -0
- package/template_scaffold/src/steps/styles/shared/question-shared.css +76 -0
- package/template_scaffold/src/steps/styles/shared/responsive-container.css +176 -0
- package/template_scaffold/src/steps/types.ts +7 -0
- package/template_scaffold/src/steps/use-claimbee-step-content.ts +15 -0
- package/template_scaffold/src/theme/theme.ts +81 -0
- package/template_scaffold/tsconfig.json +38 -0
- package/template_scaffold/vitest.config.ts +32 -0
- package/template_validation/.funnelsgrove-contract-tools.json +19 -0
- package/template_validation/src/contract/funnel-project.validation.ts +44 -0
- package/template_validation/src/contract/funnel-validator.vite.config.ts +11 -0
- package/template_validation/src/contract/validate-funnel.cli.ts +199 -0
- package/template_docs/docs/ab-experiments.md +0 -55
- package/template_docs/docs/analytics.md +0 -65
- package/template_docs/docs/editing-flow.md +0 -125
- package/template_docs/docs/editing-step.md +0 -125
- package/template_docs/docs/editor-and-content.md +0 -58
- package/template_docs/docs/funnel-runtime-architecture.md +0 -125
- package/template_docs/docs/meta-pixel-conversions-api.md +0 -50
- package/template_docs/docs/payment-plans-and-discounts.md +0 -106
- package/template_docs/docs/publishing-and-versioning.md +0 -117
- package/template_docs/docs/qa-checklist.md +0 -80
- package/template_docs/docs/sdk-api-endpoints.md +0 -78
- package/template_docs/docs/step-ui-guidelines.md +0 -110
- package/template_docs/docs/theme.md +0 -35
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file is generated from the FunnelsGrove step contract. Start at [the agent documentation router](docs/funnelsgrove/START-HERE.md), then read the exact page for the step type you are changing.
|
|
4
|
+
|
|
5
|
+
## Route by task
|
|
6
|
+
|
|
7
|
+
| Task | Read first |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Add a step | [Add a step](docs/funnelsgrove/recipes/add-step.md) |
|
|
10
|
+
| Edit a step | [Edit a step](docs/funnelsgrove/recipes/edit-step.md) |
|
|
11
|
+
| Change metadata or routing | [Step metadata](docs/funnelsgrove/contracts/step-metadata.md) and [flow routing](docs/funnelsgrove/contracts/flow-routing.md) |
|
|
12
|
+
| Add or edit choices | [Content and answers](docs/funnelsgrove/contracts/content-answers.md) |
|
|
13
|
+
| Edit product strategy, plan, or copy | [Content and answers](docs/funnelsgrove/contracts/content-answers.md) |
|
|
14
|
+
| Add an experiment | [Add an experiment](docs/funnelsgrove/recipes/add-experiment.md) |
|
|
15
|
+
| Edit email capture or analytics | [Analytics events](docs/funnelsgrove/contracts/analytics-events.md) |
|
|
16
|
+
| Edit paywall, checkout, or subscription flow | [Payments](docs/funnelsgrove/contracts/payments.md) |
|
|
17
|
+
| Edit theme, CSS, layout, or images | [Start here](docs/funnelsgrove/START-HERE.md), [flow routing](docs/funnelsgrove/contracts/flow-routing.md), and [local QA](docs/funnelsgrove/qa/local.md) |
|
|
18
|
+
| QA or publish | [Local QA](docs/funnelsgrove/qa/local.md), [analytics QA](docs/funnelsgrove/qa/analytics.md), and [publish QA](docs/funnelsgrove/qa/publish.md) |
|
|
19
|
+
|
|
20
|
+
## Non-negotiable workflow
|
|
21
|
+
|
|
22
|
+
1. Read the matching [step-type page](docs/funnelsgrove/steps/INDEX.md).
|
|
23
|
+
2. Keep manifest metadata and component metadata identical.
|
|
24
|
+
3. Use shared helpers for answers, conversions, checkout, handoff, and routing.
|
|
25
|
+
4. Run `fgrove validate` and the relevant manual QA checklist.
|
|
26
|
+
5. Publish preview first. Publish production only after explicit approval.
|
|
27
|
+
|
|
28
|
+
## Sync safety
|
|
29
|
+
|
|
30
|
+
1. Before edits run `fgrove status`, `git status --short`, and `fgrove github status` when the funnel is GitHub-connected.
|
|
31
|
+
2. Never run `fgrove sync down` over changed synced source. Use `--force` only to intentionally discard those local changes.
|
|
32
|
+
3. Sync-up uses remote compare-and-swap through the base draft version. On stale-draft rejection, download into a clean temporary directory, merge deliberately, rerun checks, and retry.
|
|
33
|
+
4. GitHub-connected changes use git push, `fgrove github pull`, terminal status, then publish; never use `fgrove sync up` for the same diff. Non-GitHub funnels use `fgrove sync up`.
|
|
34
|
+
5. Use `fgrove env pull` when only the ignored `.env` must be refreshed. Environment files never belong in synced source.
|
|
35
|
+
|
|
36
|
+
Contract version: `3`
|
|
37
|
+
|
|
38
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
39
|
+
|
|
40
|
+
## Project-specific context
|
|
41
|
+
|
|
42
|
+
If an unmanaged `AGENTS.project.md` exists, read and apply `AGENTS.project.md` after this managed contract. It may add product-specific constraints, but if it conflicts with this bundle, the managed contract wins. The docs generator never creates, hashes, copies, overwrites, or deletes that file.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Funnel Implementation Plan
|
|
2
|
+
|
|
3
|
+
## Plan Refinement Log
|
|
4
|
+
- Pass 1: Define target audience, value promise, and baseline step sequence.
|
|
5
|
+
- Pass 2: Refine copy hierarchy, CTA ownership, and branch behavior.
|
|
6
|
+
- Pass 3: Validate paywall trust signals, routing, and mobile UX constraints.
|
|
7
|
+
|
|
8
|
+
## Step Sequence
|
|
9
|
+
Use runtime IDs in order. Keep names human-readable.
|
|
10
|
+
|
|
11
|
+
### Step 1: step-1 - Opening
|
|
12
|
+
**Goal:** Define first-screen value promise.
|
|
13
|
+
**Headline:** _TBD_
|
|
14
|
+
**Body:** _TBD_
|
|
15
|
+
**CTA:** Continue
|
|
16
|
+
**Interaction:** _TBD_
|
|
17
|
+
**Image:** _none | generate | provided_
|
|
18
|
+
|
|
19
|
+
### Step 2: step-2 - Qualification
|
|
20
|
+
**Goal:** Collect key user context for personalization.
|
|
21
|
+
**Headline:** _TBD_
|
|
22
|
+
**Body:** _TBD_
|
|
23
|
+
**CTA:** Continue
|
|
24
|
+
**Interaction:** _TBD_
|
|
25
|
+
**Image:** _none | generate | provided_
|
|
26
|
+
|
|
27
|
+
### Step 3: step-3 - Processing / Insight
|
|
28
|
+
**Goal:** Reinforce progress and maintain momentum.
|
|
29
|
+
**Headline:** _TBD_
|
|
30
|
+
**Body:** _TBD_
|
|
31
|
+
**CTA:** Continue or auto-advance
|
|
32
|
+
**Interaction:** _TBD_
|
|
33
|
+
**Image:** _none | generate | provided_
|
|
34
|
+
|
|
35
|
+
### Step 4: step-4 - Transformation
|
|
36
|
+
**Goal:** Show outcome and prepare for conversion.
|
|
37
|
+
**Headline:** _TBD_
|
|
38
|
+
**Body:** _TBD_
|
|
39
|
+
**CTA:** Continue
|
|
40
|
+
**Interaction:** _TBD_
|
|
41
|
+
**Image:** _none | generate | provided_
|
|
42
|
+
|
|
43
|
+
### Step N: paywall - Offer
|
|
44
|
+
**Goal:** Convert with clear value, pricing, and trust cues.
|
|
45
|
+
**Headline:** _TBD_
|
|
46
|
+
**Body:** _TBD_
|
|
47
|
+
**CTA:** _TBD_
|
|
48
|
+
**Interaction:** Select plan then purchase.
|
|
49
|
+
**Image:** _optional_
|
|
50
|
+
|
|
51
|
+
### Step N+1: subscription-started - Handoff
|
|
52
|
+
**Goal:** Confirm purchase and route user to app/home experience.
|
|
53
|
+
**Headline:** _TBD_
|
|
54
|
+
**Body:** _TBD_
|
|
55
|
+
**CTA:** _TBD_
|
|
56
|
+
**Interaction:** Open app / deep link.
|
|
57
|
+
|
|
58
|
+
## Funnel Fuel
|
|
59
|
+
| Screen | Section / role | Feeling | Fuel |
|
|
60
|
+
| --- | --- | --- | --- |
|
|
61
|
+
|
|
62
|
+
## Paywall Requirements
|
|
63
|
+
- Keep the live `paywall` aligned with ClaimBee Figma node `6992:6210`.
|
|
64
|
+
- Preserve the prior implementation as the direct `/paywall-old` route for regression checks.
|
|
65
|
+
- Keep visible `Money-back guarantee` copy.
|
|
66
|
+
- Keep guarantee badge image: `/paywall/money-back-badge.png`.
|
|
67
|
+
- Keep pricing/trial copy explicit and easy to scan.
|
|
68
|
+
- Launch Stripe checkout in a dedicated modal dialog that matches the published checkout design.
|
|
69
|
+
- In the modal, prioritize Stripe Link and express wallet buttons before the manual card form.
|
|
70
|
+
- After a successful payment, redirect to `subscription-started` so the app handoff screen appears immediately.
|
|
71
|
+
|
|
72
|
+
## CTA Ownership Rules
|
|
73
|
+
- `FunnelFlow` owns default Continue action bar.
|
|
74
|
+
- If `actionBar.hidden !== true`, do not render a duplicate local primary CTA.
|
|
75
|
+
- For yes/no branches, define targets in routing config and use shared in-step controls.
|
|
76
|
+
|
|
77
|
+
## Validation Checklist
|
|
78
|
+
- Step IDs are stable (`step-*`, `paywall`, `subscription-started`).
|
|
79
|
+
- Routing covers each active step and avoids dead ends.
|
|
80
|
+
- Paywall trust elements are present.
|
|
81
|
+
- Mobile layout remains full-screen with safe-area spacing.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Product Sense
|
|
2
|
+
|
|
3
|
+
## Product Summary
|
|
4
|
+
Describe what the product does in one to two sentences.
|
|
5
|
+
|
|
6
|
+
## Target Audience
|
|
7
|
+
Describe the intended user segment, device assumptions, and market.
|
|
8
|
+
|
|
9
|
+
## Traffic Promise
|
|
10
|
+
Describe the ad/landing promise users arrive with.
|
|
11
|
+
|
|
12
|
+
## Core Value Proposition
|
|
13
|
+
Describe the main value delivered in the first user session.
|
|
14
|
+
|
|
15
|
+
## Pricing Model
|
|
16
|
+
Describe trial and paid plan structure (for example monthly/yearly).
|
|
17
|
+
|
|
18
|
+
## Tone and Brand Voice
|
|
19
|
+
Describe tone, style, and visual direction constraints.
|
|
20
|
+
|
|
21
|
+
## Known Objections
|
|
22
|
+
- List top objections.
|
|
23
|
+
- List trust requirements.
|
|
24
|
+
- List legal/compliance constraints if relevant.
|
|
25
|
+
|
|
26
|
+
## Strategic Pre-Work
|
|
27
|
+
| Problem | Why current solutions fail | Barrier | Value | Higher-level value |
|
|
28
|
+
| --- | --- | --- | --- | --- |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Build Context
|
|
2
|
+
|
|
3
|
+
## Run Intent
|
|
4
|
+
- Current intent: build
|
|
5
|
+
- `plan`: update `PRODUCT_SENSE.md`, `PLAN.md`, and planning docs only.
|
|
6
|
+
- `build`: implement runtime files under `src/` and assets under `public/`.
|
|
7
|
+
|
|
8
|
+
## Project Structure
|
|
9
|
+
- `src/app`: Next.js routes and shell pages.
|
|
10
|
+
- `src/components`: flow shell and editor panel UI.
|
|
11
|
+
- `src/config`: manifest, runtime metadata, and per-step billing config.
|
|
12
|
+
- `src/runtime`: manifest helpers, flow controller, and step registry.
|
|
13
|
+
- `src/steps`: step components and registry.
|
|
14
|
+
- shared packages: `@funnelsgrove/runtime`, `@funnelsgrove/analytics`, `@funnelsgrove/payments`.
|
|
15
|
+
|
|
16
|
+
## Source Of Truth Files (Build)
|
|
17
|
+
- `src/config/funnel.manifest.ts` (flow, optional legacy entry points, branches, experiments, architecture version)
|
|
18
|
+
- `src/runtime/step-registry.ts` (component ownership)
|
|
19
|
+
- `src/steps/index.ts` (derived active step registry)
|
|
20
|
+
- `src/runtime/use-funnel-flow-controller.ts` (flow orchestration, tracking, and runtime mode)
|
|
21
|
+
- `src/components/FunnelFlow.tsx` (shell render)
|
|
22
|
+
- `src/components/FunnelEditorPanel.tsx` (editor controls)
|
|
23
|
+
- `docs/references/funnel-sdk-user-answers.md` (typed user answers + analytics usage)
|
|
24
|
+
|
|
25
|
+
## Onboarding Artifacts
|
|
26
|
+
- `PRODUCT_SENSE.md`: required
|
|
27
|
+
- `PLAN.md`: required
|
|
28
|
+
|
|
29
|
+
## Sequence Contract
|
|
30
|
+
- Keep foundation anchors first: `step-1`, `step-2`, `step-3`, `step-4`
|
|
31
|
+
- Keep conversion path terminal steps: `paywall`, `subscription-started`
|
|
32
|
+
|
|
33
|
+
## Generation Mode
|
|
34
|
+
- `baseline_five_step` by default unless a wider flow is explicitly requested.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Compatibility: agent funnel implementation spec
|
|
2
|
+
|
|
3
|
+
The canonical agent contract moved to [FunnelsGrove start here](funnelsgrove/START-HERE.md).
|
|
4
|
+
|
|
5
|
+
This compatibility page intentionally contains no copied taxonomy or workflow rules. Update the canonical bundle instead.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Compatibility: funnel architecture
|
|
2
|
+
|
|
3
|
+
Use the canonical [step metadata contract](funnelsgrove/contracts/step-metadata.md) for step structure and [flow routing contract](funnelsgrove/contracts/flow-routing.md) for graph behavior.
|
|
4
|
+
|
|
5
|
+
This compatibility page intentionally contains no normative contract copy.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# FunnelsGrove agent contract: start here
|
|
2
|
+
|
|
3
|
+
This bundle is the operating manual for agents that create or edit a synced funnel. It is generated and validated against the runtime step contract; follow it before changing funnel code.
|
|
4
|
+
|
|
5
|
+
<!-- funnelsgrove:generated:start contract-v3/overview/start-here -->
|
|
6
|
+
Step contract version: `3`
|
|
7
|
+
|
|
8
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
9
|
+
|
|
10
|
+
| Type | Family | Action owner | Required kind | Terminal | Meaning |
|
|
11
|
+
| --- | --- | --- | --- | --- | --- |
|
|
12
|
+
| `cancellation_offer` | `commerce` | `step` | `cancellation` | `false` | A cancellation retention or downsell surface. |
|
|
13
|
+
| `checkout` | `commerce` | `step` | — | `false` | A dedicated payment-entry screen. |
|
|
14
|
+
| `form_input` | `form` | `either` | — | `false` | Non-choice structured input, including reserved email capture. |
|
|
15
|
+
| `intro_hero` | `content` | `shared-shell` | — | `false` | Opening promise or low-friction entry screen. |
|
|
16
|
+
| `multi_select_choice` | `choice` | `either` | — | `false` | Multiple options are selected before explicit completion. |
|
|
17
|
+
| `paywall_offer` | `commerce` | `step` | `paywall` | `false` | A monetization offer that presents purchasable plans. |
|
|
18
|
+
| `progress_interstitial` | `transition` | `either` | — | `false` | Progress, calculation, loading, reveal, or transition screen. |
|
|
19
|
+
| `purchase_completed` | `terminal` | `step` | `subscription-handoff` | `true` | The canonical terminal shown after a verified initial purchase. |
|
|
20
|
+
| `single_step_choice` | `choice` | `step` | — | `false` | Exactly one standard option is selected. |
|
|
21
|
+
| `single_step_choice_emoji` | `choice` | `step` | — | `false` | Exactly one emoji-led option is selected. |
|
|
22
|
+
| `social_proof` | `content` | `shared-shell` | — | `false` | Testimonials, reviews, credibility, or evidence. |
|
|
23
|
+
| `subscription_handoff` | `commerce` | `step` | `subscription-handoff` | `false` | A non-terminal app, store, or deep-link handoff. |
|
|
24
|
+
| `subscription_management` | `commerce` | `step` | `manage-subscription` | `false` | A screen for managing or inspecting an existing subscription. |
|
|
25
|
+
| `summary_confirmation` | `content` | `either` | — | `false` | A summary, review, or confirmation before the next action. |
|
|
26
|
+
| `upsell_offer` | `commerce` | `step` | `upsell` | `false` | A post-purchase or upgrade offer. |
|
|
27
|
+
| `value_prop_story` | `content` | `shared-shell` | — | `false` | Benefit, explanation, motivation, or narrative value screen. |
|
|
28
|
+
|
|
29
|
+
### Reserved identities
|
|
30
|
+
|
|
31
|
+
| Contract | Match | ID | Name | Type | Kind | Primary | Unique |
|
|
32
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
33
|
+
| `email-capture` | `exact` | `email-capture` | `email-capture` | `form_input` | — | — | `true` |
|
|
34
|
+
| `manage-subscription` | `exact` | `manage-subscription` | `manage-subscription` | `subscription_management` | `manage-subscription` | — | `true` |
|
|
35
|
+
| `paywall` | `exact` | `paywall` | `paywall` | `paywall_offer` | `paywall` | `true` | `true` |
|
|
36
|
+
| `paywall-variant` | `pattern` | `^paywall-[a-z0-9-]+$` | `^paywall-[a-z0-9-]+$` | `paywall_offer` | `paywall` | `false` | `false` |
|
|
37
|
+
| `subscription-started` | `exact` | `subscription-started` | `subscription-started` | `purchase_completed` | `subscription-handoff` | — | `true` |
|
|
38
|
+
<!-- funnelsgrove:generated:end contract-v3/overview/start-here -->
|
|
39
|
+
|
|
40
|
+
## Choose the right document
|
|
41
|
+
|
|
42
|
+
- Step classification and parity: [step metadata](contracts/step-metadata.md) and the [step-type index](steps/INDEX.md).
|
|
43
|
+
- Analytics ownership and lifecycle: [analytics events](contracts/analytics-events.md).
|
|
44
|
+
- Manifest edges, reserved routes, branches, and experiments: [flow routing](contracts/flow-routing.md).
|
|
45
|
+
- Choice answers and email input: [content and answers](contracts/content-answers.md).
|
|
46
|
+
- Paywall, checkout, and subscription behavior: [payments](contracts/payments.md).
|
|
47
|
+
- New work: [add a step](recipes/add-step.md), [edit a step](recipes/edit-step.md), or [add an experiment](recipes/add-experiment.md).
|
|
48
|
+
- Verification: [local QA](qa/local.md), [analytics QA](qa/analytics.md), [paywall/checkout QA](qa/paywall-checkout.md), and [publish QA](qa/publish.md).
|
|
49
|
+
- Existing funnels: [step-contract v3 migration](migrations/step-contract-v3.md).
|
|
50
|
+
|
|
51
|
+
## Non-negotiable guardrails
|
|
52
|
+
|
|
53
|
+
- Classify a step by what the user can do, not its position, copy, or visual treatment.
|
|
54
|
+
- A paywall presents purchasable plans. A loading, reveal, or “ready” screen is an interstitial.
|
|
55
|
+
- Every choice declares `choice.answerKey`, stores stable option IDs in the exact scalar/array shape, and uses `useStepChoices`.
|
|
56
|
+
- Email capture uses `submitEmailCapture`; it never manually sends analytics or hard-codes paywall navigation.
|
|
57
|
+
- `subscription-started` is the `purchase_completed` terminal. Browser terminal reach is not Quiz completed; only the trusted backend records `purchase_completed` after verifying an initial purchase.
|
|
58
|
+
- Let the controller distinguish completion from exit and suppress provider delivery in preview.
|
|
59
|
+
|
|
60
|
+
## Standard workflow
|
|
61
|
+
|
|
62
|
+
1. Read the exact type page.
|
|
63
|
+
2. Change the smallest set of component, content/editor, registry, and manifest files needed.
|
|
64
|
+
3. Keep component and manifest metadata in parity.
|
|
65
|
+
4. Run `fgrove validate` and focused tests.
|
|
66
|
+
5. Perform the relevant manual QA.
|
|
67
|
+
6. Publish preview, inspect it, then publish production only with explicit approval.
|
|
68
|
+
|
|
69
|
+
## Theme and styling ownership
|
|
70
|
+
|
|
71
|
+
`src/theme/theme.ts` is the brand-token source. Preserve the typed `FunnelTheme` and `themeCssVariables = createThemeCssVariables(theme)`. Apply theme values through the emitted CSS variables: `globals.css` owns global reset, fonts, and root behavior; shared styles own repeated patterns; step-local CSS owns only genuinely local layout. Do not duplicate brand constants in step components.
|
|
72
|
+
|
|
73
|
+
Optional product-specific guidance belongs in `AGENTS.project.md`. That file is never managed by this bundle.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Analytics event ownership
|
|
2
|
+
|
|
3
|
+
Analytics is divided between controller-owned lifecycle events, explicit shared helpers, transactional server conversions, and trusted server claims.
|
|
4
|
+
|
|
5
|
+
<!-- funnelsgrove:generated:start contract-v3/contract/analytics-events -->
|
|
6
|
+
Step contract version: `3`
|
|
7
|
+
|
|
8
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
9
|
+
|
|
10
|
+
| Contract key | Public event | Raw event | Allowed step types | Allowed identities | Owner | Automatic | Dedupe | Required metadata |
|
|
11
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
12
|
+
| `add_payment_info` | `add_payment_info` | `add_payment_info` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-helper` | `false` | `event-id` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
13
|
+
| `checkout_completed` | `checkout_completed` | `checkout_completed` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-helper` | `false` | `event-id` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
14
|
+
| `checkout_started` | `checkout_started` | `checkout_started` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-helper` | `false` | `event-id` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
15
|
+
| `email_captured` | `email_captured` | `email_captured` | `form_input` | `email-capture` | `transactional-server` | `false` | `logical-email-conversion` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `projectId`, `funnelEndUserId`, `eventId` |
|
|
16
|
+
| `first_step_clicked` | `first_step_clicked` | `first_step_clicked` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
17
|
+
| `first_step_viewed` | `first_step_viewed` | `first_step_viewed` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
18
|
+
| `funnel_completed` | `funnel_completed` | `funnel_completed` | `purchase_completed` | `any` | `terminal-helper` | `false` | `funnel-run` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `eventId` |
|
|
19
|
+
| `funnel_started` | `funnel_started` | `funnel_start` | `any` | `any` | `controller` | `true` | `funnel-run` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion` |
|
|
20
|
+
| `purchase_completed` | `purchase_completed` | `purchase_completed` | _None_ | _None_ | `trusted-server` | `false` | `provider-payment` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `projectId`, `funnelEndUserId`, `eventId`, `providerPaymentId`, `purchaseKind` |
|
|
21
|
+
| `registration_completed` | `registration_completed` | `registration_completed` | _None_ | _None_ | `trusted-server` | `false` | `subscription-claim` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `projectId`, `funnelEndUserId`, `eventId`, `subscriptionClaimId` |
|
|
22
|
+
| `step_completed` | `step_completed` | `step_end` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
23
|
+
| `step_engaged` | `step_engaged` | `step_engaged` | `any` | `any` | `controller` | `false` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType`, `durationMs` |
|
|
24
|
+
| `step_exited` | `step_exited` | `step_exit` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
25
|
+
| `step_started` | `step_started` | `step_start` | `any` | `any` | `controller` | `true` | `step-visit` | `funnelId`, `funnelVersionId`, `environment`, `stepContractVersion`, `stepId`, `stepName`, `stepType` |
|
|
26
|
+
|
|
27
|
+
The `purchase_completed` event is owned by `trusted-server` and is recorded only after the backend verifies a successful initial purchase. Entering the browser terminal or emitting `funnel_completed` does not create this business conversion. The separate `registration_completed` event remains owned by `trusted-server` for the later app-link claim. The `email_captured` event is owned by `transactional-server` and uses `logical-email-conversion` deduplication.
|
|
28
|
+
<!-- funnelsgrove:generated:end contract-v3/contract/analytics-events -->
|
|
29
|
+
|
|
30
|
+
## Ownership rules
|
|
31
|
+
|
|
32
|
+
- The flow controller emits lifecycle events. Step components do not duplicate them.
|
|
33
|
+
- `step_engaged` is non-automatic and absent by default; only an explicit, centralized, tested policy may emit it through the approved controller/helper boundary.
|
|
34
|
+
- `submitEmailCapture` creates `email_captured` transactionally, then routes only after success.
|
|
35
|
+
- Named payment helpers emit checkout semantic events at real payment boundaries.
|
|
36
|
+
- The terminal helper owns funnel completion.
|
|
37
|
+
- A trusted backend owns `purchase_completed` after verifying an initial subscription or one-time payment; browser code never emits it, and terminal reach does not count as Quiz completed.
|
|
38
|
+
- A separate trusted server claim owns `registration_completed` when the purchased subscription is later linked in the app.
|
|
39
|
+
- Provider adapters and the durable outbox own PostHog and server Meta delivery.
|
|
40
|
+
|
|
41
|
+
## Privacy boundary
|
|
42
|
+
|
|
43
|
+
- Never put raw email or other PII in analytics event metadata or logs.
|
|
44
|
+
- Only the server delivery boundary may use raw email as Meta hashing input.
|
|
45
|
+
- PostHog properties must remain non-PII.
|
|
46
|
+
|
|
47
|
+
## Completion versus exit
|
|
48
|
+
|
|
49
|
+
Completion means the step’s intended action succeeded and navigation was committed. Back, close, unload, replaced visits, and abandoned payment are exits. The controller deduplicates each visit outcome. Preview suppresses API/provider delivery.
|
|
50
|
+
|
|
51
|
+
## Email capture sequence
|
|
52
|
+
|
|
53
|
+
1. Call `submitEmailCapture` once for the in-flight submit.
|
|
54
|
+
2. On API failure, do not mutate answer state, lifecycle, or route.
|
|
55
|
+
3. On a newly created conversion, browser Pixel/Google may fan out with the server event ID.
|
|
56
|
+
4. On a duplicate, skip browser fanout and continue safely.
|
|
57
|
+
5. Never call `trackLead`, PostHog, Meta CAPI, or a provider from the email step.
|
|
58
|
+
|
|
59
|
+
Use the [analytics QA checklist](../qa/analytics.md) for journey-level evidence.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Content, choices, and persisted answers
|
|
2
|
+
|
|
3
|
+
Content labels may change; analytics-safe option IDs and answer keys must remain stable.
|
|
4
|
+
|
|
5
|
+
<!-- funnelsgrove:generated:start contract-v3/contract/content-answers -->
|
|
6
|
+
Step contract version: `3`
|
|
7
|
+
|
|
8
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
9
|
+
|
|
10
|
+
| Type | Cardinality | Presentation | Completion | allowEmpty config |
|
|
11
|
+
| --- | --- | --- | --- | --- |
|
|
12
|
+
| `multi_select_choice` | `many` | `standard` | `explicit` | `true` |
|
|
13
|
+
| `single_step_choice` | `one` | `standard` | `selection` | `false` |
|
|
14
|
+
| `single_step_choice_emoji` | `one` | `emoji` | `selection` | `false` |
|
|
15
|
+
|
|
16
|
+
| Capability | Allowed types | Allowed identities | Required owner |
|
|
17
|
+
| --- | --- | --- | --- |
|
|
18
|
+
| `choice-write` | `single_step_choice`, `single_step_choice_emoji`, `multi_select_choice` | `any` | `useStepChoices` |
|
|
19
|
+
| `email-capture` | `form_input` | `email-capture` | `submitEmailCapture` |
|
|
20
|
+
<!-- funnelsgrove:generated:end contract-v3/contract/content-answers -->
|
|
21
|
+
|
|
22
|
+
## Choice rules
|
|
23
|
+
|
|
24
|
+
- Declare `choice.answerKey` in manifest and component metadata.
|
|
25
|
+
- Use stable option IDs, never labels, array positions, or entire objects.
|
|
26
|
+
- Persist a scalar ID for single-choice types and an ID array for multi-select.
|
|
27
|
+
- Represent an allowed empty multi-select as `[]`.
|
|
28
|
+
- Use `useStepChoices` for write, completion, and routing order.
|
|
29
|
+
|
|
30
|
+
## Form and email rules
|
|
31
|
+
|
|
32
|
+
Ordinary form inputs validate and persist through their owning runtime path. The reserved email form calls `submitEmailCapture`; it never sends analytics manually and never decides the next route.
|
|
33
|
+
|
|
34
|
+
## Content/editor parity
|
|
35
|
+
|
|
36
|
+
Keep builder-editable values in content definitions, expose matching editor sections, and register them once. Do not move stable IDs or answer keys into editable copy.
|
|
37
|
+
|
|
38
|
+
## Product strategy and plan ownership
|
|
39
|
+
|
|
40
|
+
- `PRODUCT_SENSE.md` owns audience, promise, positioning, objections, value stack, and brand direction. Preserve `## Strategic Pre-Work` and its exact five columns.
|
|
41
|
+
- `PLAN.md` owns the ordered screen contract, exact screen structure and copy, shared design system/components, and `## Funnel Fuel`. Keep one row per planned screen.
|
|
42
|
+
- Update the owning artifact in the same change. Never implement a step absent from `PLAN.md`.
|
|
43
|
+
|
|
44
|
+
See the exact choice and form pages in the [step-type index](../steps/INDEX.md). Run `fgrove validate` and test reload persistence before completion.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Flow routing contract
|
|
2
|
+
|
|
3
|
+
The manifest graph owns routes. Components request an outcome; they do not choose a hard-coded destination.
|
|
4
|
+
|
|
5
|
+
<!-- funnelsgrove:generated:start contract-v3/contract/flow-routing -->
|
|
6
|
+
Step contract version: `3`
|
|
7
|
+
|
|
8
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
9
|
+
|
|
10
|
+
| Contract | Match | ID | Name | Type | Kind | Primary | Unique |
|
|
11
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
12
|
+
| `email-capture` | `exact` | `email-capture` | `email-capture` | `form_input` | — | — | `true` |
|
|
13
|
+
| `manage-subscription` | `exact` | `manage-subscription` | `manage-subscription` | `subscription_management` | `manage-subscription` | — | `true` |
|
|
14
|
+
| `paywall` | `exact` | `paywall` | `paywall` | `paywall_offer` | `paywall` | `true` | `true` |
|
|
15
|
+
| `paywall-variant` | `pattern` | `^paywall-[a-z0-9-]+$` | `^paywall-[a-z0-9-]+$` | `paywall_offer` | `paywall` | `false` | `false` |
|
|
16
|
+
| `subscription-started` | `exact` | `subscription-started` | `subscription-started` | `purchase_completed` | `subscription-handoff` | — | `true` |
|
|
17
|
+
|
|
18
|
+
The `hardcoded-navigation` capability is owned by `manifest-flow-controller`.
|
|
19
|
+
<!-- funnelsgrove:generated:end contract-v3/contract/flow-routing -->
|
|
20
|
+
|
|
21
|
+
## Rules
|
|
22
|
+
|
|
23
|
+
- Give public paths meaningful product slugs.
|
|
24
|
+
- Keep `edgesByStepId` sources and targets as explicit string literals.
|
|
25
|
+
- Model conditional ownership in `branches`, including readable labels, tags, and owned step IDs.
|
|
26
|
+
- Keep every experiment control and variant as a real step with normal outgoing edges.
|
|
27
|
+
- Configure the email-to-offer edge in the manifest; the email component never names a paywall route.
|
|
28
|
+
- Keep inactive variants unreachable from the default flow rather than deleting their identity.
|
|
29
|
+
|
|
30
|
+
## Lifecycle-safe navigation
|
|
31
|
+
|
|
32
|
+
Use the flow controller so answer writes, semantic conversions, completion, and route commits stay ordered. A stale visit must not complete or navigate after a newer visit takes ownership.
|
|
33
|
+
|
|
34
|
+
For experiments, follow [the add-experiment recipe](../recipes/add-experiment.md). Run `fgrove validate` after any graph change.
|
|
35
|
+
|
|
36
|
+
## Asset and preload metadata
|
|
37
|
+
|
|
38
|
+
- Give each funnel-critical image a stable `funnelManifest.assets` entry and attach it through the owning step's `assetIds`; every ID must resolve.
|
|
39
|
+
- `assetIds` is routing/preload metadata, not an optimization opt-in. Use framework `priority` only for current first-viewport images.
|
|
40
|
+
- `preload: 'idle'` is effective only when a tested shell consumer exists. Warm likely next-step assets only, never the full funnel; do not claim preload behavior from metadata alone.
|
|
41
|
+
- Publish optimization is separate: the image-variants stage creates AVIF/WebP sidecars while retaining the original raster fallback.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Payments and subscription contract
|
|
2
|
+
|
|
3
|
+
Commerce steps use shared plan, checkout, wallet, handoff, and subscription helpers. Components own presentation and user intent, not provider integration.
|
|
4
|
+
|
|
5
|
+
<!-- funnelsgrove:generated:start contract-v3/contract/payments -->
|
|
6
|
+
Step contract version: `3`
|
|
7
|
+
|
|
8
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
9
|
+
|
|
10
|
+
| Type | Family | Action owner | Required kind | Terminal | Meaning |
|
|
11
|
+
| --- | --- | --- | --- | --- | --- |
|
|
12
|
+
| `cancellation_offer` | `commerce` | `step` | `cancellation` | `false` | A cancellation retention or downsell surface. |
|
|
13
|
+
| `checkout` | `commerce` | `step` | — | `false` | A dedicated payment-entry screen. |
|
|
14
|
+
| `paywall_offer` | `commerce` | `step` | `paywall` | `false` | A monetization offer that presents purchasable plans. |
|
|
15
|
+
| `subscription_handoff` | `commerce` | `step` | `subscription-handoff` | `false` | A non-terminal app, store, or deep-link handoff. |
|
|
16
|
+
| `subscription_management` | `commerce` | `step` | `manage-subscription` | `false` | A screen for managing or inspecting an existing subscription. |
|
|
17
|
+
| `upsell_offer` | `commerce` | `step` | `upsell` | `false` | A post-purchase or upgrade offer. |
|
|
18
|
+
|
|
19
|
+
| Capability | Allowed types | Allowed identities | Required owner |
|
|
20
|
+
| --- | --- | --- | --- |
|
|
21
|
+
| `checkout` | `paywall_offer`, `upsell_offer`, `checkout` | `any` | `named-payment-helpers` |
|
|
22
|
+
| `subscription-handoff` | `subscription_handoff`, `purchase_completed` | `any` | `runtime-handoff-helper` |
|
|
23
|
+
| `subscription-management` | `subscription_management`, `cancellation_offer` | `any` | `runtime-subscription-helpers` |
|
|
24
|
+
<!-- funnelsgrove:generated:end contract-v3/contract/payments -->
|
|
25
|
+
|
|
26
|
+
## Paywall definition
|
|
27
|
+
|
|
28
|
+
A paywall presents purchasable plans. A reveal, loading state, calculation, or “your plan is ready” bridge is a progress interstitial even when it precedes a paywall.
|
|
29
|
+
|
|
30
|
+
## Payment rules
|
|
31
|
+
|
|
32
|
+
- Resolve plans, prices, discounts, currencies, provider IDs, and payment mode from shared configuration.
|
|
33
|
+
- Use named checkout helpers at actual checkout-started, payment-info, and completed boundaries.
|
|
34
|
+
- Reuse the same event ID when retrying the same logical conversion.
|
|
35
|
+
- Keep secrets and trusted provider calls server-side.
|
|
36
|
+
- Route post-purchase behavior through the manifest and runtime handoff helper.
|
|
37
|
+
|
|
38
|
+
## Purchase completion separation
|
|
39
|
+
|
|
40
|
+
The canonical `subscription-started` route keeps its stable identity but uses the `purchase_completed` terminal type in contract v3. It may emit lifecycle-only `funnel_completed`, but entering it never counts as Quiz completed. Only the trusted backend emits `purchase_completed` after verifying an initial subscription or one-time payment; renewals, pending payments, and browser checkout returns do not qualify. `registration_completed` remains the later app-link conversion.
|
|
41
|
+
|
|
42
|
+
Before publishing, complete [paywall/checkout QA](../qa/paywall-checkout.md) and [publish QA](../qa/publish.md).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Step metadata contract
|
|
2
|
+
|
|
3
|
+
Step metadata is an analytics and runtime API, not descriptive decoration. Choose the type from actual behavior and preserve stable identity.
|
|
4
|
+
|
|
5
|
+
<!-- funnelsgrove:generated:start contract-v3/contract/step-metadata -->
|
|
6
|
+
Step contract version: `3`
|
|
7
|
+
|
|
8
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
9
|
+
|
|
10
|
+
| Type | Family | Action owner | Required kind | Terminal | Meaning |
|
|
11
|
+
| --- | --- | --- | --- | --- | --- |
|
|
12
|
+
| `cancellation_offer` | `commerce` | `step` | `cancellation` | `false` | A cancellation retention or downsell surface. |
|
|
13
|
+
| `checkout` | `commerce` | `step` | — | `false` | A dedicated payment-entry screen. |
|
|
14
|
+
| `form_input` | `form` | `either` | — | `false` | Non-choice structured input, including reserved email capture. |
|
|
15
|
+
| `intro_hero` | `content` | `shared-shell` | — | `false` | Opening promise or low-friction entry screen. |
|
|
16
|
+
| `multi_select_choice` | `choice` | `either` | — | `false` | Multiple options are selected before explicit completion. |
|
|
17
|
+
| `paywall_offer` | `commerce` | `step` | `paywall` | `false` | A monetization offer that presents purchasable plans. |
|
|
18
|
+
| `progress_interstitial` | `transition` | `either` | — | `false` | Progress, calculation, loading, reveal, or transition screen. |
|
|
19
|
+
| `purchase_completed` | `terminal` | `step` | `subscription-handoff` | `true` | The canonical terminal shown after a verified initial purchase. |
|
|
20
|
+
| `single_step_choice` | `choice` | `step` | — | `false` | Exactly one standard option is selected. |
|
|
21
|
+
| `single_step_choice_emoji` | `choice` | `step` | — | `false` | Exactly one emoji-led option is selected. |
|
|
22
|
+
| `social_proof` | `content` | `shared-shell` | — | `false` | Testimonials, reviews, credibility, or evidence. |
|
|
23
|
+
| `subscription_handoff` | `commerce` | `step` | `subscription-handoff` | `false` | A non-terminal app, store, or deep-link handoff. |
|
|
24
|
+
| `subscription_management` | `commerce` | `step` | `manage-subscription` | `false` | A screen for managing or inspecting an existing subscription. |
|
|
25
|
+
| `summary_confirmation` | `content` | `either` | — | `false` | A summary, review, or confirmation before the next action. |
|
|
26
|
+
| `upsell_offer` | `commerce` | `step` | `upsell` | `false` | A post-purchase or upgrade offer. |
|
|
27
|
+
| `value_prop_story` | `content` | `shared-shell` | — | `false` | Benefit, explanation, motivation, or narrative value screen. |
|
|
28
|
+
|
|
29
|
+
### Reserved identities
|
|
30
|
+
|
|
31
|
+
| Contract | Match | ID | Name | Type | Kind | Primary | Unique |
|
|
32
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
33
|
+
| `email-capture` | `exact` | `email-capture` | `email-capture` | `form_input` | — | — | `true` |
|
|
34
|
+
| `manage-subscription` | `exact` | `manage-subscription` | `manage-subscription` | `subscription_management` | `manage-subscription` | — | `true` |
|
|
35
|
+
| `paywall` | `exact` | `paywall` | `paywall` | `paywall_offer` | `paywall` | `true` | `true` |
|
|
36
|
+
| `paywall-variant` | `pattern` | `^paywall-[a-z0-9-]+$` | `^paywall-[a-z0-9-]+$` | `paywall_offer` | `paywall` | `false` | `false` |
|
|
37
|
+
| `subscription-started` | `exact` | `subscription-started` | `subscription-started` | `purchase_completed` | `subscription-handoff` | — | `true` |
|
|
38
|
+
<!-- funnelsgrove:generated:end contract-v3/contract/step-metadata -->
|
|
39
|
+
|
|
40
|
+
## Required parity
|
|
41
|
+
|
|
42
|
+
For each step, the manifest and exported component metadata must agree on `id`, `name`, `type`, optional `kind`, and optional `choice`. Keep `path`, `filePath`, `componentKey`, and title in the manifest. IDs and names are durable analytics keys.
|
|
43
|
+
|
|
44
|
+
## Classification method
|
|
45
|
+
|
|
46
|
+
1. Identify the screen’s user interaction and business purpose.
|
|
47
|
+
2. Open the matching [step-type page](../steps/INDEX.md).
|
|
48
|
+
3. Copy the fixture structure, then adapt only product-specific IDs, paths, copy, and content.
|
|
49
|
+
4. Run `fgrove validate` before preview.
|
|
50
|
+
|
|
51
|
+
## Protected metadata
|
|
52
|
+
|
|
53
|
+
Do not rename an existing step, answer key, reserved identity, or analytics meaning as cleanup. Treat such changes as migrations with compatibility and measurement review.
|
|
54
|
+
|
|
55
|
+
## Completion check
|
|
56
|
+
|
|
57
|
+
Validation passes, metadata parity has no diagnostics, every reserved identity is exact, and analytics receives stable type/name values.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Migrate a funnel to step contract v3
|
|
2
|
+
|
|
3
|
+
<!-- funnelsgrove:generated:start contract-v3/migration/step-contract-v3 -->
|
|
4
|
+
Step contract version: `3`
|
|
5
|
+
|
|
6
|
+
Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
|
|
7
|
+
|
|
8
|
+
Supported read versions: `1`, `2`, `3`. Authoring and publish target version `3`. Contract v2 remains readable with `complete_registration`; migration to v3 changes that terminal type to `purchase_completed`. New v3 instructions must not author `complete_registration`.
|
|
9
|
+
|
|
10
|
+
| Contract | Match | ID | Name | Type | Kind | Primary | Unique |
|
|
11
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
12
|
+
| `email-capture` | `exact` | `email-capture` | `email-capture` | `form_input` | — | — | `true` |
|
|
13
|
+
| `manage-subscription` | `exact` | `manage-subscription` | `manage-subscription` | `subscription_management` | `manage-subscription` | — | `true` |
|
|
14
|
+
| `paywall` | `exact` | `paywall` | `paywall` | `paywall_offer` | `paywall` | `true` | `true` |
|
|
15
|
+
| `paywall-variant` | `pattern` | `^paywall-[a-z0-9-]+$` | `^paywall-[a-z0-9-]+$` | `paywall_offer` | `paywall` | `false` | `false` |
|
|
16
|
+
| `subscription-started` | `exact` | `subscription-started` | `subscription-started` | `purchase_completed` | `subscription-handoff` | — | `true` |
|
|
17
|
+
|
|
18
|
+
### Package release order
|
|
19
|
+
|
|
20
|
+
Release `@funnelsgrove/runtime` `0.1.59` first, then `@funnelsgrove/analytics` `0.1.36`, then `@funnelsgrove/cli` `0.1.18`. Deploy the API and funnel template only after those registry versions are available. Publishing packages and deploying production remain separately approved operational actions.
|
|
21
|
+
<!-- funnelsgrove:generated:end contract-v3/migration/step-contract-v3 -->
|
|
22
|
+
|
|
23
|
+
## Version-last policy
|
|
24
|
+
|
|
25
|
+
1. Inventory every step, component metadata export, manifest entry, answer key, route, branch, experiment, and custom analytics call.
|
|
26
|
+
2. Reclassify by behavior using the [step-type index](../steps/INDEX.md).
|
|
27
|
+
3. Restore exact reserved identities and manifest/component parity.
|
|
28
|
+
4. Move choice writes, email capture, payment events, handoff, routing, and lifecycle work to approved shared owners.
|
|
29
|
+
5. Add/update fixtures and focused tests.
|
|
30
|
+
6. Run `fgrove validate` and all [local](../qa/local.md), [analytics](../qa/analytics.md), and payment QA that applies.
|
|
31
|
+
7. Change `stepContractVersion` only after every earlier step passes.
|
|
32
|
+
|
|
33
|
+
Do not use the version field to silence diagnostics. Preserve legacy stable IDs and answer keys unless a separately planned data/analytics migration owns the change.
|
|
34
|
+
|
|
35
|
+
## v2 compatibility
|
|
36
|
+
|
|
37
|
+
Contract v2 funnels remain readable with the `complete_registration` terminal type. The v2-to-v3 migration preserves the `subscription-started` identity, route, file, transitions, and all unrelated metadata while changing only the contract version and terminal type to `purchase_completed`. New v3 authoring must never generate `complete_registration`.
|
|
38
|
+
|
|
39
|
+
The migration does not turn browser terminal reach into a trusted conversion. Only the backend emits the v3 `purchase_completed` analytics event after verifying a successful initial subscription or one-time payment. `registration_completed` remains the separate later app-link event.
|