@wix/agent-skills 1.13.0 → 1.15.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 (250) hide show
  1. package/README.md +4 -1
  2. package/package.json +1 -1
  3. package/skills/README.md +23 -0
  4. package/skills/wix-app/SKILL.md +10 -2
  5. package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +326 -0
  6. package/skills/wix-app/references/CODE_QUALITY.md +1 -0
  7. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +124 -115
  8. package/skills/wix-app/references/DASHBOARD_PAGE.md +3 -0
  9. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +23 -9
  10. package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
  11. package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
  12. package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
  13. package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
  14. package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
  15. package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
  16. package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
  17. package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
  18. package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
  19. package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
  20. package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
  21. package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
  22. package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
  23. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
  24. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
  25. package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
  26. package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
  27. package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
  28. package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
  29. package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
  30. package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
  31. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
  32. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
  33. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
  34. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +17 -105
  35. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
  36. package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
  37. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +15 -15
  38. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
  39. package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
  40. package/skills/wix-auth/SKILL.md +12 -0
  41. package/skills/wix-auth/references/device-flow.md +140 -0
  42. package/skills/wix-docs/SKILL.md +188 -0
  43. package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
  44. package/skills/wix-docs/references/EXTRACTING.md +120 -0
  45. package/skills/wix-headless/SKILL.md +84 -130
  46. package/skills/wix-headless/entry/bootstrap.mjs +93 -0
  47. package/skills/wix-headless/entry/skill.md +78 -0
  48. package/skills/wix-headless/references/AI_FEATURES.md +178 -0
  49. package/skills/wix-headless/references/CAPABILITIES.md +84 -0
  50. package/skills/wix-headless/references/DISCOVERY.md +34 -56
  51. package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
  52. package/skills/wix-headless/references/FEEDBACK.md +118 -0
  53. package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
  54. package/skills/wix-headless/references/SDK_HANDOFF.md +97 -0
  55. package/skills/wix-headless/references/SEED.md +44 -188
  56. package/skills/wix-headless/references/SETUP.md +32 -103
  57. package/skills/wix-headless/references/astro.md +98 -0
  58. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
  59. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
  60. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
  61. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
  62. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
  63. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
  64. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
  65. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
  66. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
  67. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
  70. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +173 -0
  71. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
  72. package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
  73. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +228 -0
  74. package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
  75. package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
  76. package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
  77. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +176 -0
  78. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +153 -0
  79. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
  80. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +161 -0
  81. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +117 -0
  82. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
  83. package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
  84. package/skills/wix-headless/references/managed/CONNECT.md +74 -0
  85. package/skills/wix-headless/references/managed/CREATE.md +130 -0
  86. package/skills/wix-headless/references/managed/DEPLOYMENT.md +57 -0
  87. package/skills/wix-headless/references/non-astro.md +59 -0
  88. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
  89. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +7 -0
  90. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
  91. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +63 -0
  92. package/skills/wix-manage/SKILL.md +24 -1
  93. package/skills/wix-manage/references/analytics/query-site-analytics.md +241 -0
  94. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
  95. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +265 -0
  96. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +436 -0
  97. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +209 -0
  98. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
  99. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +51 -0
  100. package/skills/wix-vibe-headless/SKILL.md +136 -0
  101. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
  102. package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
  103. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +153 -0
  104. package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
  105. package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +215 -0
  106. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
  107. package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
  108. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
  109. package/skills/wix-vibe-headless/references/events/wix-events-browse.js +135 -0
  110. package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
  111. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
  112. package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
  113. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
  114. package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +194 -0
  115. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
  116. package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
  117. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
  118. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
  119. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
  120. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
  121. package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
  122. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +155 -0
  123. package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
  124. package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +142 -0
  125. package/skills/wix-headless/references/BUILD-astro.md +0 -244
  126. package/skills/wix-headless/references/BUILD-own-build.md +0 -167
  127. package/skills/wix-headless/references/BUILD.md +0 -105
  128. package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
  129. package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
  130. package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
  131. package/skills/wix-headless/references/PLAN-connect.md +0 -19
  132. package/skills/wix-headless/references/PLAN-create.md +0 -17
  133. package/skills/wix-headless/references/PLAN.md +0 -92
  134. package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
  135. package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
  136. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
  137. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
  138. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
  139. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
  140. package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
  141. package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
  142. package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
  143. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
  144. package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
  145. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
  146. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
  147. package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
  148. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
  149. package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
  150. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
  151. package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
  152. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
  153. package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
  154. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
  155. package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
  156. package/skills/wix-headless/references/astro/templates/Footer.astro +0 -27
  157. package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
  158. package/skills/wix-headless/references/astro/templates/Navigation.astro +0 -38
  159. package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
  160. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
  161. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
  162. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
  163. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
  164. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
  165. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
  166. package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
  167. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
  168. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
  169. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
  170. package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
  171. package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
  172. package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
  173. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
  174. package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
  175. package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
  176. package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
  177. package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
  178. package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
  179. package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
  180. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
  181. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
  182. package/skills/wix-headless/references/astro/templates/global.css +0 -288
  183. package/skills/wix-headless/references/astro/templates/index.astro +0 -56
  184. package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
  185. package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
  186. package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
  187. package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
  188. package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
  189. package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
  190. package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
  191. package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
  192. package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
  193. package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
  194. package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
  195. package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
  196. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
  197. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
  198. package/skills/wix-headless/references/bookings/FLOW.md +0 -246
  199. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
  200. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
  201. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
  202. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
  203. package/skills/wix-headless/references/commands/known-apps.json +0 -6
  204. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
  205. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
  206. package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
  207. package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
  208. package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
  209. package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
  210. package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
  211. package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
  212. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
  213. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
  214. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
  215. package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
  216. package/skills/wix-headless/references/seed-recipes.md +0 -49
  217. package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
  218. package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
  219. package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
  220. package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
  221. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
  222. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
  223. package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
  224. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
  225. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
  226. package/skills/wix-headless/references/shared/STYLING.md +0 -141
  227. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
  228. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
  229. package/skills/wix-headless/references/verticals/_schema.json +0 -74
  230. package/skills/wix-headless/references/verticals/_schema.md +0 -95
  231. package/skills/wix-headless/references/verticals/blog.md +0 -31
  232. package/skills/wix-headless/references/verticals/bookings.md +0 -41
  233. package/skills/wix-headless/references/verticals/cms.md +0 -30
  234. package/skills/wix-headless/references/verticals/ecom.md +0 -25
  235. package/skills/wix-headless/references/verticals/forms.md +0 -26
  236. package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
  237. package/skills/wix-headless/references/verticals/stores.md +0 -33
  238. package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
  239. package/skills/wix-headless/scripts/compose.mjs +0 -525
  240. package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
  241. package/skills/wix-headless/scripts/flatten.sh +0 -61
  242. package/skills/wix-headless/scripts/generate-images.mjs +0 -242
  243. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -148
  244. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
  245. package/skills/wix-headless/scripts/scaffold.sh +0 -139
  246. package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
  247. package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
  248. package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
  249. package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
  250. package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
@@ -0,0 +1,111 @@
1
+
2
+ # Wix Portfolio Skill
3
+
4
+ > **Source files (in this skill):** the shared transport `references/shared/wix-client.js` and this vertical's `references/portfolio/wix-portfolio.js`. Copy **both** into your app's `src/rest/` side by side — the helper does `import { wixApiRequest } from "./wix-client.js"`, so they must land in the same folder.
5
+
6
+ Builds a real, client-only Wix portfolio showcase. The browser talks to Wix directly over a
7
+ public `WIX_CLIENT_ID`. Portfolio is **read-only**: never mock projects, never invent media,
8
+ and always render live Wix data (or an honest empty state). The content tree is
9
+ **Collection → Project → Project Item (image/video)**.
10
+
11
+ ## When to use
12
+ - User wants a Wix portfolio / showcase site or asks to "connect Wix Portfolio".
13
+ - Replacing placeholder/mock galleries with live Wix Portfolio data.
14
+ - Adding a collections gallery, project grids, or a project detail page (media gallery +
15
+ details/links) over an existing Wix Portfolio.
16
+
17
+ ## Prerequisites
18
+ 1. A Wix site with **Wix Portfolio installed and content already added** — at least one
19
+ collection with projects, and projects with items (this skill does NOT provision; it is
20
+ read-only over the content).
21
+ 2. The site's public headless **`WIX_CLIENT_ID`**, provided in the handoff prompt (the Wix
22
+ Business Manager surfaces a copyable prompt with the id filled in — see the router `SKILL.md`).
23
+ Paste it into `src/rest/wix-client.js` in place of the placeholder. It is a visitor-facing
24
+ credential (it only mints anonymous visitor tokens), **not** a secret, so
25
+ hardcoding/committing it is fine.
26
+ 3. If the read calls return `403`/`428` before content is published, the Portfolio app or its
27
+ content may not be live yet. That is a **Wix dashboard setup step the owner completes** —
28
+ out of this skill's scope. Flag it and continue; don't fall back to mock data.
29
+
30
+ ## The API (copy as-is; do not re-derive it)
31
+ This skill ships only the REST layer — no UI components. Build the portfolio's UI however the
32
+ project wants; wire it to these two snippets. Copy them into the app (e.g. `src/api/`) and only
33
+ adjust import paths:
34
+ - `src/rest/wix-client.js` — visitor-token mint/refresh + transport. Set `WIX_CLIENT_ID` to the
35
+ id from the prompt (replace the `<YOUR-CLIENT-ID>` placeholder). The visitor refresh token is
36
+ persisted to localStorage; do not re-mint anonymously per load.
37
+ - `src/rest/wix-portfolio.js` — exports:
38
+ - **Collections:** `queryCollections`, `getCollectionBySlug`, `countCollections`
39
+ - **Projects:** `queryProjects`, `queryProjectsByCollection`, `getProjectBySlug`, `getProject`
40
+ - **Project items (media):** `listProjectItems`
41
+
42
+ The Collection, Project, and Project Item shapes are documented as JSDoc comments at the top of
43
+ `wix-portfolio.js`. Read them before building the UI — they describe the key fields (cover
44
+ image/video, media resolutions, details rows) and link to the full API reference.
45
+
46
+ ## How to wire it (UI is the project's choice)
47
+ - **Collections gallery (home)** — `queryCollections()` for the listing (visible collections
48
+ only, in dashboard order); pass `nextCursor` back as `cursor` to load the next page. Render
49
+ `collection.title`, `collection.description`, and `collection.coverImage.imageInfo.url`. Link
50
+ each card to a collection page keyed on `collection.slug`.
51
+ - **Collection page** — `getCollectionBySlug(slug)` for the header (returns null on miss — show
52
+ a not-found state, never invent one). Then `queryProjectsByCollection(collection.id, { limit?, cursor? })`
53
+ for its project grid; paginate exactly like `queryCollections`.
54
+ - **All-work gallery (optional)** — `queryProjects()` to list every visible project across
55
+ collections (newest-first); paginate the same way.
56
+ - **Project grid card** — render `project.title` and the cover: use `project.coverImage.imageInfo.url`
57
+ when present, else the `project.coverVideo.videoInfo.posters[0]` / first
58
+ `coverVideo.videoInfo.resolutions[]` entry. Link each card to a project page keyed on `project.slug`.
59
+ - **Project detail page** — `getProjectBySlug(slug)` for the header (title, description, and the
60
+ `details[]` rows: each has a `label` plus either `text` or `link: { text, url, target }`).
61
+ Then `listProjectItems(project.id)` for the media gallery — render IMAGE items from
62
+ `image.imageInfo.url` and VIDEO items from the first `video.videoInfo.resolutions[]` entry
63
+ (with `video.videoInfo.posters[0]` as the poster). Honor each item's optional `link`.
64
+ - If you already hold a project id (not a slug), use `getProject(projectId)` instead.
65
+ - **Empty state** — if `countCollections()` is 0, show an empty state telling the user to add
66
+ collections and projects in their Wix dashboard. Never invent projects or media.
67
+
68
+ ## Hard rules (do not violate)
69
+ - ✅ Render only live Wix Portfolio data — collections, projects, and items as returned.
70
+ - ❌ Never mock projects, collections, or media — render live data or the empty state.
71
+ - ❌ Never hand-build Wix Media URLs or page permalinks — use the `url`/`imageInfo.url`/
72
+ `videoInfo.resolutions[].url` fields Wix returns.
73
+ - ❌ Never invent project details, captions, dates, or testimonials. Show only what the API returns.
74
+ - ❌ Never show `hidden: true` collections or projects to visitors (the helpers already filter
75
+ `hidden` out — don't add them back).
76
+ - ✅ Set `WIX_CLIENT_ID` from the prompt's value (public client id — safe to hardcode).
77
+ - ✅ Route on `slug` (`getCollectionBySlug` / `getProjectBySlug`); fall back to `getProject(id)`
78
+ only when you hold a GUID.
79
+ - The helpers fail soft on read: single fetches return `null` on a miss so you render a
80
+ not-found/empty state rather than a crash — surface that state, don't paper over it with fake data.
81
+
82
+ ## Beyond the snippets
83
+ The snippets cover the common portfolio paths. If you hit a use case they don't cover (e.g.
84
+ collection SEO tags, project watermark settings, portfolio-wide settings, or filtering by a
85
+ field not shown), make the call yourself with `wixApiRequest` — but look up the exact endpoint,
86
+ HTTP method, and request body in the **official Wix API reference** first; never guess:
87
+ - Wix Portfolio API reference: https://dev.wix.com/docs/api-reference/business-solutions/portfolio.md
88
+ - Portfolio Settings (logo, layout, options): https://dev.wix.com/docs/api-reference/business-solutions/portfolio/portfolio-settings/get-portfolio-settings.md
89
+ - API query language (filters, sort, paging): https://dev.wix.com/docs/rest/articles/getting-started/api-query-language.md
90
+
91
+ Keep the snippets as the default for everything they already do; reach for the API reference
92
+ only for the gap.
93
+
94
+ ## Point the user to their dashboard
95
+ In some cases, users need to access the Wix dashboard in order to edit the portfolio content for their site. To facilitate this, provide the user with deep links directly to the relevant dashboard pages. For portfolio data those pages are:
96
+ - **Portfolio** — `https://manage.wix.com/dashboard/{metaSiteId}/wix-portfolio/projects` (`Dashboard → Portfolio`). Projects and Collections are tabs on this one page: the **Projects** tab adds projects and their media galleries; the **Collections** tab groups projects into collections.
97
+
98
+ Substitute the site's `metaSiteId` to complete the links (you have it from the handoff / `ListWixSites`). Include the in-dashboard navigation as a fallback.
99
+
100
+ ## Verification checklist (before declaring done)
101
+ - [ ] `WIX_CLIENT_ID` set to the prompt's value (not the `<YOUR-CLIENT-ID>` placeholder)
102
+ - [ ] Visitor token persists across reload (no re-mint storm; reads stay fast)
103
+ - [ ] Collections gallery renders live collections with cover images, in dashboard order
104
+ - [ ] Clicking a collection lists its projects via `queryProjectsByCollection`
105
+ - [ ] Project page renders the project's media gallery from `listProjectItems` (images AND videos)
106
+ - [ ] Project `details[]` rows render (text rows and link rows both)
107
+ - [ ] Slug routing works; an unknown slug shows a not-found state (no invented project)
108
+ - [ ] Hidden collections/projects never appear
109
+ - [ ] Empty state shown when `countCollections()` is 0
110
+ - [ ] No mock projects, collections, or media anywhere
111
+ - [ ] Told the user at least once that they can continue setting up their portfolio in the dashboard and provided deep links.
@@ -0,0 +1,194 @@
1
+ import { wixApiRequest } from "./wix-client.js";
2
+
3
+ /**
4
+ * Wix Portfolio — read-only showcase. 3-level tree:
5
+ * Collection → Project → Project Item (image or video)
6
+ * Hidden entities (hidden: true) are editor-only — every helper here filters them out.
7
+ *
8
+ * Collection: { id, title, description, slug, hidden, sortOrder,
9
+ * coverImage.imageInfo: { id, url, height, width, altText },
10
+ * url: { relativePath, url } (only when includePageUrl=true) }
11
+ * Full model: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/collection-object.md
12
+ *
13
+ * Project: { id, title, description, slug, hidden, collectionIds {string[]},
14
+ * details {array} — [{ label, text? OR link: { text, url, target } }],
15
+ * coverImage.imageInfo: { id, url, height, width, altText } (ONE-OF with coverVideo),
16
+ * coverVideo.videoInfo: { id, url, posters, resolutions },
17
+ * url: { relativePath, url } (only when includePageUrl=true) }
18
+ * Full media gallery is in Project Items — fetch with listProjectItems(project.id).
19
+ * Full model: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/project-object.md
20
+ *
21
+ * Project Item: { id, projectId, sortOrder, title, description,
22
+ * type "IMAGE"|"VIDEO"|"UNDEFINED",
23
+ * image.imageInfo: { id, url, height, width, altText } (when IMAGE),
24
+ * video.videoInfo: { id, url, posters, resolutions } (when VIDEO; render first resolution),
25
+ * link: { text, url, target } }
26
+ * Full model: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/project-items/project-item-object.md
27
+ */
28
+
29
+ const COLLECTIONS_QUERY_URL = "/portfolio/v1/collections/query";
30
+ const PROJECTS_QUERY_URL = "/portfolio/v1/projects/query";
31
+
32
+ /**
33
+ * Query visible portfolio collections (one page), sorted by their dashboard order.
34
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/query-collections.md
35
+ * @param {{ limit?: number, cursor?: string }} [options]
36
+ * @returns {Promise<{ collections: object[], nextCursor: string|null }>}
37
+ */
38
+ export async function queryCollections({ limit = 100, cursor } = {}) {
39
+ const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
40
+ method: "POST",
41
+ body: {
42
+ includePageUrl: true,
43
+ query: cursor
44
+ ? { cursorPaging: { limit, cursor } }
45
+ : {
46
+ filter: { hidden: false },
47
+ sort: [{ fieldName: "sortOrder", order: "ASC" }],
48
+ cursorPaging: { limit },
49
+ },
50
+ },
51
+ });
52
+ return {
53
+ collections: res?.collections ?? [],
54
+ nextCursor: res?.metadata?.cursors?.next ?? null,
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Get a single visible collection by its URL slug. Returns null if not found / hidden.
60
+ * Portfolio has no get-by-slug endpoint, so this queries with a slug filter.
61
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/query-collections.md
62
+ * @param {string} slug
63
+ * @returns {Promise<object|null>}
64
+ */
65
+ export async function getCollectionBySlug(slug) {
66
+ const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
67
+ method: "POST",
68
+ body: {
69
+ includePageUrl: true,
70
+ query: { filter: { slug, hidden: false }, cursorPaging: { limit: 1 } },
71
+ },
72
+ });
73
+ return res?.collections?.[0] ?? null;
74
+ }
75
+
76
+ /**
77
+ * Total number of visible collections. Used for empty-state logic
78
+ * (0 → prompt the user to add collections in their Wix dashboard).
79
+ * @returns {Promise<number>}
80
+ */
81
+ export async function countCollections() {
82
+ const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
83
+ method: "POST",
84
+ body: { query: { filter: { hidden: false }, cursorPaging: { limit: 100 } } },
85
+ });
86
+ return res?.metadata?.total ?? (res?.collections?.length ?? 0);
87
+ }
88
+
89
+ /**
90
+ * Query visible projects (one page), sorted newest-first. Use for an "all work" gallery.
91
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/query-projects.md
92
+ * @param {{ limit?: number, cursor?: string }} [options]
93
+ * @returns {Promise<{ projects: object[], nextCursor: string|null }>}
94
+ */
95
+ export async function queryProjects({ limit = 100, cursor } = {}) {
96
+ const res = await wixApiRequest(PROJECTS_QUERY_URL, {
97
+ method: "POST",
98
+ body: {
99
+ includePageUrl: true,
100
+ query: cursor
101
+ ? { cursorPaging: { limit, cursor } }
102
+ : {
103
+ filter: { hidden: false },
104
+ sort: [{ fieldName: "createdDate", order: "DESC" }],
105
+ cursorPaging: { limit },
106
+ },
107
+ },
108
+ });
109
+ return {
110
+ projects: res?.projects ?? [],
111
+ nextCursor: res?.metadata?.cursors?.next ?? null,
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Query the visible projects that belong to a collection (one page), in dashboard order.
117
+ * Filters on `collectionIds` with `$hasSome`.
118
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/query-projects.md
119
+ * @param {string} collectionId `collection.id` from queryCollections / getCollectionBySlug.
120
+ * @param {{ limit?: number, cursor?: string }} [options]
121
+ * @returns {Promise<{ projects: object[], nextCursor: string|null }>}
122
+ */
123
+ export async function queryProjectsByCollection(collectionId, { limit = 100, cursor } = {}) {
124
+ const res = await wixApiRequest(PROJECTS_QUERY_URL, {
125
+ method: "POST",
126
+ body: {
127
+ includePageUrl: true,
128
+ query: cursor
129
+ ? { cursorPaging: { limit, cursor } }
130
+ : {
131
+ filter: { hidden: false, collectionIds: { $hasSome: [collectionId] } },
132
+ cursorPaging: { limit },
133
+ },
134
+ },
135
+ });
136
+ return {
137
+ projects: res?.projects ?? [],
138
+ nextCursor: res?.metadata?.cursors?.next ?? null,
139
+ };
140
+ }
141
+
142
+ /**
143
+ * Get a single visible project by its URL slug. Returns null if not found / hidden.
144
+ * Portfolio has no get-by-slug endpoint, so this queries with a slug filter.
145
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/query-projects.md
146
+ * @param {string} slug
147
+ * @returns {Promise<object|null>}
148
+ */
149
+ export async function getProjectBySlug(slug) {
150
+ const res = await wixApiRequest(PROJECTS_QUERY_URL, {
151
+ method: "POST",
152
+ body: {
153
+ includePageUrl: true,
154
+ query: { filter: { slug, hidden: false }, cursorPaging: { limit: 1 } },
155
+ },
156
+ });
157
+ return res?.projects?.[0] ?? null;
158
+ }
159
+
160
+ /**
161
+ * Get a single project by its GUID. Returns null if not found.
162
+ * Use when you already hold a project id (e.g. from a list) rather than a slug.
163
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/get-project.md
164
+ * @param {string} projectId
165
+ * @returns {Promise<object|null>}
166
+ */
167
+ export async function getProject(projectId) {
168
+ try {
169
+ const res = await wixApiRequest(`/portfolio/v1/projects/${encodeURIComponent(projectId)}`, {
170
+ method: "GET",
171
+ query: { includePageUrl: "true" },
172
+ });
173
+ return res?.project ?? null;
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+
179
+ /**
180
+ * List all media items (images/videos) of a project, in dashboard order.
181
+ * This is the project's gallery — call it on the project detail screen.
182
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/project-items/list-project-items.md
183
+ * @param {string} projectId `project.id`.
184
+ * @param {{ limit?: number, offset?: number }} [options] Project items use offset paging, not cursors.
185
+ * @returns {Promise<{ items: object[], total: number }>}
186
+ */
187
+ export async function listProjectItems(projectId, { limit = 100, offset = 0 } = {}) {
188
+ const res = await wixApiRequest(`/portfolio/v1/projectItems/${encodeURIComponent(projectId)}/items`, {
189
+ method: "GET",
190
+ query: { "paging.limit": String(limit), "paging.offset": String(offset) },
191
+ });
192
+ const items = (res?.items ?? []).slice().sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
193
+ return { items, total: res?.metadata?.total ?? items.length };
194
+ }
@@ -0,0 +1,127 @@
1
+
2
+ # Wix Pricing Plans Skill
3
+
4
+ > **Source files (in this skill):** the shared transport `references/shared/wix-client.js` and this vertical's `references/pricing-plans/wix-pricing-plans.js`. Copy **both** into your app's `src/rest/` side by side — the helper does `import { wixApiRequest } from "./wix-client.js"`, so they must land in the same folder.
5
+
6
+ Builds a real, client-only Wix pricing-plans / membership front end. The browser talks to Wix
7
+ directly over a public `WIX_CLIENT_ID`. Never mock plans; never hand-build a `/checkout` or
8
+ purchase URL — purchasing always goes through the Wix-hosted **redirect-session** (which also
9
+ handles member login and payment).
10
+
11
+ ## When to use
12
+ - User wants a "Plans & Pricing", membership, or subscription page on a Wix site.
13
+ - User asks to "connect Wix pricing plans" or sell memberships / subscriptions / paid plans.
14
+ - Replacing placeholder/mock plans with live Wix data.
15
+ - Adding a plan detail page, a buy/subscribe button, or a "my plans" area over existing plans.
16
+
17
+ ## Prerequisites
18
+ 1. A Wix site with **Pricing Plans installed and at least one plan created** (this skill does
19
+ NOT provision — it's read-only over the plans the merchant added in the dashboard).
20
+ 2. The site's public headless **`WIX_CLIENT_ID`**, provided in the handoff prompt (the Wix
21
+ Business Manager surfaces a copyable prompt with the id filled in — see the router `SKILL.md`). Paste
22
+ it into `src/rest/wix-client.js` in place of the placeholder. It is a buyer-facing credential
23
+ (it only mints anonymous visitor tokens), **not** a secret, so hardcoding/committing it is fine.
24
+ 3. **Purchasing a plan is members-only and uses Wix-hosted checkout.** The hosted flow handles
25
+ member login/signup + the order form + payment, then returns to your site. The deployed app
26
+ domain must be allow-listed on the OAuth client for that return to work — this is a **separate
27
+ Wix setup flow the user completes later**, out of this skill's scope. If the return fails
28
+ before that setup is done, that's expected; flag it and continue.
29
+ 4. To actually charge for paid plans, the site needs a payment method connected and (where
30
+ applicable) tax/business-address configured in the Wix dashboard. Free plans work without this.
31
+
32
+ ## The API (copy as-is; do not re-derive it)
33
+ This skill ships only the REST layer — no UI components. Build the page's UI however the project
34
+ wants; wire it to these two snippets. Copy them into the app (e.g. `src/api/`) and only adjust
35
+ import paths:
36
+ - `src/rest/wix-client.js` — visitor-token mint/refresh + transport. Set `WIX_CLIENT_ID` to the
37
+ id from the prompt (replace the `<YOUR-CLIENT-ID>` placeholder). The visitor refresh token is
38
+ persisted to localStorage; after a hosted checkout the same identity returns as a logged-in
39
+ member. Do not re-mint anonymously per load.
40
+ - `src/rest/wix-pricing-plans.js` — exports:
41
+ - **Plans:** `queryPlans`, `getPlanById`, `getPlanBySlug`
42
+ - **Purchase:** `checkout`
43
+ - **Member:** `getMyPlanOrders`
44
+
45
+ The Plan and Order shapes are documented as JSDoc comments at the top of `wix-pricing-plans.js`.
46
+ Read them before building the UI — pricing has several models (recurring subscription,
47
+ single-payment-for-duration, single-payment-unlimited, free, plus free trials) and the JSDoc
48
+ shows exactly how to read price, cycle, and trial for display.
49
+
50
+ ## How to wire it (UI is the project's choice)
51
+ - **Plans grid** — `queryPlans()` for the listing (PUBLIC plans only); pass `nextCursor` back as
52
+ `cursor` to load the next page. For each plan render `name`, `description`, `perks[].description`
53
+ as feature bullets, and the price from `pricingVariants[0]` (see the JSDoc "Reading the price"
54
+ notes: `pricingStrategies[0].flatRate.amount` + plan `currency`, plus `billingCycle` for
55
+ recurring and `freeTrialDays` for trials). Show a "Subscribe"/"Buy" button only when
56
+ `plan.buyable` is true.
57
+ - **Plan detail** — `getPlanBySlug(slug)` keyed off the URL slug (or `getPlanById(id)`); returns
58
+ null on miss — show a not-found state, never invent a plan. Render perks, the full price/billing
59
+ summary, free-trial note, and `termsAndConditions` if present.
60
+ - **Purchase** — `window.location.href = await checkout(planId, { thankYouPageUrl })`. This
61
+ redirects to Wix-hosted checkout, which logs the member in (or signs them up), collects the
62
+ order form, and takes payment. On success Wix returns to `thankYouPageUrl` with a
63
+ `?planOrderId=<GUID>` query param (and `wixMemberLoggedIn`); on abandon/interrupt it returns to
64
+ `postFlowUrl` (defaults to the current page). Never create the order or build the URL yourself.
65
+ - **My plans / confirmation** — `getMyPlanOrders()` for the logged-in member's purchases; filter
66
+ with `{ orderStatuses: ["ACTIVE"] }` for current memberships. After returning from checkout,
67
+ re-fetch (e.g. on mount + `visibilitychange`, or when `planOrderId` is in the URL) to show the
68
+ new order. Returns `[]` for anonymous visitors — show a "log in to see your plans" state, and wire
69
+ that log-in via the **members** vertical (`references/members/`) so they can sign in on your own UI.
70
+ - **Empty state** — if `queryPlans()` returns no plans, show an empty state telling the user to
71
+ create plans in their Wix dashboard. Never invent plans.
72
+
73
+ ## Hard rules (do not violate)
74
+ - ✅ Purchase ONLY via `checkout()` (`/headless/v1/redirect-session` with `paidPlansCheckout`),
75
+ then redirect to `redirectSession.fullUrl`.
76
+ - ❌ Never hand-build a checkout, purchase, or `/plans-checkout` URL; never call create-order
77
+ directly from the client to "skip" the hosted flow.
78
+ - ❌ Never mock plans — render live Wix data or the empty state.
79
+ - ❌ Never invent perks, prices, trials, testimonials, or member counts. Render only what the
80
+ plan object returns; empty perks → no feature list.
81
+ - ✅ Set `WIX_CLIENT_ID` from the prompt's value (public client id — safe to hardcode).
82
+ - ✅ Treat plan objects as display-only — never compute the final charge; Wix settles price, tax,
83
+ proration, and schedule during hosted checkout.
84
+ - ✅ Show the buy button only when `plan.buyable` is true; otherwise the plan is merchant-assigned.
85
+ - The engine fails loudly on purpose: `checkout()` throws if it can't create the redirect session.
86
+ A green path means it really reached Wix-hosted checkout — don't swallow these.
87
+
88
+ ## Beyond the snippets
89
+ The snippets cover the common plans paths. If you hit a use case they don't cover, make the call
90
+ yourself with `wixApiRequest` — but look up the exact endpoint, HTTP method, and request body in
91
+ the **official Wix API reference** first; never guess:
92
+ - Pricing Plans API reference: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans.md
93
+ - Orders (cancel / pause / resume a member's order, price preview): https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/orders.md
94
+ - Headless redirect session (login, logout, other checkouts): https://dev.wix.com/docs/api-reference/business-management/headless/redirects/create-redirect-session.md
95
+
96
+ Common genuine gaps and where to look:
97
+ - **Cancel / pause / resume** a member's subscription → Orders API (`request-cancellation`,
98
+ `pause-order`, `resume-order`). Gate on `plan.buyerCanCancel`.
99
+ - **Member login / logout** outside of a purchase → use the **members** vertical
100
+ (`references/members/INSTRUCTIONS.md`) for *custom* login (email+password / Google / Facebook / SSO)
101
+ on your own UI — so a member can log in *before* subscribing and see "my plans" without going through
102
+ a purchase. Pair it with this vertical whenever plans need a real account surface.
103
+ - **Coupons / custom start date** at purchase → covered by the hosted checkout; for a fully
104
+ custom flow see Create Online Order in the Orders reference.
105
+
106
+ Keep the snippets as the default for everything they already do; reach for the API reference only
107
+ for the gap.
108
+
109
+ ## Point the user to their dashboard
110
+ In some cases, users need to access the Wix dashboard in order to edit the pricing plans content for their site. To facilitate this, provide the user with deep links directly to the relevant dashboard pages. For pricing plans data those pages are:
111
+ - **Pricing Plans** — `https://manage.wix.com/dashboard/{metaSiteId}/pricing-plans` (`Dashboard → Pricing Plans`) → **+ Create Plan** (set the name, pricing model, perks, and connect the plan to the content/services it unlocks)
112
+
113
+ Substitute the site's `metaSiteId` to complete the links (you have it from the handoff / `ListWixSites`). Include the in-dashboard navigation as a fallback.
114
+
115
+ ## Verification checklist (before declaring done)
116
+ - [ ] `WIX_CLIENT_ID` set to the prompt's value (not the `<YOUR-CLIENT-ID>` placeholder)
117
+ - [ ] Plans list renders live data; price, billing cycle, and free trial read correctly across
118
+ pricing models (recurring, single-payment, free)
119
+ - [ ] Plan detail loads by slug and shows a not-found state on a bad slug
120
+ - [ ] Buy button shown only for `buyable` plans
121
+ - [ ] Purchase redirects via redirect-session `fullUrl` (no hand-built URL) and reaches
122
+ Wix-hosted login + payment
123
+ - [ ] On return, the new order appears via `getMyPlanOrders()` (and a "log in" state shows for
124
+ anonymous visitors)
125
+ - [ ] Empty state shown when `queryPlans()` returns no plans
126
+ - [ ] No mock plans, perks, or prices anywhere
127
+ - [ ] Told the user at least once that they can continue setting up their plans in the dashboard and provided deep links.
@@ -0,0 +1,157 @@
1
+ import { wixApiRequest } from "./wix-client.js";
2
+
3
+ /**
4
+ * Wix Pricing Plans V3 Plan — key fields for a Plans & Pricing page.
5
+ * Full model: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/plans-v3/plan-object.md
6
+ *
7
+ * id {string}, name {string}, description {string}, slug {string},
8
+ * image {object} — { id, width, height, altText } (id is a WixMedia id),
9
+ * currency {string} — ISO-4217 e.g. "USD", termsAndConditions {string},
10
+ * visibility "PUBLIC"|"PRIVATE" — queryPlans returns PUBLIC only,
11
+ * buyable {boolean} — hide buy button when false, buyerCanCancel {boolean},
12
+ * perks {array} — [{ id, description }] feature bullets,
13
+ * pricingVariants {array} — 1 variant per plan:
14
+ * [{ id, name, freeTrialDays, pricingStrategies[0].flatRate.amount (decimal string, "0" = free),
15
+ * billingTerms: { billingCycle: { period "DAY"|"WEEK"|"MONTH"|"YEAR", count },
16
+ * startType "ON_PURCHASE"|"CUSTOM", endType "UNTIL_CANCELLED"|"CYCLES_COMPLETED" } }]
17
+ * Display price: amount = v.pricingStrategies[0].flatRate.amount + plan.currency.
18
+ * Never compute a final charge — Wix settles price, tax, and schedule at hosted checkout.
19
+ *
20
+ * Order (member's purchase) — key fields for "My plans" screen.
21
+ * Full model: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/orders/order-object.md
22
+ * id {string}, planId {string}, planName {string},
23
+ * status "DRAFT"|"PENDING"|"ACTIVE"|"PAUSED"|"ENDED"|"CANCELED",
24
+ * lastPaymentStatus "PAID"|"REFUNDED"|"FAILED"|"UNPAID"|"NOT_APPLICABLE",
25
+ * startDate {string}, endDate {string}, freeTrialDays {number},
26
+ * currentCycle { index, startedDate, endedDate }, autoRenewCanceled {boolean}
27
+ */
28
+
29
+ const REDIRECT_SESSION_URL = "/headless/v1/redirect-session";
30
+
31
+ /**
32
+ * Query public, listable pricing plans (one page).
33
+ * Returns only PUBLIC plans (the ones meant for the Plans & Pricing page). Some plans may have
34
+ * `buyable: false` (merchant-assigned only) — keep them for display but hide the buy button.
35
+ *
36
+ * Reference: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/plans-v3/query-plans.md
37
+ *
38
+ * @param {{ limit?: number, cursor?: string }} [options]
39
+ * @returns {Promise<{ plans: object[], nextCursor: string|null }>}
40
+ */
41
+ export async function queryPlans({ limit = 100, cursor } = {}) {
42
+ const res = await wixApiRequest("/pricing-plans/v3/plans/query", {
43
+ method: "POST",
44
+ body: {
45
+ query: {
46
+ ...(cursor ? {} : { filter: { visibility: "PUBLIC" } }),
47
+ cursorPaging: cursor ? { limit, cursor } : { limit },
48
+ },
49
+ },
50
+ });
51
+ return {
52
+ plans: res?.plans ?? [],
53
+ nextCursor: res?.pagingMetadata?.cursors?.next ?? null,
54
+ };
55
+ }
56
+
57
+ /**
58
+ * Fetch a single plan by its GUID. Returns null if not found.
59
+ * Reference: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/plans-v3/get-plan.md
60
+ *
61
+ * @param {string} planId Plan GUID (`plan.id`).
62
+ * @returns {Promise<object|null>}
63
+ */
64
+ export async function getPlanById(planId) {
65
+ try {
66
+ const res = await wixApiRequest(`/pricing-plans/v3/plans/${encodeURIComponent(planId)}`, {
67
+ method: "GET",
68
+ });
69
+ return res?.plan ?? null;
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Fetch a single PUBLIC plan by its URL slug. Returns null if not found.
77
+ * There is no get-by-slug endpoint, so this queries with a slug filter and returns the first match.
78
+ * Reference: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/plans-v3/query-plans.md
79
+ *
80
+ * @param {string} slug
81
+ * @returns {Promise<object|null>}
82
+ */
83
+ export async function getPlanBySlug(slug) {
84
+ const res = await wixApiRequest("/pricing-plans/v3/plans/query", {
85
+ method: "POST",
86
+ body: {
87
+ query: {
88
+ filter: { visibility: "PUBLIC", slug },
89
+ cursorPaging: { limit: 1 },
90
+ },
91
+ },
92
+ });
93
+ return res?.plans?.[0] ?? null;
94
+ }
95
+
96
+ /**
97
+ * Start a purchase for a plan and return the Wix-hosted checkout URL.
98
+ *
99
+ * Pricing Plans purchases are MEMBERS-ONLY: the hosted flow handles member login (or signup),
100
+ * the order form, and payment, then returns the visitor to your site. Redirect the browser to the
101
+ * returned URL — do NOT create the order yourself; Wix settles price, tax, and the subscription.
102
+ *
103
+ * On return:
104
+ * - postFlowUrl is hit when the flow completes, is abandoned, or is interrupted.
105
+ * - thankYouPageUrl (if given) is hit only on success, with a `?planOrderId=<GUID>` query param.
106
+ * - Both callbacks also carry `wixMemberLoggedIn` (true if a member logged in during the flow).
107
+ * After a successful purchase the visitor is a logged-in member — call getMyPlanOrders() to confirm.
108
+ *
109
+ * Reference: https://dev.wix.com/docs/api-reference/business-management/headless/redirects/create-redirect-session.md
110
+ *
111
+ * @param {string} planId Plan GUID (`plan.id`). Must be a buyable plan.
112
+ * @param {{ thankYouPageUrl?: string, postFlowUrl?: string }} [options]
113
+ * @returns {Promise<string>} The hosted checkout URL to redirect to.
114
+ */
115
+ export async function checkout(planId, { thankYouPageUrl, postFlowUrl } = {}) {
116
+ if (!planId) throw new Error("Cannot check out: a planId is required.");
117
+ const callbacks = { postFlowUrl: postFlowUrl ?? window.location.href };
118
+ if (thankYouPageUrl) callbacks.thankYouPageUrl = thankYouPageUrl;
119
+
120
+ const redirect = await wixApiRequest(REDIRECT_SESSION_URL, {
121
+ method: "POST",
122
+ body: { paidPlansCheckout: { planId }, callbacks },
123
+ });
124
+ const url = redirect?.redirectSession?.fullUrl;
125
+ if (!url) throw new Error("Failed to create the pricing-plan checkout redirect session.");
126
+ return url;
127
+ }
128
+
129
+ /**
130
+ * List the currently logged-in member's own plan orders (their purchases / subscriptions).
131
+ * Use for a "My plans" screen and to confirm a purchase after returning from checkout.
132
+ *
133
+ * Requires a MEMBER identity. For an anonymous visitor (not logged in) Wix returns no member
134
+ * context — this resolves to `[]` rather than throwing, so the UI can show a "log in to see your
135
+ * plans" state. Up to 50 orders are returned per call.
136
+ *
137
+ * Reference: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/orders/member-orders-service-list-orders.md
138
+ *
139
+ * @param {{ orderStatuses?: string[], limit?: number, offset?: number }} [options]
140
+ * orderStatuses: filter, e.g. ["ACTIVE"] | ["ACTIVE","PENDING","PAUSED"].
141
+ * @returns {Promise<object[]>} The member's orders (empty array if none / not a member).
142
+ */
143
+ export async function getMyPlanOrders({ orderStatuses, limit, offset } = {}) {
144
+ try {
145
+ const res = await wixApiRequest("/pricing-plans/v2/member/orders", {
146
+ method: "GET",
147
+ query: {
148
+ orderStatuses,
149
+ limit: limit !== undefined ? String(limit) : undefined,
150
+ offset: offset !== undefined ? String(offset) : undefined,
151
+ },
152
+ });
153
+ return res?.orders ?? [];
154
+ } catch {
155
+ return [];
156
+ }
157
+ }