@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.
Files changed (293) hide show
  1. package/contracts/step-contract-v2.json +733 -0
  2. package/dist/analyticsOutput.d.ts +30 -15
  3. package/dist/analyticsOutput.js +45 -28
  4. package/dist/apiClient.d.ts +85 -0
  5. package/dist/apiClient.js +225 -8
  6. package/dist/cli.d.ts +149 -1
  7. package/dist/cli.js +1232 -71
  8. package/dist/diagnosticOutput.d.ts +42 -0
  9. package/dist/diagnosticOutput.js +83 -0
  10. package/dist/docsOutput.d.ts +19 -0
  11. package/dist/docsOutput.js +73 -0
  12. package/dist/docsTransaction.d.ts +81 -0
  13. package/dist/docsTransaction.js +1755 -0
  14. package/dist/funnelValidation.d.ts +14 -0
  15. package/dist/funnelValidation.js +297 -0
  16. package/dist/localSync.d.ts +79 -0
  17. package/dist/localSync.js +428 -53
  18. package/dist/projectValidator.d.ts +27 -0
  19. package/dist/projectValidator.js +208 -0
  20. package/dist/reskin.js +27 -1
  21. package/dist/stepContractMigration.d.ts +71 -0
  22. package/dist/stepContractMigration.js +1323 -0
  23. package/dist/templateDocs.js +8 -25
  24. package/docs-release-history.json +66 -0
  25. package/legacy-docs-catalog.json +1012 -0
  26. package/package.json +13 -4
  27. package/template_docs/.funnelsgrove-docs.json +144 -0
  28. package/template_docs/AGENTS.md +30 -58
  29. package/template_docs/CLAUDE.md +0 -2
  30. package/template_docs/docs/funnelsgrove/START-HERE.md +73 -0
  31. package/template_docs/docs/funnelsgrove/contracts/analytics-events.md +59 -0
  32. package/template_docs/docs/funnelsgrove/contracts/content-answers.md +44 -0
  33. package/template_docs/docs/funnelsgrove/contracts/flow-routing.md +41 -0
  34. package/template_docs/docs/funnelsgrove/contracts/payments.md +42 -0
  35. package/template_docs/docs/funnelsgrove/contracts/step-metadata.md +57 -0
  36. package/template_docs/docs/funnelsgrove/migrations/step-contract-v3.md +39 -0
  37. package/template_docs/docs/funnelsgrove/qa/analytics.md +43 -0
  38. package/template_docs/docs/funnelsgrove/qa/local.md +42 -0
  39. package/template_docs/docs/funnelsgrove/qa/paywall-checkout.md +55 -0
  40. package/template_docs/docs/funnelsgrove/qa/publish.md +32 -0
  41. package/template_docs/docs/funnelsgrove/recipes/add-experiment.md +34 -0
  42. package/template_docs/docs/funnelsgrove/recipes/add-step.md +33 -0
  43. package/template_docs/docs/funnelsgrove/recipes/edit-step.md +31 -0
  44. package/template_docs/docs/funnelsgrove/steps/INDEX.md +26 -0
  45. package/template_docs/docs/funnelsgrove/steps/cancellation_offer.md +112 -0
  46. package/template_docs/docs/funnelsgrove/steps/checkout.md +120 -0
  47. package/template_docs/docs/funnelsgrove/steps/form_input.md +115 -0
  48. package/template_docs/docs/funnelsgrove/steps/intro_hero.md +110 -0
  49. package/template_docs/docs/funnelsgrove/steps/multi_select_choice.md +123 -0
  50. package/template_docs/docs/funnelsgrove/steps/paywall_offer.md +115 -0
  51. package/template_docs/docs/funnelsgrove/steps/progress_interstitial.md +111 -0
  52. package/template_docs/docs/funnelsgrove/steps/purchase_completed.md +117 -0
  53. package/template_docs/docs/funnelsgrove/steps/single_step_choice.md +122 -0
  54. package/template_docs/docs/funnelsgrove/steps/single_step_choice_emoji.md +122 -0
  55. package/template_docs/docs/funnelsgrove/steps/social_proof.md +110 -0
  56. package/template_docs/docs/funnelsgrove/steps/subscription_handoff.md +113 -0
  57. package/template_docs/docs/funnelsgrove/steps/subscription_management.md +112 -0
  58. package/template_docs/docs/funnelsgrove/steps/summary_confirmation.md +110 -0
  59. package/template_docs/docs/funnelsgrove/steps/upsell_offer.md +112 -0
  60. package/template_docs/docs/funnelsgrove/steps/value_prop_story.md +110 -0
  61. package/template_docs/funnel-docs.config.json +43 -0
  62. package/template_scaffold/.env.example +41 -0
  63. package/template_scaffold/.funnelsgrove-contract-tools.json +19 -0
  64. package/template_scaffold/.funnelsgrove-docs.json +144 -0
  65. package/template_scaffold/.funnelsgrove-scaffold.json +1078 -0
  66. package/template_scaffold/AGENTS.md +42 -0
  67. package/template_scaffold/CLAUDE.md +1 -0
  68. package/template_scaffold/PLAN.md +81 -0
  69. package/template_scaffold/PRODUCT_SENSE.md +28 -0
  70. package/template_scaffold/context/build-context.md +34 -0
  71. package/template_scaffold/docs/AGENT_FUNNEL_IMPLEMENTATION_SPEC.md +5 -0
  72. package/template_scaffold/docs/ARCHITECTURE.md +5 -0
  73. package/template_scaffold/docs/FLOW_CONFIG_AND_ROUTING.md +5 -0
  74. package/template_scaffold/docs/PAYWALL_AND_PAYMENTS.md +5 -0
  75. package/template_scaffold/docs/README.md +5 -0
  76. package/template_scaffold/docs/funnelsgrove/START-HERE.md +73 -0
  77. package/template_scaffold/docs/funnelsgrove/contracts/analytics-events.md +59 -0
  78. package/template_scaffold/docs/funnelsgrove/contracts/content-answers.md +44 -0
  79. package/template_scaffold/docs/funnelsgrove/contracts/flow-routing.md +41 -0
  80. package/template_scaffold/docs/funnelsgrove/contracts/payments.md +42 -0
  81. package/template_scaffold/docs/funnelsgrove/contracts/step-metadata.md +57 -0
  82. package/template_scaffold/docs/funnelsgrove/migrations/step-contract-v3.md +39 -0
  83. package/template_scaffold/docs/funnelsgrove/qa/analytics.md +43 -0
  84. package/template_scaffold/docs/funnelsgrove/qa/local.md +42 -0
  85. package/template_scaffold/docs/funnelsgrove/qa/paywall-checkout.md +55 -0
  86. package/template_scaffold/docs/funnelsgrove/qa/publish.md +32 -0
  87. package/template_scaffold/docs/funnelsgrove/recipes/add-experiment.md +34 -0
  88. package/template_scaffold/docs/funnelsgrove/recipes/add-step.md +33 -0
  89. package/template_scaffold/docs/funnelsgrove/recipes/edit-step.md +31 -0
  90. package/template_scaffold/docs/funnelsgrove/steps/INDEX.md +26 -0
  91. package/template_scaffold/docs/funnelsgrove/steps/cancellation_offer.md +112 -0
  92. package/template_scaffold/docs/funnelsgrove/steps/checkout.md +120 -0
  93. package/template_scaffold/docs/funnelsgrove/steps/form_input.md +115 -0
  94. package/template_scaffold/docs/funnelsgrove/steps/intro_hero.md +110 -0
  95. package/template_scaffold/docs/funnelsgrove/steps/multi_select_choice.md +123 -0
  96. package/template_scaffold/docs/funnelsgrove/steps/paywall_offer.md +115 -0
  97. package/template_scaffold/docs/funnelsgrove/steps/progress_interstitial.md +111 -0
  98. package/template_scaffold/docs/funnelsgrove/steps/purchase_completed.md +117 -0
  99. package/template_scaffold/docs/funnelsgrove/steps/single_step_choice.md +122 -0
  100. package/template_scaffold/docs/funnelsgrove/steps/single_step_choice_emoji.md +122 -0
  101. package/template_scaffold/docs/funnelsgrove/steps/social_proof.md +110 -0
  102. package/template_scaffold/docs/funnelsgrove/steps/subscription_handoff.md +113 -0
  103. package/template_scaffold/docs/funnelsgrove/steps/subscription_management.md +112 -0
  104. package/template_scaffold/docs/funnelsgrove/steps/summary_confirmation.md +110 -0
  105. package/template_scaffold/docs/funnelsgrove/steps/upsell_offer.md +112 -0
  106. package/template_scaffold/docs/funnelsgrove/steps/value_prop_story.md +110 -0
  107. package/template_scaffold/docs/references/funnel-sdk-user-answers.md +5 -0
  108. package/template_scaffold/eslint.config.mjs +16 -0
  109. package/template_scaffold/funnel-agent-docs.test.ts +699 -0
  110. package/template_scaffold/funnel-docs.config.json +43 -0
  111. package/template_scaffold/funnel.config.json +5 -0
  112. package/template_scaffold/gitignore.template +5 -0
  113. package/template_scaffold/next-env.d.ts +6 -0
  114. package/template_scaffold/next.config.ts +53 -0
  115. package/template_scaffold/package-lock.json +7737 -0
  116. package/template_scaffold/package.json +37 -0
  117. package/template_scaffold/package.test.ts +23 -0
  118. package/template_scaffold/public/claimbee/bee.png +0 -0
  119. package/template_scaffold/public/claimbee/device-iphone.png +0 -0
  120. package/template_scaffold/public/claimbee/device-macbook.png +0 -0
  121. package/template_scaffold/public/claimbee/device-none.png +0 -0
  122. package/template_scaffold/public/claimbee/device-watch.png +0 -0
  123. package/template_scaffold/public/claimbee/glow.svg +3 -0
  124. package/template_scaffold/public/claimbee/steps-sprite-alt.png +0 -0
  125. package/template_scaffold/public/claimbee/steps-sprite-default.png +0 -0
  126. package/template_scaffold/public/claimbee/testimonial-avatar.png +0 -0
  127. package/template_scaffold/public/claimbee/testimonial-star.svg +3 -0
  128. package/template_scaffold/public/paywall/ai-claim-assistant.png +0 -0
  129. package/template_scaffold/public/paywall/claim-history.png +0 -0
  130. package/template_scaffold/public/paywall/clear-progress.png +0 -0
  131. package/template_scaffold/public/paywall/hero.png +0 -0
  132. package/template_scaffold/public/paywall/money-alerts.png +0 -0
  133. package/template_scaffold/public/paywall/money-back-badge.png +0 -0
  134. package/template_scaffold/public/paywall/paywall-image.png +0 -0
  135. package/template_scaffold/public/paywall/r1.png +0 -0
  136. package/template_scaffold/public/paywall/r2.png +0 -0
  137. package/template_scaffold/public/paywall/r3.png +0 -0
  138. package/template_scaffold/public/paywall/r4.png +0 -0
  139. package/template_scaffold/public/paywall/r5.png +0 -0
  140. package/template_scaffold/public/paywall/r6.png +0 -0
  141. package/template_scaffold/public/paywall/special-offer-gift.png +0 -0
  142. package/template_scaffold/public/please/bee.png +0 -0
  143. package/template_scaffold/public/please/device-iphone.png +0 -0
  144. package/template_scaffold/public/please/device-macbook.png +0 -0
  145. package/template_scaffold/public/please/device-none.png +0 -0
  146. package/template_scaffold/public/please/device-watch.png +0 -0
  147. package/template_scaffold/public/please/glow.svg +3 -0
  148. package/template_scaffold/public/please/steps-sprite-alt.png +0 -0
  149. package/template_scaffold/public/please/steps-sprite-default.png +0 -0
  150. package/template_scaffold/public/please/testimonial-avatar.png +0 -0
  151. package/template_scaffold/public/please/testimonial-star.svg +3 -0
  152. package/template_scaffold/public/upsell/upgrade-hero.png +0 -0
  153. package/template_scaffold/src/app/[stepId]/page.test.tsx +59 -0
  154. package/template_scaffold/src/app/[stepId]/page.tsx +62 -0
  155. package/template_scaffold/src/app/globals.css +49 -0
  156. package/template_scaffold/src/app/layout.test.ts +26 -0
  157. package/template_scaffold/src/app/layout.tsx +61 -0
  158. package/template_scaffold/src/app/page.tsx +8 -0
  159. package/template_scaffold/src/app/sdk/page.tsx +673 -0
  160. package/template_scaffold/src/app/subscription-dashboard/page.tsx +274 -0
  161. package/template_scaffold/src/assets/claimbee/bee.png +0 -0
  162. package/template_scaffold/src/assets/claimbee/device-iphone.png +0 -0
  163. package/template_scaffold/src/assets/claimbee/device-macbook.png +0 -0
  164. package/template_scaffold/src/assets/claimbee/device-none.png +0 -0
  165. package/template_scaffold/src/assets/claimbee/device-watch.png +0 -0
  166. package/template_scaffold/src/assets/claimbee/glow.svg +3 -0
  167. package/template_scaffold/src/assets/claimbee/steps-sprite-alt.png +0 -0
  168. package/template_scaffold/src/assets/claimbee/steps-sprite-default.png +0 -0
  169. package/template_scaffold/src/assets/claimbee/testimonial-avatar.png +0 -0
  170. package/template_scaffold/src/assets/claimbee/testimonial-star.svg +3 -0
  171. package/template_scaffold/src/components/FunnelEditorPanel.tsx +194 -0
  172. package/template_scaffold/src/components/FunnelFlow.test.tsx +17 -0
  173. package/template_scaffold/src/components/FunnelFlow.tsx +114 -0
  174. package/template_scaffold/src/components/FunnelStepImage.test.ts +15 -0
  175. package/template_scaffold/src/components/FunnelStepImage.tsx +28 -0
  176. package/template_scaffold/src/components/step/FunnelStepHeader.tsx +35 -0
  177. package/template_scaffold/src/config/billing.plans.test.ts +143 -0
  178. package/template_scaffold/src/config/billing.plans.ts +69 -0
  179. package/template_scaffold/src/config/billing.test.plans.ts +32 -0
  180. package/template_scaffold/src/config/experiments.generated.ts +4 -0
  181. package/template_scaffold/src/config/experiments.test.ts +12 -0
  182. package/template_scaffold/src/config/experiments.ts +9 -0
  183. package/template_scaffold/src/config/funnel.config.ts +12 -0
  184. package/template_scaffold/src/config/funnel.manifest.test.ts +166 -0
  185. package/template_scaffold/src/config/funnel.manifest.ts +139 -0
  186. package/template_scaffold/src/config/offer-sets.generated.ts +4 -0
  187. package/template_scaffold/src/contract/funnel-project.validation.test.ts +80 -0
  188. package/template_scaffold/src/contract/funnel-project.validation.ts +44 -0
  189. package/template_scaffold/src/contract/funnel-validator.vite.config.ts +11 -0
  190. package/template_scaffold/src/contract/golden/cancellation_offer.fixture.ts +29 -0
  191. package/template_scaffold/src/contract/golden/checkout.fixture.ts +37 -0
  192. package/template_scaffold/src/contract/golden/form_input.fixture.ts +28 -0
  193. package/template_scaffold/src/contract/golden/golden-fixtures.test.ts +190 -0
  194. package/template_scaffold/src/contract/golden/intro_hero.fixture.ts +27 -0
  195. package/template_scaffold/src/contract/golden/multi_select_choice.fixture.ts +37 -0
  196. package/template_scaffold/src/contract/golden/paywall_offer.fixture.ts +30 -0
  197. package/template_scaffold/src/contract/golden/progress_interstitial.fixture.ts +28 -0
  198. package/template_scaffold/src/contract/golden/purchase_completed.fixture.ts +33 -0
  199. package/template_scaffold/src/contract/golden/single_step_choice.fixture.ts +36 -0
  200. package/template_scaffold/src/contract/golden/single_step_choice_emoji.fixture.ts +36 -0
  201. package/template_scaffold/src/contract/golden/social_proof.fixture.ts +27 -0
  202. package/template_scaffold/src/contract/golden/subscription_handoff.fixture.ts +30 -0
  203. package/template_scaffold/src/contract/golden/subscription_management.fixture.ts +29 -0
  204. package/template_scaffold/src/contract/golden/summary_confirmation.fixture.ts +27 -0
  205. package/template_scaffold/src/contract/golden/upsell_offer.fixture.ts +29 -0
  206. package/template_scaffold/src/contract/golden/value_prop_story.fixture.ts +27 -0
  207. package/template_scaffold/src/contract/validate-funnel.cli.test.ts +180 -0
  208. package/template_scaffold/src/contract/validate-funnel.cli.ts +199 -0
  209. package/template_scaffold/src/runtime/checkout-runtime-config.test.ts +60 -0
  210. package/template_scaffold/src/runtime/checkout-runtime-config.ts +26 -0
  211. package/template_scaffold/src/runtime/funnel-runtime.test.ts +25 -0
  212. package/template_scaffold/src/runtime/funnel-runtime.ts +118 -0
  213. package/template_scaffold/src/runtime/step-content-context.test.ts +38 -0
  214. package/template_scaffold/src/runtime/step-content-context.ts +65 -0
  215. package/template_scaffold/src/runtime/step-registry.ts +66 -0
  216. package/template_scaffold/src/runtime/step-variable-values.ts +31 -0
  217. package/template_scaffold/src/runtime/use-funnel-flow-controller.integration.test.ts +203 -0
  218. package/template_scaffold/src/runtime/use-funnel-flow-controller.test.ts +76 -0
  219. package/template_scaffold/src/runtime/use-funnel-flow-controller.ts +53 -0
  220. package/template_scaffold/src/steps/content/email-capture.content.ts +29 -0
  221. package/template_scaffold/src/steps/content/manage-subscription.content.ts +62 -0
  222. package/template_scaffold/src/steps/content/paywall.content.ts +191 -0
  223. package/template_scaffold/src/steps/content/step-01.content.ts +23 -0
  224. package/template_scaffold/src/steps/content/step-02.content.ts +77 -0
  225. package/template_scaffold/src/steps/content/step-03.content.ts +40 -0
  226. package/template_scaffold/src/steps/content/step-04.content.ts +49 -0
  227. package/template_scaffold/src/steps/content/step-32-paywall.content.ts +352 -0
  228. package/template_scaffold/src/steps/content/subscription-started.content.ts +68 -0
  229. package/template_scaffold/src/steps/editor/email-capture.editor.ts +58 -0
  230. package/template_scaffold/src/steps/editor/manage-subscription.editor.ts +179 -0
  231. package/template_scaffold/src/steps/editor/paywall.editor.ts +232 -0
  232. package/template_scaffold/src/steps/editor/step-01.editor.ts +22 -0
  233. package/template_scaffold/src/steps/editor/step-02.editor.ts +41 -0
  234. package/template_scaffold/src/steps/editor/step-03.editor.ts +58 -0
  235. package/template_scaffold/src/steps/editor/step-04.editor.ts +98 -0
  236. package/template_scaffold/src/steps/editor/step-32-paywall.editor.ts +478 -0
  237. package/template_scaffold/src/steps/editor/subscription-started.editor.ts +131 -0
  238. package/template_scaffold/src/steps/index.ts +25 -0
  239. package/template_scaffold/src/steps/paywall-checkout-options.test.ts +104 -0
  240. package/template_scaffold/src/steps/paywall-checkout-options.ts +130 -0
  241. package/template_scaffold/src/steps/pricing/paywall-b.pricing.ts +12 -0
  242. package/template_scaffold/src/steps/pricing/paywall.pricing.ts +12 -0
  243. package/template_scaffold/src/steps/pricing/shared-plan-order.ts +17 -0
  244. package/template_scaffold/src/steps/pricing/upsell-form.pricing.ts +16 -0
  245. package/template_scaffold/src/steps/shared-header-contract.test.ts +27 -0
  246. package/template_scaffold/src/steps/step-01.test.ts +38 -0
  247. package/template_scaffold/src/steps/step-01.tsx +108 -0
  248. package/template_scaffold/src/steps/step-02.test.ts +43 -0
  249. package/template_scaffold/src/steps/step-02.tsx +140 -0
  250. package/template_scaffold/src/steps/step-03.test.ts +15 -0
  251. package/template_scaffold/src/steps/step-03.tsx +262 -0
  252. package/template_scaffold/src/steps/step-04.test.ts +32 -0
  253. package/template_scaffold/src/steps/step-04.tsx +673 -0
  254. package/template_scaffold/src/steps/step-31-email-capture.test.ts +22 -0
  255. package/template_scaffold/src/steps/step-31-email-capture.tsx +195 -0
  256. package/template_scaffold/src/steps/step-32-paywall.test.ts +770 -0
  257. package/template_scaffold/src/steps/step-32-paywall.tsx +2253 -0
  258. package/template_scaffold/src/steps/step-32b-paywall-b.tsx +35 -0
  259. package/template_scaffold/src/steps/step-33-subscription-started.test.ts +26 -0
  260. package/template_scaffold/src/steps/step-33-subscription-started.tsx +86 -0
  261. package/template_scaffold/src/steps/step-34-upsell-form.test.ts +27 -0
  262. package/template_scaffold/src/steps/step-35-manage-subscription.tsx +46 -0
  263. package/template_scaffold/src/steps/step-content.registry.ts +45 -0
  264. package/template_scaffold/src/steps/step-image-migration.test.ts +20 -0
  265. package/template_scaffold/src/steps/styles/index.css +2 -0
  266. package/template_scaffold/src/steps/styles/shared/final-flow-shared.css +55 -0
  267. package/template_scaffold/src/steps/styles/shared/funnel-base.css +543 -0
  268. package/template_scaffold/src/steps/styles/shared/info-shared.css +139 -0
  269. package/template_scaffold/src/steps/styles/shared/progress-shared.css +117 -0
  270. package/template_scaffold/src/steps/styles/shared/question-shared.css +76 -0
  271. package/template_scaffold/src/steps/styles/shared/responsive-container.css +176 -0
  272. package/template_scaffold/src/steps/types.ts +7 -0
  273. package/template_scaffold/src/steps/use-claimbee-step-content.ts +15 -0
  274. package/template_scaffold/src/theme/theme.ts +81 -0
  275. package/template_scaffold/tsconfig.json +38 -0
  276. package/template_scaffold/vitest.config.ts +32 -0
  277. package/template_validation/.funnelsgrove-contract-tools.json +19 -0
  278. package/template_validation/src/contract/funnel-project.validation.ts +44 -0
  279. package/template_validation/src/contract/funnel-validator.vite.config.ts +11 -0
  280. package/template_validation/src/contract/validate-funnel.cli.ts +199 -0
  281. package/template_docs/docs/ab-experiments.md +0 -55
  282. package/template_docs/docs/analytics.md +0 -65
  283. package/template_docs/docs/editing-flow.md +0 -125
  284. package/template_docs/docs/editing-step.md +0 -125
  285. package/template_docs/docs/editor-and-content.md +0 -58
  286. package/template_docs/docs/funnel-runtime-architecture.md +0 -125
  287. package/template_docs/docs/meta-pixel-conversions-api.md +0 -50
  288. package/template_docs/docs/payment-plans-and-discounts.md +0 -106
  289. package/template_docs/docs/publishing-and-versioning.md +0 -117
  290. package/template_docs/docs/qa-checklist.md +0 -80
  291. package/template_docs/docs/sdk-api-endpoints.md +0 -78
  292. package/template_docs/docs/step-ui-guidelines.md +0 -110
  293. 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,5 @@
1
+ # Compatibility: flow configuration and routing
2
+
3
+ Use the canonical [flow routing contract](funnelsgrove/contracts/flow-routing.md).
4
+
5
+ This compatibility page intentionally contains no copied routing rules.
@@ -0,0 +1,5 @@
1
+ # Compatibility: paywall and payments
2
+
3
+ Use the canonical [payments contract](funnelsgrove/contracts/payments.md).
4
+
5
+ This compatibility page intentionally contains no copied paywall taxonomy or provider rules.
@@ -0,0 +1,5 @@
1
+ # Compatibility: funnel template documentation
2
+
3
+ Start with the canonical [FunnelsGrove agent contract](funnelsgrove/START-HERE.md).
4
+
5
+ The canonical router links step types, recipes, QA, analytics, routing, answers, payments, and migration guidance.
@@ -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.