@wix/agent-skills 1.16.3 → 1.18.0

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 (283) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +115 -12
  3. package/skills/wix-app/references/APP_MARKET_REVIEW.md +1 -1
  4. package/skills/wix-app/references/BACKEND_API.md +18 -0
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +6 -0
  6. package/skills/wix-app/references/DASHBOARD_MODAL.md +10 -2
  7. package/skills/wix-app/references/DASHBOARD_PAGE.md +32 -70
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +145 -127
  9. package/skills/wix-app/references/SITE_PLUGIN.md +14 -2
  10. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +74 -68
  11. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
  12. package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +79 -0
  13. package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +73 -0
  14. package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +52 -0
  15. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +184 -0
  16. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
  17. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +94 -49
  18. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +16 -6
  19. package/skills/wix-app/references/editor-react-component/BROWSER-SUPPORT.md +56 -0
  20. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
  21. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +35 -40
  22. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +167 -445
  23. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +56 -29
  24. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
  25. package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
  26. package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
  27. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +11 -3
  28. package/skills/wix-app/references/editor-react-component/PARTS.md +46 -24
  29. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
  30. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
  31. package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
  32. package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
  33. package/skills/wix-base44-connector/SKILL.md +156 -50
  34. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +78 -0
  35. package/skills/wix-base44-connector/scripts/utils.js +239 -45
  36. package/skills/wix-headless/entry/bootstrap.mjs +9 -2
  37. package/skills/wix-headless/entry/skill.md +1 -1
  38. package/skills/wix-headless/references/CAPABILITIES.md +9 -1
  39. package/skills/wix-headless/references/DESIGN.md +1 -0
  40. package/skills/wix-headless/references/DISCOVERY.md +2 -1
  41. package/skills/wix-headless/references/IMAGE_GENERATION.md +1 -0
  42. package/skills/wix-headless/references/SDK_HANDOFF.md +5 -2
  43. package/skills/wix-headless/references/SEED.md +2 -1
  44. package/skills/wix-headless/references/SETUP.md +1 -0
  45. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +2 -2
  46. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +68 -31
  47. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +26 -10
  48. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +8 -8
  49. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +1 -1
  50. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +1 -1
  51. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
  52. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +254 -0
  53. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
  54. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +13 -0
  55. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +254 -0
  56. package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
  57. package/skills/wix-headless/references/non-astro.md +1 -1
  58. package/skills/wix-headless-fast/SKILL.md +166 -0
  59. package/skills/wix-headless-fast/entry/skill.md +99 -0
  60. package/skills/wix-headless-fast/install/deploy.mjs +433 -0
  61. package/skills/wix-headless-fast/install/fast-path.mjs +141 -0
  62. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +137 -0
  63. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +137 -0
  64. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +113 -0
  65. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +42 -0
  66. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +123 -0
  67. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +70 -0
  68. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +99 -0
  69. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +76 -0
  70. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +62 -0
  71. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +40 -0
  72. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +99 -0
  73. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +24 -0
  74. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +16156 -0
  75. package/skills/wix-headless-fast/references/blog/seed/SEED.md +72 -0
  76. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +287 -0
  77. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +129 -0
  78. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +143 -0
  79. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +119 -0
  80. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +138 -0
  81. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +54 -0
  82. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +206 -0
  83. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +96 -0
  84. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +70 -0
  85. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +40 -0
  86. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +76 -0
  87. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +22 -0
  88. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +11962 -0
  89. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +61 -0
  90. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +302 -0
  91. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +179 -0
  92. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +83 -0
  93. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +57 -0
  94. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +151 -0
  95. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +75 -0
  96. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +41 -0
  97. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +11262 -0
  98. package/skills/wix-headless-fast/references/cms/seed/SEED.md +103 -0
  99. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +324 -0
  100. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +149 -0
  101. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +66 -0
  102. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +176 -0
  103. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +118 -0
  104. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +117 -0
  105. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +59 -0
  106. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +136 -0
  107. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +128 -0
  108. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +61 -0
  109. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +40 -0
  110. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +12 -0
  111. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +80 -0
  112. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +21 -0
  113. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +11884 -0
  114. package/skills/wix-headless-fast/references/events/seed/SEED.md +86 -0
  115. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +276 -0
  116. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +150 -0
  117. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +317 -0
  118. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +269 -0
  119. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +231 -0
  120. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +135 -0
  121. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +10593 -0
  122. package/skills/wix-headless-fast/references/forms/seed/SEED.md +108 -0
  123. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +320 -0
  124. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +63 -0
  125. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +60 -0
  126. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +155 -0
  127. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +78 -0
  128. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +47 -0
  129. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +66 -0
  130. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +88 -0
  131. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +53 -0
  132. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +122 -0
  133. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +50 -0
  134. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +21 -0
  135. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +42 -0
  136. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +10 -0
  137. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +11 -0
  138. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +10329 -0
  139. package/skills/wix-headless-fast/references/members/seed/SEED.md +39 -0
  140. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +94 -0
  141. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +134 -0
  142. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
  143. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
  144. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +115 -0
  145. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +59 -0
  146. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +39 -0
  147. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +58 -0
  148. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +165 -0
  149. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +55 -0
  150. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
  151. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
  152. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +21 -0
  153. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +29 -0
  154. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +10197 -0
  155. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +78 -0
  156. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +258 -0
  157. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +133 -0
  158. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +58 -0
  159. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +126 -0
  160. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +37 -0
  161. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +39 -0
  162. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +75 -0
  163. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +45 -0
  164. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +30 -0
  165. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
  166. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +40 -0
  167. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +21 -0
  168. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +11226 -0
  169. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +71 -0
  170. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +279 -0
  171. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +165 -0
  172. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +142 -0
  173. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
  174. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
  175. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +155 -0
  176. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +55 -0
  177. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +43 -0
  178. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +177 -0
  179. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +165 -0
  180. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +103 -0
  181. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +254 -0
  182. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +146 -0
  183. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +168 -0
  184. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
  185. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +22 -0
  186. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +12 -0
  187. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +12560 -0
  188. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +81 -0
  189. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +479 -0
  190. package/skills/wix-headless-fast/references/shared/CONTENT.md +22 -0
  191. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +73 -0
  192. package/skills/wix-headless-fast/references/shared/DESIGN.md +26 -0
  193. package/skills/wix-headless-fast/references/shared/app/styles/global.css +52 -0
  194. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +15 -0
  195. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +27 -0
  196. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +24 -0
  197. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +76 -0
  198. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
  199. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +46 -0
  200. package/skills/wix-headless-fast/references/shared/seed/images.mjs +145 -0
  201. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +149 -0
  202. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +26 -0
  203. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +121 -0
  204. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +100 -0
  205. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +130 -0
  206. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +48 -0
  207. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +66 -0
  208. package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +103 -0
  209. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +48 -0
  210. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +140 -0
  211. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +80 -0
  212. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +101 -0
  213. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +221 -0
  214. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +215 -0
  215. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +109 -0
  216. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +46 -0
  217. package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +56 -0
  218. package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +23 -0
  219. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +12247 -0
  220. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +85 -0
  221. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +415 -0
  222. package/skills/wix-manage/SKILL.md +28 -2
  223. package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
  224. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
  225. package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
  226. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +141 -0
  227. package/skills/wix-manage/references/google-business-profile/connect-google-business-profile.md +134 -0
  228. package/skills/wix-manage/references/google-business-profile/manage-google-business-profile-locations.md +182 -0
  229. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +3 -0
  230. package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
  231. package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
  232. package/skills/wix-manage/references/sites/query-sites.md +72 -161
  233. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +21 -6
  234. package/skills/wix-manage/references/stores/update-product-with-options.md +83 -0
  235. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
  236. package/skills/wix-vibe-headless/SKILL.md +18 -4
  237. package/skills/wix-vibe-headless/install/deploy.cjs +12 -4
  238. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +2 -1
  239. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +16 -10
  240. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +13 -8
  241. package/skills/wix-vibe-headless/platforms/base44.md +27 -62
  242. package/skills/wix-vibe-headless/platforms/generic.md +6 -3
  243. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +45 -0
  244. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +67 -0
  245. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +128 -0
  246. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +5 -3
  247. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
  248. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +250 -0
  249. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +12 -5
  250. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +41 -0
  251. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.js +267 -0
  252. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +6 -3
  253. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +470 -0
  254. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +425 -0
  255. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +187 -0
  256. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +238 -0
  257. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +108 -0
  258. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1762 -0
  259. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +13 -0
  260. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
  261. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
  262. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
  263. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
  264. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +152 -92
  265. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
  266. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
  267. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +15 -8
  268. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +37 -0
  269. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
  270. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +18 -6
  271. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +30 -7
  272. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +46 -10
  273. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
  274. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
  275. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -516
  276. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
  277. package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
  278. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
  279. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +0 -110
  280. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +0 -51
  281. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +0 -49
  282. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +0 -92
  283. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +0 -139
@@ -24,22 +24,24 @@ A concise contract for writing the **frontend code** of a storefront against a C
24
24
  | Products (list, get, search, filter) | `@wix/stores` | `productsV3` |
25
25
  | Variants (to resolve `variantId`) | `@wix/stores` | `readOnlyVariantsV3` |
26
26
  | Categories | `@wix/stores` | `categories` |
27
- | Cart (add / get / checkout) | `@wix/ecom` | `currentCart` |
27
+ | Cart (add / get / checkout) | `@wix/ecom` | `currentCartV2` |
28
28
  | Redirect to hosted checkout | `@wix/redirects` | `redirects` |
29
29
 
30
+ > Migrating from Cart V1 / Checkout V1? The code below is V2-only — see the [migration guide](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/migration-guide) for the before/after.
31
+
30
32
  **Never** import the V1 `products` or `collections` modules from `@wix/stores`.
31
33
 
32
34
  **Auth / client — framework split:**
33
- - **Astro (Wix-managed):** authentication is ambient. Call `currentCart` / `productsV3` / `readOnlyVariantsV3` directly from server components and backend routes (`src/pages/api/*.ts`) — **no `createClient`, no `OAuthStrategy`, no `clientId`.**
35
+ - **Astro (Wix-managed):** authentication is ambient. Call `currentCartV2` / `productsV3` / `readOnlyVariantsV3` directly from server components and backend routes (`src/pages/api/*.ts`) — **no `createClient`, no `OAuthStrategy`, no `clientId`.**
34
36
  - **Non-Astro (Vite/React/Vue/static):** build one manual visitor client and reuse it:
35
37
  ```js
36
38
  import { createClient, OAuthStrategy } from '@wix/sdk';
37
39
  import { productsV3, readOnlyVariantsV3 } from '@wix/stores';
38
- import { currentCart } from '@wix/ecom';
40
+ import { currentCartV2 } from '@wix/ecom';
39
41
  import { redirects } from '@wix/redirects';
40
42
 
41
43
  const client = createClient({
42
- modules: { productsV3, readOnlyVariantsV3, currentCart, redirects },
44
+ modules: { productsV3, readOnlyVariantsV3, currentCartV2, redirects },
43
45
  auth: OAuthStrategy({ clientId: /* the project's PUBLIC OAuth client id */ }),
44
46
  });
45
47
  ```
@@ -49,16 +51,19 @@ A concise contract for writing the **frontend code** of a storefront against a C
49
51
 
50
52
  ## The shapes you read (field cheat-sheet)
51
53
 
52
- The exact field paths the storefront reads, and the **plausible-wrong sibling** each is mistaken for — the sections below reference these instead of re-describing them. All `amount`s are **strings**. These are **read** shapes; the cart-add body (under *Adding to cart*) is a separate **write** shape, and the `_id` rule applies to read **entities**, not to method-return wrappers (note `checkoutId`).
54
+ The exact field paths the storefront reads, and the **plausible-wrong sibling** each is mistaken for — the sections below reference these instead of re-describing them. All `amount`s are **strings**. These are **read** shapes; the cart-add body (under *Adding to cart*) is a separate **write** shape, and the `_id` rule applies to read **entities**, not to request params (note the redirect session's `checkoutId`, which is just the cart's `_id`).
53
55
 
54
56
  ```jsonc
55
- // productsV3.queryProducts().…find() → result.items[]
56
- // productsV3.searchProducts({...}) → result.products[]
57
+ // Request CURRENCY and PLAIN_DESCRIPTION on every product read — they populate formattedAmount and plainDescription.
58
+ const PRODUCT_FIELDS = ['CURRENCY', 'PLAIN_DESCRIPTION'];
59
+ // productsV3.queryProducts({ fields: PRODUCT_FIELDS }).…find() → result.items[]
60
+ // productsV3.searchProducts({ ..., fields: PRODUCT_FIELDS }) → result.products[]
57
61
  product = {
58
62
  _id, // links · cart catalogItemId · variant filter (NOT .id → empty → HTTP 500)
59
63
  slug, name, visible, // only visible:true is returned to a visitor token
60
- actualPriceRange: { minValue: { amount } }, // PRICE (NOT price.actualPrice.amount — that's the seed/WRITE shape → $NaN)
61
- compareAtPriceRange: { minValue: { amount } }, // strike-through price
64
+ currency, // present when CURRENCY is requested
65
+ actualPriceRange: { minValue: { amount, formattedAmount } }, // PRICE (NOT price.actualPrice.amount — that's the seed/WRITE shape → $NaN)
66
+ compareAtPriceRange: { minValue: { amount, formattedAmount } }, // strike-through price
62
67
  inventory: { availabilityStatus }, // product-level stock, "IN_STOCK"
63
68
  media: { main: { image } }, // image is a wix:image:// id → resolve it (see Rendering images)
64
69
  plainDescription, // plain string; description.nodes is the rich-text form
@@ -72,11 +77,12 @@ variant = {
72
77
  inventoryStatus: { inStock }, // variant-level stock (boolean)
73
78
  }
74
79
 
75
- // currentCart.getCurrentCart() → { lineItems: [...] }
76
- lineItem = { quantity, price: { amount }, image } // price is HERE (NOT actualPriceRange); image is wix:image:// too → resolve
80
+ // currentCartV2.getCurrentCart() → { cart: { _id, lineItems: [...] } } // NOTE: returns { cart } — destructure it
81
+ lineItem = { _id, name: { original }, quantityInfo: { confirmedQuantity }, pricing: { unitPrice: { amount } }, attributes: { image } }
82
+ // price → pricing.unitPrice (ConvertedMoney, NO formatted string in V2 — format it yourself; .amount is site currency, .convertedAmount the buyer's display currency); qty → quantityInfo.confirmedQuantity; image → attributes.image (wix:image:// → resolve)
77
83
 
78
- // currentCart.createCheckoutFromCurrentCart({ channelType }) → { checkoutId } // a STRING — NOT { checkout }, NOT _id
79
- // redirects.createRedirectSession({ ecomCheckout: { checkoutId }, callbacks }) → { redirectSession: { fullUrl } }
84
+ // the cart's _id is the checkout id → pass to the redirect session:
85
+ // redirects.createRedirectSession({ ecomCheckout: { checkoutId: cart._id }, callbacks }) → { redirectSession: { fullUrl } }
80
86
  ```
81
87
 
82
88
  ---
@@ -87,18 +93,30 @@ Each section below is a **self-contained storefront feature** — implement only
87
93
 
88
94
  ### Listing products (and the `_id` rule)
89
95
 
90
- Query products with `productsV3.queryProducts()` / `.searchProducts()`.
96
+ Query products with `productsV3.queryProducts()` / `.searchProducts()`. **Every product listing,
97
+ category search, and detail read must request `CURRENCY` and `PLAIN_DESCRIPTION`**. Without `CURRENCY`, `formattedAmount` is omitted
98
+ and a product card renders an unsymbolled number such as `34.99` instead of a localized price. Without `PLAIN_DESCRIPTION`, `product.plainDescription` is absent for cards and detail pages.
91
99
  Doc: <https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/query-products.md?apiView=SDK>
92
100
 
93
- **⚠️ `queryProducts()` takes NO arguments — it returns a builder, not a Promise.** Chain `.eq(...)`/`.limit(...)`/`.find()` on it (e.g. `await productsV3.queryProducts().limit(50).find()`). Passing a query object (`queryProducts({...})`) does **not** type-check and returns a `Promise` that has no `.limit`/`.eq`/`.find` to chain — if the SDK reference page shows a `(query, options)→Promise` signature, trust the installed no-arg builder over that example. (`searchProducts` is the one that *does* take a query — see category filtering below.)
101
+ **⚠️ `queryProducts()` returns a builder, not a Promise.** Pass requested fields when needed, then chain `.eq(...)`/`.limit(...)`/`.find()` — for example:
102
+
103
+ ```js
104
+ const PRODUCT_FIELDS = ['CURRENCY', 'PLAIN_DESCRIPTION'];
105
+ const { items } = await productsV3
106
+ .queryProducts({ fields: PRODUCT_FIELDS })
107
+ .limit(50)
108
+ .find();
109
+ ```
110
+
111
+ Do not pass a search/filter object to `queryProducts`; use `searchProducts` for that (see category filtering below). Reuse the same `PRODUCT_FIELDS` constant for every product read so home, shop, category, and detail pages cannot drift.
94
112
 
95
113
  **⚠️ CRITICAL: the entity id is `_id`, NOT `id`.** The SDK normalizes every entity's id to **`_id`**. `product.id` is `undefined` in SDK code. This is the cart-killer: feeding `product.id` into the cart's `catalogItemId` sends an empty string and the add returns **HTTP 500** (`"catalogItemId" has size 0`). Use `product._id` everywhere — in links, as the cart `catalogItemId`, and as the variant-query filter value. (If a field name surprises you, you are probably reading the REST doc view — re-open it with `?apiView=SDK`.)
96
114
 
97
- **Scope of the `_id` rule — entity reads only.** `_id` is the id of a read **entity** (product, variant, cart line item). It is **not** a universal "every id field is `_id`" rule: method results name their own fields (e.g. `createCheckoutFromCurrentCart` returns `checkoutId`, *not* `_id` — see Checkout). Don't assume a method's return wrapper exposes `_id`.
115
+ **Scope of the `_id` rule — entity reads only.** `_id` is the id of a read **entity** (product, variant, cart line item). It is **not** a universal "every id field is `_id`" rule: request params name their own fields (e.g. the redirect session takes `ecomCheckout.checkoutId`, *not* `_id` — see the *Checkout* section below — even though the value you pass is the cart's `_id`). Don't assume every id-shaped field is spelled `_id`.
98
116
 
99
117
  **Visibility:** only `visible: true` products are returned to a visitor token, so a missing product usually means it wasn't seeded visible — not a query bug.
100
118
 
101
- **Price** comes from `actualPriceRange.minValue.amount` (see the cheat-sheet) — **not** `price.actualPrice.amount` (the seed/write shape), which reads `undefined` → `$NaN`.
119
+ **Price:** after requesting `CURRENCY`, render `actualPriceRange.minValue.formattedAmount` (and the matching `compareAtPriceRange` value) directly. Fall back to raw `.amount` only if the formatted value is unexpectedly absent. Never use `price.actualPrice.amount`: that is the seed/write shape and reads `undefined` → `$NaN`.
102
120
 
103
121
  ### Category navigation — list categories live
104
122
 
@@ -111,7 +129,7 @@ const res = await categories.queryCategories({
111
129
  }).exists('name', true).find(); // read the returned array per the SDK doc; ids are `_id`; link each to /category/<slug>
112
130
  ```
113
131
 
114
- **⚠️ The query MUST carry a filter condition — chain `.exists('name', true)` (as above), do NOT call a bare `.find()`.** A `.find()` with no chained filter serializes an empty `"filter": {}`, which `categories/v1/categories/query` rejects with `400 INVALID_FILTER` ("Filter expression cannot contain an empty condition"). **This is fatal on the visitor/manual-client (non-Astro) path** — the call throws and the nav never renders; managed-Astro's server-side transport happens to tolerate the empty filter, so a bare `.find()` *looks* fine there but breaks the moment the same code runs client-side. `.exists('name', true)` is a tautology (every category has a `name`), so it matches **all** categories and is accepted on **both** paths — use this one shape everywhere. **Do NOT filter on `visible`** (`.eq('visible', true)`): unlike `name`, `visible` is **not declared filterable** on `queryCategories`, so it triggers a silently-swallowed `400` and the nav renders blank; if you ever need to hide a category, filter the returned array **client-side**. (`getCategoryBySlug(slug, { appNamespace: '@wix/stores' })` on the category page is unaffected — it takes no query filter.) This is a **distinct API from bookings' `categoriesV2`** — don't copy that module's query shape here; read the exact result-array key + field names from the `@wix/categories` SDK doc: <https://dev.wix.com/docs/sdk/business-solutions/categories/introduction.md?apiView=SDK>.
132
+ **⚠️ The query MUST carry a filter condition — chain `.exists('name', true)` (as above), do NOT call a bare `.find()`.** A `.find()` with no chained filter serializes an empty `"filter": {}`, which `categories/v1/categories/query` rejects with `400 INVALID_FILTER` ("Filter expression cannot contain an empty condition"). **This is fatal on the visitor/manual-client (non-Astro) path** — the call throws and the nav never renders; managed-Astro's server-side transport happens to tolerate the empty filter, so a bare `.find()` *looks* fine there but breaks the moment the same code runs client-side. `.exists('name', true)` is a tautology (every category has a `name`), so it matches **all** categories and is accepted on **both** paths — use this one shape everywhere. **Do NOT filter on `visible`** (`.eq('visible', true)`): unlike `name`, `visible` is **not declared filterable** on `queryCategories`, so it triggers a silently-swallowed `400` and the nav renders blank; if you ever need to hide a category, filter the returned array **client-side**. (`getCategoryBySlug(slug, { appNamespace: '@wix/stores' })` on the category page is unaffected — it takes no query filter.) This is a **distinct API from bookings' `categoriesV2`** — don't copy that module's query shape here; read the exact result-array key + field names from the `@wix/categories` SDK doc: <https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/categories/introduction.md?apiView=SDK>.
115
133
 
116
134
  ### Filtering products by category
117
135
 
@@ -122,6 +140,7 @@ const res = await categories.queryCategories({
122
140
  ```js
123
141
  const { products } = await productsV3.searchProducts({
124
142
  filter: { 'directCategoriesInfo.categories': { $matchItems: [{ id: categoryId }] } },
143
+ fields: PRODUCT_FIELDS,
125
144
  });
126
145
  ```
127
146
 
@@ -149,11 +168,11 @@ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v
149
168
 
150
169
  Each `variant` carries `variant.optionChoices[].optionChoiceNames` — `{ optionName, choiceName }`. Match the buyer's selected options (Size = "Small", Color = "Red", …) against those names to pick the variant. For a **single-variant** product, use the only item. Fall back to `items[0]` if matching yields nothing. The id to send to the cart is **`variant.variantId ?? variant._id`**.
151
170
 
152
- **2 · Add it.** Doc: <https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart/add-to-current-cart.md?apiView=SDK> · catalogReference contract: <https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/e-commerce-integration.md?apiView=SDK>
171
+ **2 · Add it.** Doc: <https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/add-line-items-to-current-cart.md?apiView=SDK> · catalogReference contract: <https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/e-commerce-integration.md?apiView=SDK>
153
172
 
154
173
  ```js
155
- await currentCart.addToCurrentCart({
156
- lineItems: [{
174
+ await currentCartV2.addLineItemsToCurrentCart({
175
+ catalogItems: [{ // the write shape uses `catalogItems`
157
176
  quantity,
158
177
  catalogReference: {
159
178
  catalogItemId: product._id, // the product's _id (the `_id` rule above)
@@ -164,28 +183,46 @@ await currentCart.addToCurrentCart({
164
183
  });
165
184
  ```
166
185
 
167
- **⚠️ CRITICAL: `options.variantId` is MANDATORY for any product that has variants.** Adding by `catalogItemId` alone returns **HTTP 200 but adds nothing** — the silent empty cart. The cart method's required-params list omits `variantId`, so this fails quietly and looks like success. Always resolve and include it (part 1 above).
186
+ **⚠️ CRITICAL: `options.variantId` is MANDATORY for any product that has variants.** Adding by `catalogItemId` alone **fails** — the catalog can't resolve a variant-bearing product without it, and Cart V2 **rejects the add with an explicit error** rather than accepting an invalid line. The cart method's required-params list omits `variantId`, so it's an easy one to miss. Always resolve and include it (part 1 above).
187
+
188
+ **CRITICAL: `ITEM_NOT_FOUND_IN_CATALOG` for a product that exists is a catalog defect, not a stale id.** A `DIGITAL` product whose variant has no `digitalProperties.digitalFile` is rejected under that code, and one with no stock is rejected as `exceeds available inventory` — both read back `visible: true` and in the catalog. Fix the product (`setup-online-store.md` → digital products); re-reading ids won't help.
168
189
 
169
- **⚠️ CRITICAL: `options.options` is for MODIFIERS, not variant selection.** Product option selections (Size/Color) are resolved to a **variant** and referenced by `variantId`. `options.options` is only for free-text / TEXT_CHOICES add-on **modifiers**. Do **not** encode Size/Color as `options.options` — that is the coffee-grind bug (`200` + empty cart).
190
+ **⚠️ CRITICAL: `options.options` is for MODIFIERS, not variant selection.** Product option selections (Size/Color) are resolved to a **variant** and referenced by `variantId`. `options.options` is only for free-text / TEXT_CHOICES add-on **modifiers**. Do **not** encode Size/Color as `options.options` — that is the coffee-grind bug: the variant never resolves, so Cart V2 rejects the add with an explicit error.
170
191
 
171
- ### Checkout
192
+ ### Checkout — redirect to the hosted checkout page
172
193
 
173
- Create a checkout from the current cart, then redirect the buyer to the hosted checkout.
174
- Docs: <https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart/create-checkout-from-current-cart.md?apiView=SDK> · <https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart/get-current-cart.md?apiView=SDK>
194
+ The cart's `_id` **is** the checkout id — pass it into the redirect session's `ecomCheckout.checkoutId`. Read the current cart, then hand its id to a redirect session, which carries the visitor/member session across to the hosted checkout on its own domain.
195
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/get-current-cart.md?apiView=SDK>
175
196
 
176
197
  ```js
177
- const checkout = await currentCart.createCheckoutFromCurrentCart({ channelType: currentCart.ChannelType.WEB });
198
+ const { cart } = await currentCartV2.getCurrentCart(); // NOTE: returns { cart } — destructure it
178
199
  const session = await redirects.createRedirectSession({
179
- ecomCheckout: { checkoutId: checkout.checkoutId }, // checkout.checkoutId — NOT checkout._id
200
+ ecomCheckout: { checkoutId: cart._id }, // the cart's _id IS the checkout id
180
201
  callbacks: { postFlowUrl: `${origin}/`, thankYouPageUrl: `${origin}/` },
181
202
  });
182
203
  window.location.href = session.redirectSession.fullUrl; // the hosted-checkout URL
183
204
  ```
184
205
 
185
- **⚠️ Return shapes are in the cheat-sheet** — `createCheckoutFromCurrentCart` gives **`checkout.checkoutId`** (a string), not `checkout._id`. Reading `checkout._id` (over-applying the `_id` rule) throws *"Cannot read properties of undefined (reading '_id')"* — the silent checkout crash.
206
+ **⚠️ The cart's `_id` is the checkout id.** Pass `cart._id` straight into the redirect session's `ecomCheckout.checkoutId`. And `getCurrentCart()` returns **`{ cart }`** — destructure it, or `cart` is `undefined` and `cart._id` throws *"Cannot read properties of undefined (reading '_id')"*.
186
207
 
187
208
  **⚠️ CRITICAL: `origin` for `postFlowUrl`/`thankYouPageUrl` MUST be the `https://` published host — derive it from `window.location.origin`, NEVER `new URL(request.url).origin`.** The Headless redirect allowlist registers the site's **`https://`** host and treats **`http://<same host>` as a different, unlisted origin**. When the buyer returns from the hosted checkout (e.g. clicks "Continue Browsing"), the redirect goes through the allowlist — and an `http://` `postFlowUrl` **403s** with *"… isn't listed as an allowed redirect domain."* If you build the redirect session in a **server route** (`src/pages/api/*`), `new URL(request.url).origin` resolves to **`http://`** behind Wix's TLS-terminating proxy → guaranteed 403 on return. So **pass `window.location.origin` from the client** into the route (don't read the origin off the request), or force the scheme to `https`. Doc: <https://dev.wix.com/docs/go-headless/getting-started/setup/manage-urls/add-allowed-redirect-domains>.
188
209
 
210
+ ### Formatting cart prices
211
+
212
+ **Product** prices from `productsV3` still carry a ready-to-show `actualPriceRange.minValue.formattedAmount` — use it directly. But **Cart V2 money does not**: every cart amount — line-item `pricing.unitPrice` / `pricing.totalPrice` **and** the `estimateCurrentCart`/`calculateCurrentCart` `summary.priceSummary.*` — is a `ConvertedMoney` `{ amount, convertedAmount }` with **no** formatted string. So once items are in the cart, you format the price yourself. The currency isn't on the money object; read it from the cart (`cart.customerInfo?.currencyCode ?? cart.businessInfo?.currencyCode`), and use `convertedAmount` (buyer's display currency) when present, else `amount` (site currency):
213
+
214
+ ```js
215
+ function formatCartMoney(money, cart) {
216
+ const value = money?.convertedAmount ?? money?.amount;
217
+ const currency = cart?.customerInfo?.currencyCode ?? cart?.businessInfo?.currencyCode ?? 'USD';
218
+ return value == null ? '' : new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(Number(value));
219
+ }
220
+ // e.g. line item: formatCartMoney(item.pricing.totalPrice, cart)
221
+ // subtotal: formatCartMoney(estimate.summary.priceSummary.subtotal, cart)
222
+ ```
223
+
224
+ Never hardcode `$` or assume USD — stores run in EUR/GBP too.
225
+
189
226
  ### Showing stock state
190
227
 
191
228
  Read the **V3** inventory fields: product-level in-stock is `product.inventory.availabilityStatus` (`"IN_STOCK"`); variant-level is `variant.inventoryStatus.inStock`. Reading the V1 inventory field on V3 data returns `undefined` → everything renders out-of-stock (the all-OOS bug). These come from `productsV3` / `readOnlyVariantsV3`, not the V1 module.
@@ -208,7 +245,7 @@ function imgSrc(mediaMain, w = 600, h = 600) {
208
245
 
209
246
  **Never hand-build a `static.wixstatic.com/.../v1/fit/...` URL** either — the format is easy to get wrong and the image then **403s**. Only `wix:image://` values need resolving; an already-absolute `https://` URL goes straight into `<img src>`. Doc: <https://dev.wix.com/docs/sdk/core-modules/sdk/media>
210
247
 
211
- **This applies to cart line-item images too, not just product reads.** A cart `lineItem.image` is the same `wix:image://` identifier — run it through the same `imgSrc()` helper before `<img src>`. (If you build the cart over an API route, resolve there and return a ready URL so the component never sees a `wix:image://`.)
248
+ **This applies to cart line-item images too, not just product reads.** A cart `lineItem.attributes.image` is the same `wix:image://` identifier — run it through the same `imgSrc()` helper before `<img src>`. (If you build the cart over an API route, resolve there and return a ready URL so the component never sees a `wix:image://`.)
212
249
 
213
250
  ### Rendering product descriptions
214
251
 
@@ -230,7 +267,7 @@ Optional: render a `Product` schema.org JSON-LD `<script>` from the fetched prod
230
267
 
231
268
  ## Conclusion
232
269
  A correct Catalog V3 storefront frontend:
233
- - imports **`productsV3` / `readOnlyVariantsV3` / `categories` / `currentCart` / `redirects`** — never the V1 `products`/`collections` modules;
270
+ - imports **`productsV3` / `readOnlyVariantsV3` / `categories` / `currentCartV2` / `redirects`** — never the V1 `products`/`collections` modules;
234
271
  - uses **`product._id`** (never `product.id`) as the cart's `catalogItemId`;
235
272
  - resolves the **mandatory `variantId`** via `readOnlyVariantsV3` and passes it as `options.variantId` (not `options.options`);
236
273
  - builds its category nav from a **live `categories.queryCategories()`** and filters category pages server-side with **`searchProducts` + `$matchItems: [{ id: categoryId }]`** keyed on the live `categoryId` — never a frozen seed-time `productIds` map, never `queryProducts` for category filtering, never `$hasSome`, never V1 `collectionIds`;
@@ -456,7 +456,7 @@ async function submitContact(formEl) {
456
456
  formId: SEEDED_FORM_ID, // from seeded.forms[].formId
457
457
  submissions: values, // map of target -> value (or -> nested object, for an address)
458
458
  });
459
- return { _id, status }; // CONFIRMED → render a thank-you (see the status note below)
459
+ return { _id, status }; // any status → the submission exists; render a thank-you (see the status note below)
460
460
  }
461
461
  ```
462
462
 
@@ -482,13 +482,28 @@ construction, with no hand-maintained list to drift.
482
482
 
483
483
  Both are fixed in `setup-forms.md` STEP 2.
484
484
 
485
- **⚠️ A resolved promise is not always a recorded submission.** Read `status` from the result: for the
486
- Wix Forms namespace it is `CONFIRMED` (recorded — show the thank-you), but a form that collects
487
- payment returns `PAYMENT_WAITING` and some namespaces return `PENDING`, neither of which is recorded
488
- or visible to the owner yet
485
+ **⚠️ Read `status` from the result — but a resolved call means the submission EXISTS, whatever the
486
+ status.** For the Wix Forms namespace it's `CONFIRMED` (recorded). Some namespaces return `PENDING`,
487
+ which is **not yet recorded** in the Wix Forms collection but **is a created submission**;
488
+ `PAYMENT_WAITING` is a created submission on a form that collects payment
489
489
  ([Submission status](https://dev.wix.com/docs/api-reference/crm/forms/form-submissions/introduction#submission-status)).
490
- Since this renderer skips `PAYMENT` fields, treat anything other than `CONFIRMED` as "not done yet"
491
- rather than showing a success state.
490
+
491
+ **All three are a successful submit — show the thank-you.** The visitor has done everything the form
492
+ asked of them; confirming a `PENDING` is a server-side step they play no part in. Showing an error
493
+ instead invites them to submit again, so the cost of getting this wrong is duplicate submissions in
494
+ the owner's inbox for a submission that already exists.
495
+
496
+ `PAYMENT_WAITING` is the same call: the entry is in the owner's inbox and the *submit* succeeded, so
497
+ **never fail it back to the visitor**. Payment is a separate step — surface it *inside* the success
498
+ state (a "complete your payment" link or instruction) rather than as a failed submission. Since this
499
+ renderer skips `PAYMENT` fields it shouldn't arise at all; if it does, the schema has a payment field
500
+ the UI isn't rendering.
501
+
502
+ ```js
503
+ const { _id, status } = await submissions.createSubmission({ formId, submissions: values });
504
+ // CONFIRMED | PENDING | PAYMENT_WAITING → the submission exists. Thank-you either way.
505
+ if (status === "PAYMENT_WAITING") { /* …and surface the payment step within it */ }
506
+ ```
492
507
 
493
508
  **⚠️ Per-field validation errors — the SDK buries them two levels deeper than the docs' shape.** The
494
509
  documented entries (`errorPath`, `errorType`, `errorMessage`, `params` — see
@@ -667,9 +682,10 @@ A correct Wix Forms frontend:
667
682
  `target`** so the `submissions` map is keyed by `target` by construction;
668
683
  - submits on the **plain visitor token with NO `auth.elevate`** (anonymous submit works; a pure SPA
669
684
  can't elevate anyway) and, at the default `ADVANCED` protection, **no captcha**;
670
- - **only writes submissions** — reading them back is owner-only — and treats
671
- **`status === "CONFIRMED"`**, not a resolved promise, as the signal to show the thank-you; reads
672
- the created id as **`result._id`**, never `result.id`;
685
+ - **only writes submissions** — reading them back is owner-only — and shows the thank-you for
686
+ **`CONFIRMED`, `PENDING` *or* `PAYMENT_WAITING`** (all three are created submissions; a payment
687
+ form surfaces the payment step *within* that success state, never as a failed submit); reads the
688
+ created id as **`result._id`**, never `result.id`;
673
689
  - is **accessible by construction** (the inputs are generated, so a slip repeats on every field):
674
690
  each error carries a deterministic id from its `errorPath` and is referenced by `aria-describedby`
675
691
  + `role="alert"` and persisted (not conditionally unmounted); a choice group's error and
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "How to Code Members (Astro)"
3
- description: The frontend contract for member sign-up / log-in / log-out and member-gated surfaces on a Wix-managed **Astro** frontend — the built-in `/api/auth/login` + `/api/auth/logout` routes that `@wix/astro` ships, the `returnUrl` param, gating a page by resolving the member in SSR / a backend route, reading the current member with `@wix/members` `getCurrentMember`, and the two rules that keep this path from breaking: **no `OAuthStrategy`/no client** (that 500s under auto-auth) and **no `auth.elevate`** for a member reading their own data. Specifies the *how* for the Astro axis only — read `how-to-code-members-non-astro.md` for any non-Astro frontend.
3
+ description: The frontend contract for member sign-up / log-in / log-out and member-gated surfaces on a Wix-managed **Astro** frontend — the built-in `/api/auth/login` + `/api/auth/logout` routes that `@wix/astro` ships, the `returnToUrl` param, gating a page by resolving the member in SSR / a backend route, reading the current member with `@wix/members` `getCurrentMember`, and the two rules that keep this path from breaking: **no `OAuthStrategy`/no client** (that 500s under auto-auth) and **no `auth.elevate`** for a member reading their own data. Specifies the *how* for the Astro axis only — read `how-to-code-members-non-astro.md` for any non-Astro frontend.
4
4
  ---
5
5
  **RECIPE**: How to Code Member Auth on a Wix-managed **Astro** Frontend (built-in `/api/auth/*`, `@wix/members`)
6
6
 
@@ -39,16 +39,16 @@ So a paywall that only needs "logged-in vs not" runs on identity alone; anything
39
39
  <a href="/api/auth/login">Log in / Sign up</a>
40
40
 
41
41
  <!-- land the member somewhere specific afterward -->
42
- <a href="/api/auth/login?returnUrl=/account">Log in</a>
42
+ <a href="/api/auth/login?returnToUrl=/account">Log in</a>
43
43
  ```
44
44
 
45
- Logout is a **POST** to `/api/auth/logout` (optionally with `?returnUrl=`):
45
+ Logout is a **POST** to `/api/auth/logout` (optionally with `?returnToUrl=`):
46
46
 
47
47
  ```astro
48
48
  <form method="POST" action="/api/auth/logout"><button>Log out</button></form>
49
49
  ```
50
50
 
51
- - **`returnUrl` must be an allowed redirect URI.** When the project is created with that URL it's auto-added; an un-allow-listed `returnUrl` fails the redirect. Default to a relative path already known-good (the login page auto-allows the project's own origin paths).
51
+ - **The param is `returnToUrl` — not `returnUrl`.** The routes validate their query with a strict schema that silently DROPS unknown params, so a misspelled param doesn't error — the member just lands on `/`. The value must be a **relative path** (the callback refuses absolute URLs).
52
52
  - After login the member identity **rides on every subsequent SDK call automatically** — no client, no token handling. That's auto-auth (`astro.md`).
53
53
 
54
54
  ---
@@ -67,14 +67,14 @@ try {
67
67
  me = res.member ?? null;
68
68
  } catch { /* not a member / not installed — treat as anonymous */ }
69
69
 
70
- if (!me) return Astro.redirect('/api/auth/login?returnUrl=/account');
70
+ if (!me) return Astro.redirect('/api/auth/login?returnToUrl=/account');
71
71
  ---
72
72
  <h1>Welcome, {me.profile?.nickname ?? me.loginEmail}</h1>
73
73
  ```
74
74
 
75
75
  - **Guard the SSR call in `try/catch`** — an unguarded throw truncates the response mid-stream (white screen; `astro.md` A3). An anonymous visitor is a normal state, not an error: catch → treat as logged-out → redirect to login.
76
76
  - **Don't render account/gated UI as a client island that checks auth in the browser.** Resolve identity server-side and gate the route; render only what a member should see. (Same reasoning as the blog-comment API-endpoint path — avoid the browser-auth detour.)
77
- - For an **action** that only *some* callers may take (post a comment, place a member order), don't gate the whole page: render the control always, and on submit POST to a `src/pages/api/*.ts` endpoint that resolves the session and, if the caller isn't a member, redirects to `/api/auth/login?returnUrl=…`.
77
+ - For an **action** that only *some* callers may take (post a comment, place a member order), don't gate the whole page: render the control always, and on submit POST to a `src/pages/api/*.ts` endpoint that resolves the session and, if the caller isn't a member, redirects to `/api/auth/login?returnToUrl=…`.
78
78
 
79
79
  ---
80
80
 
@@ -116,8 +116,8 @@ So: browsing the plans grid is public, but the **subscribe** button and the **my
116
116
 
117
117
  ## Conclusion
118
118
  Correct member auth on an Astro frontend:
119
- - uses the **built-in `/api/auth/login`** (login *and* sign-up) and **POST `/api/auth/logout`** routes with an allow-listed `returnUrl` — the login handshake **never** builds an `OAuthStrategy` client, and one must never be built in **SSR frontmatter** (the public-env `clientId` is `undefined` at server render → 500). (The one exception is the custom-login surface — `how-to-code-members-custom-login.md` — which builds an explicit client in a backend route or client island, never in SSR frontmatter.)
120
- - gates surfaces **server-side** (SSR frontmatter or a `src/pages/api/*.ts` route), guarded in `try/catch`, bouncing anonymous visitors to `/api/auth/login?returnUrl=…`;
119
+ - uses the **built-in `/api/auth/login`** (login *and* sign-up) and **POST `/api/auth/logout`** routes with an allow-listed `returnToUrl` — the login handshake **never** builds an `OAuthStrategy` client, and one must never be built in **SSR frontmatter** (the public-env `clientId` is `undefined` at server render → 500). (The one exception is the custom-login surface — `how-to-code-members-custom-login.md` — which builds an explicit client in a backend route or client island, never in SSR frontmatter.)
120
+ - gates surfaces **server-side** (SSR frontmatter or a `src/pages/api/*.ts` route), guarded in `try/catch`, bouncing anonymous visitors to `/api/auth/login?returnToUrl=…`;
121
121
  - reads the current member via **`@wix/members` `getCurrentMember`** (not the dev-preview `@wix/site-members`), resolving the photo `wix:image://` URI and expecting only PUBLIC fields for other members;
122
122
  - does **no `auth.elevate`** for a member reading their own data (elevation is a different, admin-only axis that lives in a backend route);
123
123
  - treats **login as required** whenever pricing-plans is present (subscribe + my-subscription), and as a soft add-on for the "my …" surfaces of the other verticals;
@@ -15,7 +15,7 @@ A concise contract for building your **own** login / sign-up / logout UI and dri
15
15
  > **⚠️ This is a client-driven (`OAuthStrategy`) flow — it is the non-Astro shape.** `register`/`login` live on `client.auth`, i.e. the manual visitor client `non-astro.md` builds. Astro's auto-auth ships **no client** to call them on. So: on a **non-Astro** frontend (SPA / static), this is the natural path. On **Astro**, custom login means stepping *outside* auto-auth — instantiate an explicit `OAuthStrategy` client (in a backend route or a client island) to run these calls; do **not** expect the built-in `/api/auth/*` routes to do custom login (they only drive the Wix login page). If the brief is Astro *and* doesn't demand a custom form, prefer the Wix login page (`how-to-code-members-astro.md`).
16
16
 
17
17
  Pinned docs (read before wiring — `curl` the `.md` directly):
18
- - Custom login via the JS SDK: <https://dev.wix.com/docs/go-headless/self-managed-headless/authentication/members/custom-login-page/custom-login/custom-login-using-the-js-sdk.md>
18
+ - Custom login via the JS SDK: <https://dev.wix.com/docs/go-headless/authentication/members/custom-login-page/build-a-custom-login-page-js-sdk.md>
19
19
  - `OAuthStrategy` reference (`register`/`login`/`processVerification`/`getMemberTokensForDirectLogin`/`sendPasswordResetEmail`, the `StateMachine` + `IdentityProfile` objects): <https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md>
20
20
  - Current member (SDK): <https://dev.wix.com/docs/sdk/frontend-modules/members/current-member/introduction> (open with `?apiView=SDK`)
21
21
 
@@ -11,7 +11,7 @@ A concise contract for wiring **login / sign-up / logout and member-gated surfac
11
11
  > **One mechanism, not three.** Sign-up, log-in and log-out are the *same* flow — the Wix login page **logs in an existing member or registers a new one** in one step; you never build a separate "sign up" call. Member tokens are the **same shape** as visitor tokens, just `role: member`: login just swaps the token set on the client you already have.
12
12
 
13
13
  Pinned docs (read before wiring — `curl` the `.md` directly):
14
- - Wix-managed login via the JS SDK: <https://dev.wix.com/docs/go-headless/self-managed-headless/authentication/members/wix-login-page/wix-managed-login-using-the-js-sdk.md>
14
+ - Wix-managed login via the JS SDK: <https://dev.wix.com/docs/go-headless/authentication/members/wix-login-page/add-a-wix-login-page-js-sdk.md>
15
15
  - `OAuthStrategy` reference (member flows, token/session methods): <https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md>
16
16
  - Handle visitors & members via the JS SDK: <https://dev.wix.com/docs/go-headless/self-managed-headless/authentication/visitors/handle-visitors-using-the-js-sdk.md>
17
17
  - Current member (SDK): <https://dev.wix.com/docs/sdk/frontend-modules/members/current-member/introduction> (open with `?apiView=SDK`)
@@ -23,7 +23,9 @@ A contract for the **frontend code** of a pricing-plans site: showing the plans
23
23
  | List / read plans (the grid) | `@wix/pricing-plans` | `plansV3` (Plans V3 — `queryPlans`, `getPlan`) |
24
24
  | Order a plan + read a member's orders | `@wix/pricing-plans` | `orders` (`createOnlineOrder`, `memberListOrders`, `memberGetOrder`) |
25
25
  | Member login / current member | `@wix/members` + `@wix/sdk` auth | see the members recipe (`getCurrentMember`, `loggedIn()`) |
26
- | Book a service with a membership (integration) | `@wix/bookings` + `@wix/ecom` (+ `@wix/redirects`) | `bookings` (`createBooking`), ecom `checkout` (`membershipOptions`) — see *Booking with a membership* |
26
+ | Book a service with a membership (integration) | `@wix/bookings` + `@wix/ecom` (+ `@wix/redirects`) | `bookings` (`createBooking`), ecom `currentCartV2` (line-item `membershipPayment`) — see *Booking with a membership* |
27
+
28
+ > Migrating from Cart V1 / Checkout V1? The code below is V2-only — see the [migration guide](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/migration-guide) for the before/after.
27
29
 
28
30
  **Never** import `@wix/site-pricing-plans` in headless code, and don't reach for a V1 `plans`-collection query — Plans V3 (`queryPlans` → `pricingVariants`) is the shape the seed creates.
29
31
 
@@ -98,15 +100,15 @@ This is the payoff of the seed's STEP 2: a member who holds a plan that **covers
98
100
 
99
101
  1. **Require login** — membership payment resolves against the member identity (a covered service booked anonymously just falls back to pay-per-booking).
100
102
  2. **On `createBooking`, set `selectedPaymentOption: "MEMBERSHIP"`** (instead of `ONLINE`/`OFFLINE`). Enum values: `ONLINE`, `OFFLINE`, **`MEMBERSHIP`** (pay with a pricing plan), `MEMBERSHIP_OFFLINE`. Doc: <https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/create-booking.md?apiView=SDK>
101
- 3. **The booking still rides the ecom checkout** (Bookings is an ecom catalog, appId `13d21c63-b5ec-5912-8397-c3a5ddb27a97`) — the membership is applied **on the checkout**, not on the booking object. The eligible plan surfaces on the **ecom Checkout** entity's `membershipOptions`:
102
- - `membershipOptions.eligibleMemberships[]` — the member's plans that can cover the line item (each `{ _id, appId, name, credits }`).
103
- - apply one via `checkout.updateCheckout(...)` setting `membershipOptions.selectedMemberships.memberships = [{ _id, appId, lineItemIds: [<booking line item id>] }]`. When the membership covers the full price, `payNow` drops to `0`.
104
- Doc: <https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/checkout/checkout/get-checkout.md?apiView=SDK>
103
+ 3. **The booking still rides the ecom cart** (Bookings is an ecom catalog, appId `13d21c63-b5ec-5912-8397-c3a5ddb27a97`) — the membership is applied **on the cart line item**, not on the booking object. Set membership selection on the line item via `updateLineItemsInCurrentCart`:
104
+ - **Apply one** by setting the line item's `membershipPayment` via `currentCartV2.updateLineItemsInCurrentCart({ lineItems: [{ lineItemId: <booking line item id>, membershipPayment: { existingMembership: { membershipId, appId } } }] })` — `membershipId`/`appId` identify the member's existing plan membership (the Pricing Plans app); the line item reads it back as `paymentConfig.membership`. When the membership covers the full price, the calculated total drops to `0`.
105
+ - **Which plan to apply / eligibility:** the cart has **no** candidate-memberships read in V2 — `calculateCurrentCart` → `summary.paymentSummary.memberships` lists memberships **already applied**, not candidates — so which plan to apply comes from the member's plans + live coverage (see the LIVE-read note below). **⚠️ VERIFY IN A LIVE BUILD** which `appId`/`membershipId` a headless member token must pass.
106
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/update-line-items.md?apiView=SDK>
105
107
  4. **⚠️ Do NOT call `confirmBooking`** — for a membership payment Wix **auto-confirms** the booking on redemption (the same "no confirmBooking" rule as `how-to-code-bookings.md`; the membership drives confirmation).
106
108
 
107
- - **⚠️ Eligibility / coverage is a LIVE read, never a hardcoded plan→service map.** A new eligible plan, or a service newly added to a plan's coverage in the backoffice, **must be honored with no code change** — so never freeze the seed-time `{ planId → serviceIds }` map into the frontend. **Preferred:** read `checkout.membershipOptions.eligibleMemberships` — the plans that can cover *this* line item, computed server-side from live coverage. (It's tagged "reserved for internal use" in the schema, so **VERIFY IN A LIVE BUILD** whether a headless member token reads it client-side.) **Fallback if that field comes back empty for a member token:** list the member's active orders (`orders.memberListOrders`, `status: ACTIVE` within the date window) and match each `planId` against the plan's **live** Benefit-Program coverage (query the program's items — the same API `setup-pricing-plans.md` STEP 2 wrote to — at request time; do **not** read a coverage map baked into code). Set `selectedPaymentOption: "MEMBERSHIP"` + `selectedMemberships` from whichever read succeeds.
109
+ - **⚠️ Eligibility / coverage is a LIVE read, never a hardcoded plan→service map.** A new eligible plan, or a service newly added to a plan's coverage in the backoffice, **must be honored with no code change** — so never freeze the seed-time `{ planId → serviceIds }` map into the frontend. Since Cart V2 has no per-line "eligible memberships" read, compute eligibility from the member's own plans against live coverage: list the member's active orders (`orders.memberListOrders`, `status: ACTIVE` within the date window) and match each `planId` against the plan's **live** Benefit-Program coverage (query the program's items — the same API `setup-pricing-plans.md` STEP 2 wrote to — at request time; do **not** read a coverage map baked into code). Set `selectedPaymentOption: "MEMBERSHIP"` on the booking + the line item's `membershipPayment.existingMembership` from the matched plan.
108
110
  - **⚠️ A `MEMBERSHIP` booking on a service the plan does NOT cover fails at checkout** (unless `skipSelectedPaymentOptionValidation`, which needs elevation — don't use in a member flow). Only offer "book with membership" for services actually covered by one of the member's active plans; otherwise fall back to the normal paid booking (`how-to-code-bookings.md`).
109
- - **Credit/session plans:** for a limited (non-unlimited) plan, `eligibleMemberships[].credits.remaining` matters — `0` remaining is not eligible. An unlimited plan (seed `price:"0"`) has no credit ceiling.
111
+ - **Credit/session plans:** for a limited (non-unlimited) plan, don't pre-read a balance — apply the membership, then `calculateCurrentCart`/`estimateCurrentCart`. The summary lists the applied memberships (`summary.paymentSummary.memberships`), the covered line's `paymentConfig.membership` carries `redemptionCost` (balance deducted for this booking; `0` = unlimited) + `redemptionType` (`CREDITS`/`SESSIONS`), and an exhausted/over-limit plan surfaces **explicitly** as a `summary.violations` entry (or an error at place-order) — treat that as "not eligible." The ecom cart itself carries no remaining-balance read; the balance is owned by the plan's **Benefit-Program** domain (the same source as the coverage check above), so if you need the actual number read it there — not off the cart. An unlimited plan (seed `price:"0"`) has no ceiling.
110
112
 
111
113
  ### Out of scope (do not build these)
112
114
  - **Completing/activating payment from code** — connecting a payments account, marking orders paid, forcing an order `ACTIVE`, "activating" a subscription server-side. Payment is the member's hosted-flow step or a merchant dashboard/config task, never frontend code (see the SCOPE callout under *Subscribing*).
@@ -121,4 +123,4 @@ A correct Pricing Plans frontend:
121
123
  - imports **`@wix/pricing-plans`** (`plansV3`, `orders`) — **never** `@wix/site-pricing-plans` (its `startOnlinePurchase` is Wix-site page-code, not headless);
122
124
  - lists the grid publicly with **`plansV3.queryPlans().eq('visibility','PUBLIC')`**, reads **`plan._id`** and price from **`pricingVariants[].pricingStrategies[].flatRate.amount`** (decimal string) — never a top-level `price` — and only shows a buy button on `buyable` plans;
123
125
  - treats **subscribe and my-subscription as login-gated** (the hard members dependency), orders with **`orders.createOnlineOrder(planId)`** (no `onBehalf`, no elevate), renders free plans as `ACTIVE` immediately, and drives paid plans through a payment redirect (**exact headless redirect to be confirmed in a live build**) — and **stops at the redirect**: no payments-account connect, no order activation / mark-as-paid from code (see *Out of scope*);
124
- - for the Bookings integration, books a covered service by setting **`selectedPaymentOption: "MEMBERSHIP"`** on `createBooking`, applies the membership on the **ecom checkout** (`membershipOptions`), never calls `confirmBooking`, and falls back to matching the member's active-order `planId`s to the service's coverage when the checkout eligibility field isn't readable client-side.
126
+ - for the Bookings integration, books a covered service by setting **`selectedPaymentOption: "MEMBERSHIP"`** on `createBooking`, applies the membership on the **ecom cart line item** (`membershipPayment.existingMembership` via `updateLineItemsInCurrentCart`), never calls `confirmBooking`, and falls back to matching the member's active-order `planId`s to the service's coverage when the cart eligibility field isn't readable client-side.