@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
@@ -0,0 +1,78 @@
1
+ # Portfolio — seeding
2
+
3
+ Seed by **running `seed-portfolio.mjs` with a plan file** — don't hand-write the REST calls.
4
+ The script mints its own site token via the Wix CLI (logged-in session + `wix.config.json`
5
+ required), installs the Portfolio app if needed, and creates everything in the right order:
6
+ collections first (a project's `collectionIds` are NOT validated — a wrong id silently
7
+ orphans the project), then projects, gallery items, and covers.
8
+
9
+ ```bash
10
+ # from the project root (where wix.config.json lives):
11
+ node <SKILL_ROOT>/references/portfolio/seed/seed-portfolio.mjs plan.json
12
+ ```
13
+
14
+ `plan.json` is plain data — write it from the brief. **Default to 2 collections × 2 projects
15
+ each** (the seed shows the shape; the owner adds the rest in the dashboard) and make them
16
+ exercise the UI: every collection and project gets a cover, every project gets 2–3 gallery
17
+ `items` (a portfolio without images looks broken), and a couple of projects get `details`
18
+ rows (Role, Year, Client…).
19
+
20
+ ```json
21
+ {
22
+ "collections": [
23
+ { "title": "Brand Identity", "description": "Logo systems and visual identities.",
24
+ "coverImageUrl": "https://…" },
25
+ { "title": "Editorial", "description": "Print and digital editorial design.",
26
+ "coverImageUrl": "https://…" }
27
+ ],
28
+ "projects": [
29
+ { "title": "Northwind Rebrand", "description": "Full identity refresh for a logistics firm.",
30
+ "collection": "Brand Identity",
31
+ "details": [ { "label": "Role", "text": "Brand & Art Direction" }, { "label": "Year", "text": "2025" } ],
32
+ "coverImageUrl": "https://…",
33
+ "items": [
34
+ { "sortOrder": 1, "title": "Logo system", "imageUrl": "https://…" },
35
+ { "sortOrder": 2, "title": "Stationery", "imageUrl": "https://…" }
36
+ ] },
37
+ { "title": "Harbor Coffee", "description": "Packaging and label suite.",
38
+ "collection": "Brand Identity", "coverImageUrl": "https://…",
39
+ "items": [ { "sortOrder": 1, "title": "Label set", "imageUrl": "https://…" } ] },
40
+ { "title": "Field Notes Quarterly", "description": "Magazine layout and typography.",
41
+ "collection": "Editorial", "coverImageUrl": "https://…",
42
+ "items": [ { "sortOrder": 1, "title": "Spread", "imageUrl": "https://…" } ] },
43
+ { "title": "City Guides", "description": "Travel series covers.",
44
+ "collection": "Editorial", "coverImageUrl": "https://…",
45
+ "items": [ { "sortOrder": 1, "title": "Covers", "imageUrl": "https://…" } ] }
46
+ ]
47
+ }
48
+ ```
49
+
50
+ - `collection` — a collection **title from this plan**; resolved to its created id. A project
51
+ without one belongs to no collection (reachable only from an all-projects list).
52
+ - `details` — optional `[{ label, text }]` rows; render on the project page. Omit for none.
53
+ - Every image field's default is a prompt (`coverImagePrompt` / `items[].imagePrompt` —
54
+ AI-generated, ~1 Wix AI credit per image, account-billed): brand-contextual — subject,
55
+ aesthetic/mood, palette, lighting — always ending "no text, no watermarks". At least one image in the set shows the real subject of the business — the actual product/space/service, not abstract decoration. For an asset the user actually supplied
56
+ use a path (`coverImagePath` / `items[].imagePath` — a file on this machine, uploaded to
57
+ Wix Media) or a url (`coverImageUrl` / `items[].imageUrl` — their own hosted URL; verify it
58
+ with `curl -sI` → 200) — never a stock-photo or guessed URL. All images —
59
+ covers and gallery items alike — resolve in one parallel wave and never block the seed; a
60
+ failed image skips just that item/cover. The **cover** is the
61
+ listing thumbnail; **items** are the detail-page gallery — separate entities, both wanted.
62
+ If a project has only a cover, reuse its url as item 1 so the gallery isn't empty.
63
+ - `sortOrder` (1, 2, 3…) sets the gallery render order.
64
+ - `hidden` defaults to shown — omit it; send `hidden: true` only to hide an entity.
65
+ - Gallery items seed as images only; the owner adds videos in the dashboard.
66
+ - A fresh Portfolio install ships sample content ("My Portfolio" + sample projects). **Seeding
67
+ is additive — never delete or overwrite existing content**; if removing the samples seems
68
+ wanted, ask the owner first.
69
+
70
+ ## Escape hatch — individual functions
71
+ `setupPortfolio` composes exported steps — `installPortfolioApp`, `createCollections`,
72
+ `createProjects`, `importImage`, `attachProjectCovers`, `attachCollectionCovers`,
73
+ `createProjectItems`, `listCollections`, `listProjects`, plus `makeCtx()` — import them only
74
+ for a partial re-seed.
75
+
76
+ ## Reference
77
+ Unexpected shape or an uncovered operation → read the live Wix API reference; the
78
+ authoritative source recipe is `wix-headless/references/inline-recipes/setup-portfolio.md`.
@@ -0,0 +1,258 @@
1
+ // Portfolio seed — a BUILD-TIME script, never shipped in the app. Run from the project root
2
+ // (where wix.config.json lives) with a plan file:
3
+ //
4
+ // node <SKILL_ROOT>/references/portfolio/seed/seed-portfolio.mjs plan.json
5
+ //
6
+ // It mints its own site token via the Wix CLI, installs the Wix Portfolio app if needed,
7
+ // creates collections then projects (collections FIRST — a project's collectionIds are NOT
8
+ // validated, so a wrong id is silently accepted and orphans the project), creates each
9
+ // project's gallery items, and imports+attaches cover images. Prints a JSON result to stdout.
10
+ //
11
+ // Plan shape (see SEED.md):
12
+ // { "collections": [{ "title", "description"?, "hidden"?, "coverImageUrl"? | "coverImagePrompt"? }],
13
+ // "projects": [{ "title", "description"?, "hidden"?,
14
+ // "collection"? (title), // resolved to that collection's id
15
+ // "details"?: [{ "label", "text" }],
16
+ // "coverImageUrl"? | "coverImagePrompt"?,
17
+ // "items"?: [{ "sortOrder", "title"?, "imageUrl" | "imagePrompt" }] }] }
18
+ //
19
+ // Seeding is ADDITIVE — never deletes or overwrites existing content. A fresh Portfolio
20
+ // install ships its own sample content ("My Portfolio" + sample projects); removing it is the
21
+ // owner's call, not this script's. Unexpected shapes → read the live API reference;
22
+ // authoritative source recipe: wix-headless/references/inline-recipes/setup-portfolio.md.
23
+ import { execFileSync } from "node:child_process";
24
+ import { readFileSync } from "node:fs";
25
+ import { resolveItemImages } from "../../shared/seed/images.mjs";
26
+
27
+ const API = "https://www.wixapis.com";
28
+ const PORTFOLIO_APP_ID = "d90652a2-f5a1-4c7c-84c4-d4cdcc41f130";
29
+
30
+ export function makeCtx({ cwd = process.cwd() } = {}) {
31
+ const config = JSON.parse(readFileSync(`${cwd}/wix.config.json`, "utf8"));
32
+ const siteId = config.siteId ?? config.projectId;
33
+ if (!siteId) throw new Error("wix.config.json has no siteId — is this a Wix CLI project?");
34
+ const token = execFileSync("npx", ["@wix/cli@latest", "token", "--site", siteId], {
35
+ encoding: "utf8",
36
+ cwd,
37
+ }).trim();
38
+ if (!token) throw new Error("The Wix CLI returned no token — run `npx @wix/cli@latest login` first.");
39
+ return { token, siteId };
40
+ }
41
+
42
+ async function req(ctx, path, { method = "POST", body } = {}) {
43
+ const res = await fetch(API + path, {
44
+ method,
45
+ headers: {
46
+ Authorization: `Bearer ${ctx.token}`,
47
+ "wix-site-id": ctx.siteId,
48
+ "Content-Type": "application/json",
49
+ },
50
+ body: body ? JSON.stringify(body) : undefined,
51
+ });
52
+ const json = await res.json().catch(() => ({}));
53
+ if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
54
+ return json;
55
+ }
56
+
57
+ // ---- operations ----------------------------------------------------------------------------------
58
+
59
+ // Idempotent — re-installing returns 200.
60
+ // docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
61
+ export async function installPortfolioApp(ctx) {
62
+ try {
63
+ await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
64
+ tenant: { tenantType: "SITE", id: ctx.siteId },
65
+ appInstance: { appDefId: PORTFOLIO_APP_ID, enabled: true },
66
+ } });
67
+ } catch {
68
+ /* already installed is fine */
69
+ }
70
+ }
71
+
72
+ // Read-only listing helpers (partial re-seeds, verification).
73
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/list-collections.md
74
+ export async function listCollections(ctx) {
75
+ const r = await req(ctx, "/portfolio/v1/collections", { method: "GET" });
76
+ return (r.collections ?? []).map((c) => ({ id: c.id, title: c.title, slug: c.slug }));
77
+ }
78
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/list-projects.md
79
+ export async function listProjects(ctx) {
80
+ const r = await req(ctx, "/portfolio/v1/projects", { method: "GET" });
81
+ return (r.projects ?? []).map((p) => ({ id: p.id, title: p.title, slug: p.slug }));
82
+ }
83
+
84
+ // STEP 1 — collections. The display name is `title`, not `name`; `slug` auto-generates from
85
+ // the title; `hidden` defaults to false = shown (omit it — send true only to hide). No
86
+ // bulk-create: one call per collection.
87
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/create-collection.md
88
+ export async function createCollections(ctx, collections) {
89
+ const out = [];
90
+ for (const c of collections) {
91
+ const body = { collection: { title: c.title, description: c.description } };
92
+ if (c.hidden) body.collection.hidden = true;
93
+ const r = await req(ctx, "/portfolio/v1/collections", { body });
94
+ out.push({ id: r.collection?.id, slug: r.collection?.slug, revision: r.collection?.revision });
95
+ }
96
+ return out;
97
+ }
98
+
99
+ // STEP 2 — projects, AFTER collections: collectionIds must hold real ids from createCollections
100
+ // (they are NOT validated — a wrong/missing id silently orphans the project). `details` is an
101
+ // optional [{ label, text }] array. No bulk-create: one call per project.
102
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/create-project.md
103
+ export async function createProjects(ctx, projects) {
104
+ const out = [];
105
+ for (const p of projects) {
106
+ const project = {
107
+ title: p.title,
108
+ description: p.description,
109
+ collectionIds: p.collectionIds ?? [],
110
+ };
111
+ if (p.details) project.details = p.details;
112
+ if (p.hidden) project.hidden = true;
113
+ const r = await req(ctx, "/portfolio/v1/projects", { body: { project } });
114
+ out.push({ id: r.project?.id, slug: r.project?.slug, revision: r.project?.revision });
115
+ }
116
+ return out;
117
+ }
118
+
119
+ // Portfolio binds covers + gallery items by Wix Media file ID — an external url must be
120
+ // imported first (a raw url renders nothing); a plan `imagePrompt`/`coverImagePrompt` is
121
+ // generated (Wix AI, 1 credit) then imported. Both live in the shared util (parallel,
122
+ // resilient, never blocks the seed).
123
+ export { importImage } from "../../shared/seed/images.mjs";
124
+
125
+ // Cover = the listing-card thumbnail. PATCH per entity, echoing the current revision (missing/
126
+ // stale revision fails); height + width are required alongside the imported file id.
127
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/update-project.md
128
+ export async function attachProjectCovers(ctx, items) {
129
+ for (const it of items) {
130
+ await req(ctx, `/portfolio/v1/projects/${it.id}`, {
131
+ method: "PATCH",
132
+ body: { project: { id: it.id, revision: it.revision, coverImage: { imageInfo: { id: it.imageId, height: it.height, width: it.width } } } },
133
+ });
134
+ }
135
+ }
136
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/update-collection.md
137
+ export async function attachCollectionCovers(ctx, items) {
138
+ for (const it of items) {
139
+ await req(ctx, `/portfolio/v1/collections/${it.id}`, {
140
+ method: "PATCH",
141
+ body: { collection: { id: it.id, revision: it.revision, coverImage: { imageInfo: { id: it.imageId, height: it.height, width: it.width } } } },
142
+ });
143
+ }
144
+ }
145
+
146
+ // The detail-page gallery is a SEPARATE `item` entity — one POST per image; sortOrder (1,2,3…)
147
+ // sets render order. Lowercase `items` — `/Items` 404s. There is NO public list endpoint.
148
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/project-items/create-project-item.md
149
+ export async function createProjectItems(ctx, items) {
150
+ const out = [];
151
+ for (const it of items) {
152
+ const r = await req(ctx, "/portfolio/v1/items", {
153
+ body: { item: { projectId: it.projectId, sortOrder: it.sortOrder, title: it.title, image: { imageInfo: { id: it.imageId, height: it.height, width: it.width } } } },
154
+ });
155
+ out.push({ id: r.item?.id });
156
+ }
157
+ return out;
158
+ }
159
+
160
+ /**
161
+ * ONE-CALL seed: install → collections → projects (into collections) → gallery items →
162
+ * covers, ids threaded in memory. The default path.
163
+ */
164
+ export async function setupPortfolio(ctx, { collections = [], projects = [] } = {}) {
165
+ await installPortfolioApp(ctx);
166
+
167
+ const cols = await createCollections(ctx, collections);
168
+ const idByTitle = new Map(collections.map((c, i) => [c.title, cols[i].id]));
169
+
170
+ const projs = await createProjects(
171
+ ctx,
172
+ projects.map((p) => ({
173
+ title: p.title,
174
+ description: p.description,
175
+ details: p.details,
176
+ hidden: p.hidden,
177
+ collectionIds: p.collection ? [idByTitle.get(p.collection)].filter(Boolean) : [],
178
+ })),
179
+ );
180
+
181
+ // Pass 2 — images: gallery items + project covers + collection covers, flattened into ONE
182
+ // parallel wave (import by url / generate by prompt), then mapped back to each attach.
183
+ // A failed image skips just that item/cover; the seed's exit never depends on images.
184
+ const specs = [];
185
+ const galleryRefs = [];
186
+ projects.forEach((p, pi) => {
187
+ for (const it of p.items ?? []) {
188
+ galleryRefs.push({ pi, it, spec: specs.length });
189
+ specs.push({ path: it.imagePath, url: it.imageUrl, prompt: it.imagePrompt, displayName: `${it.title || "item"}.png` });
190
+ }
191
+ });
192
+ const projCoverAt = specs.length;
193
+ projects.forEach((p) => specs.push({ path: p.coverImagePath, url: p.coverImageUrl, prompt: p.coverImagePrompt, displayName: `${p.title || "project"}-cover.png` }));
194
+ const colCoverAt = specs.length;
195
+ collections.forEach((c) => specs.push({ path: c.coverImagePath, url: c.coverImageUrl, prompt: c.coverImagePrompt, displayName: `${c.title || "collection"}-cover.png` }));
196
+ const files = await resolveItemImages(ctx, specs);
197
+ const dims = { height: 1024, width: 1024 };
198
+
199
+ const itemsFlat = galleryRefs
200
+ .map(({ pi, it, spec }) => (files[spec] && projs[pi]?.id
201
+ ? { projectId: projs[pi].id, sortOrder: it.sortOrder, title: it.title, imageId: files[spec].id, ...dims }
202
+ : null))
203
+ .filter(Boolean);
204
+ let items = [];
205
+ try {
206
+ if (itemsFlat.length) items = await createProjectItems(ctx, itemsFlat);
207
+ } catch {
208
+ /* the remaining gallery items stay unseeded */
209
+ }
210
+
211
+ const projCovers = projs
212
+ .map((p, i) => (files[projCoverAt + i] && p.id
213
+ ? { id: p.id, revision: p.revision, imageId: files[projCoverAt + i].id, ...dims }
214
+ : null))
215
+ .filter(Boolean);
216
+ const colCovers = cols
217
+ .map((c, i) => (files[colCoverAt + i] && c.id
218
+ ? { id: c.id, revision: c.revision, imageId: files[colCoverAt + i].id, ...dims }
219
+ : null))
220
+ .filter(Boolean);
221
+ let coversAttached = 0;
222
+ try {
223
+ if (projCovers.length) { await attachProjectCovers(ctx, projCovers); coversAttached += projCovers.length; }
224
+ } catch {
225
+ /* those projects stay cover-less */
226
+ }
227
+ try {
228
+ if (colCovers.length) { await attachCollectionCovers(ctx, colCovers); coversAttached += colCovers.length; }
229
+ } catch {
230
+ /* those collections stay cover-less */
231
+ }
232
+
233
+ return {
234
+ collections: cols,
235
+ projects: projs,
236
+ itemsCreated: items.length,
237
+ coversAttached,
238
+ };
239
+ }
240
+
241
+ // ---- CLI entry ----------------------------------------------------------------------------------
242
+
243
+ const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
244
+ if (invokedDirectly) {
245
+ const planPath = process.argv[2];
246
+ if (!planPath) {
247
+ console.error("usage: node seed-portfolio.mjs <plan.json> (run from the project root)");
248
+ process.exit(1);
249
+ }
250
+ const plan = JSON.parse(readFileSync(planPath, "utf8"));
251
+ const ctx = makeCtx();
252
+ setupPortfolio(ctx, plan)
253
+ .then((result) => console.log(JSON.stringify(result, null, 2)))
254
+ .catch((e) => {
255
+ console.error(e.message);
256
+ process.exit(1);
257
+ });
258
+ }
@@ -0,0 +1,133 @@
1
+ # Pricing Plans — playbook
2
+
3
+ The plans machinery ships as files — plan reads (grid + by-slug) and the hosted purchase
4
+ redirect, typed end-to-end. **The presentation is yours**: you design and implement the plan
5
+ card, the pricing grid, and the plan detail surface on the shipped hooks/DTOs, plus the home
6
+ page and the brand. You never write purchase logic; you never skip designing.
7
+
8
+ ## The file map (deployed into `src/`)
9
+
10
+ **Don't read the shipped files** — this table and the contracts below are everything you
11
+ need. Open a shipped file's source only on a real fallback (runtime error / uncovered field),
12
+ or to read a reference component's pattern.
13
+
14
+ | file | what it is |
15
+ |---|---|
16
+ | `wix/config.ts` · `wix/sdk.ts` · `wix/media.ts` · `wix/money.ts` | shared auth seam + helpers (deploy configures; nothing to set) |
17
+ | `wix/pricing-plans/types.ts` | the DTOs (`PlanSummary`, `PlanDetail`) — contracts below |
18
+ | `wix/pricing-plans/plans.ts` | `fetchPlans`, `fetchPlanBySlug` |
19
+ | `wix/pricing-plans/purchase.ts` | `purchasePlan` — the hosted-checkout redirect session lives here |
20
+ | `hooks/pricing-plans/usePlans.ts` | plans listing — contract below |
21
+ | `hooks/pricing-plans/usePlanPurchase.ts` | the purchase action — contract below |
22
+ | `components/pricing-plans/PlansView.tsx` (+ `PlanCard`) · `PlanDetailView.tsx` | **REFERENCE implementations** — correct, plain; build your own instead of shipping them |
23
+ | `styles/global.css` | the design system: Tailwind v4 + the `@theme` token block (shared across verticals) |
24
+
25
+ Astro stack additionally gets:
26
+
27
+ | file | what it is |
28
+ |---|---|
29
+ | `layouts/SiteLayout.astro` | site chrome — **yours to brand** (keep the `seo-tags` slot + global.css import). If another vertical is also deployed, its layout won — add a Plans nav link there |
30
+ | `pages/plans.astro` | SSR pricing grid — **keep the frontmatter**, swap the island import to YOUR component |
31
+ | `pages/plans/[slug].astro` | SSR plan detail — **keep the frontmatter** (plain `<title>`/`<meta>` from the DTO: Pricing Plans has no owner-editable SEO item type); swap the island import |
32
+
33
+ ## What you build — the design job
34
+
35
+ 1. **The plan card + pricing grid** — your tier card (name, price + billing cadence, trial
36
+ badge, perks list, Subscribe CTA — only when `buyable`) and grid rhythm (a highlighted
37
+ recommended tier is a classic), with skeletons while loading and an honest empty state —
38
+ on `usePlans` + `usePlanPurchase`.
39
+ 2. **The plan detail surface** — the full pitch: price block, perks, terms & conditions
40
+ (plain text — render pre-wrap), subscribe CTA — on `usePlanPurchase` (the plan itself
41
+ arrives as an SSR-fetched DTO prop).
42
+ 3. **The home page** — hero, a featured-plans strip (fetch in frontmatter → your components),
43
+ brand story.
44
+
45
+ Plus the **theme** (`@theme` block, one edit) and the **chrome** (`SiteLayout`, one pass).
46
+ Style everything with Tailwind utilities on the tokens.
47
+
48
+ ### The contracts your components consume
49
+
50
+ ```ts
51
+ // PlanSummary (cards) — display-ready:
52
+ // { id, slug, name, description, price /* "$29.00" | "Free" */, free,
53
+ // billing /* "per month" | "every 3 months" | "one-time" | "" (free) */,
54
+ // freeTrialDays: number|null, perks: string[], buyable, imageUrl /* "" when none */ }
55
+ // PlanDetail adds: termsAndConditions (plain text; "" when not set).
56
+
57
+ // usePlans({ initialPlans? }) →
58
+ // { plans: PlanSummary[]|null /* null = loading → skeletons */, error }
59
+
60
+ // usePlanPurchase() →
61
+ // { purchase(planId, { thankYouPageUrl?, postFlowUrl? }?): Promise<void>,
62
+ // // resolves as the browser navigates to the Wix-hosted checkout;
63
+ // // rejects with a visitor-facing message — surface it
64
+ // purchasingId, // plan id in flight (null when idle) — key the CTA spinner off it
65
+ // error }
66
+ ```
67
+
68
+ ### Wiring — Astro (default)
69
+
70
+ 1. Set the `@theme` tokens (one edit); brand `SiteLayout.astro` (one pass — merge into the
71
+ other vertical's layout instead if both are deployed).
72
+ 2. Write your components under `src/components/pricing-plans/` (new names — don't overwrite
73
+ the references), swap the island imports in `pages/plans.astro` and
74
+ `pages/plans/[slug].astro`. Both islands: `client:load` with the SSR DTO props. **Author
75
+ your surfaces in as few messages as possible** — batch multiple Writes per message.
76
+ 3. Write `pages/index.astro` (home) — it exists from the scaffold; Read it before overwriting.
77
+
78
+ ### Wiring — React SPA (Vite etc.)
79
+
80
+ Import `./styles/global.css` once at the app entry (needs `@tailwindcss/vite` in the vite
81
+ plugins — deploy added the dep). Routes: `/plans` → your grid; `/plans/:slug` → fetch with
82
+ `fetchPlanBySlug(slug)` client-side, then your detail surface (null → your not-found state).
83
+
84
+ ## Hard rules
85
+
86
+ - **Purchase only through the shipped exports** — `usePlanPurchase`/`purchasePlan` own the
87
+ hosted redirect session. Never hand-build a checkout URL, never call
88
+ `orders.createOnlineOrder` (member-only, and it leaves payment unhandled), never mark
89
+ anything paid.
90
+ - **Purchasing is members-only, and that's fine as-is**: the hosted flow handles member
91
+ login/signup, the order form, and payment, then returns to your site. Don't build a login
92
+ gate in front of the CTA.
93
+ - **No success theater.** Returning from checkout is NOT a success signal — `postFlowUrl` is
94
+ hit on abandon too. Success arrives only at a `thankYouPageUrl` you pass, as
95
+ `?planOrderId=<GUID>`; if you build a thank-you page, read that param — never fake a
96
+ confirmation off the mere return.
97
+ - **Prices are display-only.** `price`/`billing` come pre-formatted; never compute a charge,
98
+ discount, or proration — Wix settles price, tax, and schedule at the hosted checkout.
99
+ - **Show the Subscribe CTA only when `buyable`** — a PUBLIC plan can be merchant-assigned.
100
+ - Theme via the `@theme` tokens; no parallel theme files, no hardcoded palettes.
101
+ - Live data or an honest empty state — never mock plans, prices, or perks.
102
+
103
+ ## Out of scope (don't improvise these)
104
+
105
+ Member-gated surfaces — a "my plans" page, the member's orders (`orders.memberListOrders`),
106
+ cancel/pause flows, and booking a covered bookings service with a membership — require a
107
+ logged-in member session this skill doesn't ship yet. Subscribers manage their plan through
108
+ Wix's emails and hosted member flows. If the user asks for a member area, route to
109
+ `wix-headless` (members recipes) rather than shipping code that returns nothing for visitors.
110
+
111
+ ## Point the user to their dashboard
112
+
113
+ Give the owner the dashboard link plus the Pricing Plans page — the deploy step's JSON
114
+ printed `dashboardUrl`; append `/pricing-plans` for plan management (edit plans, connect
115
+ plans to content, see orders). Taking real payments needs a premium plan + a connected
116
+ payment method — mention it.
117
+
118
+ ## Seeding
119
+
120
+ Per `seed/SEED.md` — plain-data `plan.json` into `seed-pricing-plans.mjs` from the project
121
+ root. Seed a tier ladder that exercises the UI (a free tier, a monthly, a yearly or
122
+ one-time; 3–4 perks each).
123
+
124
+ ## Verify (before declaring done)
125
+
126
+ - [ ] `/plans` renders live plans SSR (view-source shows names) through YOUR components;
127
+ empty catalog shows your honest empty state.
128
+ - [ ] Every price shape reads right: free ("Free", no cadence), recurring ("$29.00 per
129
+ month"), one-time; Subscribe renders only on `buyable` plans.
130
+ - [ ] A plan page loads by slug and 404s (Astro) / shows not-found (SPA) on a bad slug.
131
+ - [ ] Subscribe redirects to the Wix-hosted checkout (login/signup + payment live there).
132
+ - [ ] Card/grid/detail/home are YOUR designs on the tokens; data-layer/hook files unedited.
133
+ - [ ] Dashboard links handed to the owner.
@@ -0,0 +1,58 @@
1
+ // REFERENCE detail surface: price/billing block + perks + terms + subscribe CTA, on the
2
+ // @theme tokens. Correct and complete; per the skill's model you design and build your own
3
+ // on usePlanPurchase (the plan itself arrives as an SSR-fetched DTO prop).
4
+ import { usePlanPurchase } from "../../hooks/pricing-plans/usePlanPurchase";
5
+ import type { PlanDetail } from "../../wix/pricing-plans/types";
6
+
7
+ export default function PlanDetailView({ plan }: { plan: PlanDetail }) {
8
+ const { purchase, purchasingId, error } = usePlanPurchase();
9
+ const purchasing = purchasingId === plan.id;
10
+
11
+ return (
12
+ <div>
13
+ <p>
14
+ <span className="text-4xl font-bold tracking-tight text-foreground">{plan.price}</span>
15
+ {plan.billing && <span className="ml-2 text-muted-foreground">{plan.billing}</span>}
16
+ </p>
17
+ {plan.freeTrialDays !== null && (
18
+ <p className="mt-1 text-sm text-muted-foreground">{plan.freeTrialDays}-day free trial</p>
19
+ )}
20
+
21
+ {plan.perks.length > 0 && (
22
+ <ul className="mt-6 space-y-2.5">
23
+ {plan.perks.map((perk) => (
24
+ <li key={perk} className="flex gap-2 text-sm text-foreground">
25
+ <span className="text-muted-foreground" aria-hidden="true">
26
+ ✓
27
+ </span>
28
+ <span>{perk}</span>
29
+ </li>
30
+ ))}
31
+ </ul>
32
+ )}
33
+
34
+ {error && <p className="mt-4 text-sm text-red-600">{error}</p>}
35
+ {plan.buyable ? (
36
+ <button
37
+ type="button"
38
+ disabled={purchasing}
39
+ onClick={() => void purchase(plan.id).catch(() => {})}
40
+ className="mt-6 rounded-full bg-primary px-8 py-3 text-sm font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-50"
41
+ >
42
+ {purchasing ? "Redirecting…" : plan.free ? "Get this plan" : `Subscribe · ${plan.price}`}
43
+ </button>
44
+ ) : (
45
+ <p className="mt-6 text-sm text-muted-foreground">This plan is assigned by the site owner.</p>
46
+ )}
47
+
48
+ {plan.termsAndConditions && (
49
+ <div className="mt-10 border-t border-border pt-5">
50
+ <p className="eyebrow">Terms &amp; conditions</p>
51
+ <p className="mt-2 whitespace-pre-wrap text-sm leading-relaxed text-muted-foreground">
52
+ {plan.termsAndConditions}
53
+ </p>
54
+ </div>
55
+ )}
56
+ </div>
57
+ );
58
+ }
@@ -0,0 +1,126 @@
1
+ // REFERENCE pricing surface: plan cards in a grid on the @theme tokens. Correct and
2
+ // complete; per the skill's model you design and build your own on usePlans +
3
+ // usePlanPurchase.
4
+ import type { ComponentType, ReactNode } from "react";
5
+ import { usePlans } from "../../hooks/pricing-plans/usePlans";
6
+ import { usePlanPurchase } from "../../hooks/pricing-plans/usePlanPurchase";
7
+ import type { PlanSummary } from "../../wix/pricing-plans/types";
8
+
9
+ export interface LinkLikeProps {
10
+ href: string;
11
+ className?: string;
12
+ children?: ReactNode;
13
+ }
14
+
15
+ const PlainLink = ({ href, className, children }: LinkLikeProps) => (
16
+ <a href={href} className={className}>
17
+ {children}
18
+ </a>
19
+ );
20
+
21
+ export interface PlanCardProps {
22
+ plan: PlanSummary;
23
+ onSubscribe: (planId: string) => void;
24
+ purchasing: boolean;
25
+ planHref?: (slug: string) => string;
26
+ LinkComponent?: ComponentType<LinkLikeProps>;
27
+ }
28
+
29
+ export function PlanCard({
30
+ plan,
31
+ onSubscribe,
32
+ purchasing,
33
+ planHref = (slug) => `/plans/${slug}`,
34
+ LinkComponent = PlainLink,
35
+ }: PlanCardProps) {
36
+ return (
37
+ <div className="flex h-full flex-col rounded-lg border border-border bg-background p-6">
38
+ <p className="text-base font-semibold text-foreground">{plan.name}</p>
39
+ {plan.description && <p className="mt-1 text-sm text-muted-foreground">{plan.description}</p>}
40
+ <p className="mt-4">
41
+ <span className="text-3xl font-bold tracking-tight text-foreground">{plan.price}</span>
42
+ {plan.billing && <span className="ml-1.5 text-sm text-muted-foreground">{plan.billing}</span>}
43
+ </p>
44
+ {plan.freeTrialDays !== null && (
45
+ <p className="mt-1 text-xs font-medium text-muted-foreground">{plan.freeTrialDays}-day free trial</p>
46
+ )}
47
+ {plan.perks.length > 0 && (
48
+ <ul className="mt-4 space-y-2">
49
+ {plan.perks.map((perk) => (
50
+ <li key={perk} className="flex gap-2 text-sm text-foreground">
51
+ <span className="text-muted-foreground" aria-hidden="true">
52
+ ✓
53
+ </span>
54
+ <span>{perk}</span>
55
+ </li>
56
+ ))}
57
+ </ul>
58
+ )}
59
+ <div className="mt-auto grid gap-2 pt-6">
60
+ {plan.buyable && (
61
+ <button
62
+ type="button"
63
+ disabled={purchasing}
64
+ onClick={() => onSubscribe(plan.id)}
65
+ className="rounded-full bg-primary px-6 py-2.5 text-sm font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-50"
66
+ >
67
+ {purchasing ? "Redirecting…" : "Subscribe"}
68
+ </button>
69
+ )}
70
+ <LinkComponent
71
+ href={planHref(plan.slug)}
72
+ className="rounded-full border border-border px-6 py-2.5 text-center text-sm font-semibold text-foreground no-underline transition-colors hover:bg-secondary"
73
+ >
74
+ View details
75
+ </LinkComponent>
76
+ </div>
77
+ </div>
78
+ );
79
+ }
80
+
81
+ export interface PlansViewProps {
82
+ initialPlans?: PlanSummary[];
83
+ emptyMessage?: string;
84
+ planHref?: PlanCardProps["planHref"];
85
+ LinkComponent?: ComponentType<LinkLikeProps>;
86
+ CardComponent?: ComponentType<PlanCardProps>;
87
+ }
88
+
89
+ export default function PlansView({
90
+ initialPlans,
91
+ emptyMessage = "No plans yet — check back soon.",
92
+ planHref,
93
+ LinkComponent,
94
+ CardComponent = PlanCard,
95
+ }: PlansViewProps) {
96
+ const { plans, error } = usePlans({ initialPlans });
97
+ const { purchase, purchasingId, error: purchaseError } = usePlanPurchase();
98
+
99
+ return (
100
+ <div>
101
+ {(error ?? purchaseError) && <p className="mb-4 text-sm text-red-600">{error ?? purchaseError}</p>}
102
+ {plans === null ? (
103
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3" aria-busy="true">
104
+ {Array.from({ length: 3 }, (_, i) => (
105
+ <div key={i} className="h-80 animate-pulse rounded-lg bg-secondary" />
106
+ ))}
107
+ </div>
108
+ ) : plans.length === 0 ? (
109
+ <p className="py-16 text-center text-muted-foreground">{emptyMessage}</p>
110
+ ) : (
111
+ <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
112
+ {plans.map((p) => (
113
+ <CardComponent
114
+ key={p.id}
115
+ plan={p}
116
+ onSubscribe={(id) => void purchase(id).catch(() => {})}
117
+ purchasing={purchasingId === p.id}
118
+ planHref={planHref}
119
+ LinkComponent={LinkComponent}
120
+ />
121
+ ))}
122
+ </div>
123
+ )}
124
+ </div>
125
+ );
126
+ }