@wix/agent-skills 1.14.0 → 1.15.1

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 (268) hide show
  1. package/README.md +12 -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/DATA_COLLECTION.md +5 -3
  10. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +25 -9
  11. package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
  12. package/skills/wix-app/references/STORES_VERSIONING.md +9 -211
  13. package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
  14. package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
  15. package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
  16. package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
  17. package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
  18. package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
  19. package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
  20. package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
  21. package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
  22. package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
  23. package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
  24. package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
  25. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
  26. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
  27. package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
  28. package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
  29. package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
  30. package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
  31. package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
  32. package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
  33. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +5 -0
  34. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
  35. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +151 -0
  36. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
  37. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
  38. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +57 -0
  39. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +23 -105
  40. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
  41. package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
  42. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +18 -16
  43. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
  44. package/skills/wix-app/references/stores/CATEGORIES.md +22 -0
  45. package/skills/wix-app/references/stores/GET_PRODUCT.md +99 -0
  46. package/skills/wix-app/references/stores/INVENTORY.md +37 -0
  47. package/skills/wix-app/references/stores/QUERY.md +87 -0
  48. package/skills/wix-app/references/stores/WRITE.md +55 -0
  49. package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
  50. package/skills/wix-auth/SKILL.md +12 -0
  51. package/skills/wix-auth/references/device-flow.md +140 -0
  52. package/skills/wix-docs/SKILL.md +188 -0
  53. package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
  54. package/skills/wix-docs/references/EXTRACTING.md +120 -0
  55. package/skills/wix-headless/SKILL.md +89 -130
  56. package/skills/wix-headless/entry/bootstrap.mjs +93 -0
  57. package/skills/wix-headless/entry/skill.md +76 -0
  58. package/skills/wix-headless/references/AI_FEATURES.md +178 -0
  59. package/skills/wix-headless/references/CAPABILITIES.md +86 -0
  60. package/skills/wix-headless/references/DISCOVERY.md +34 -56
  61. package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
  62. package/skills/wix-headless/references/FEEDBACK.md +129 -0
  63. package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
  64. package/skills/wix-headless/references/SDK_HANDOFF.md +99 -0
  65. package/skills/wix-headless/references/SEED.md +45 -187
  66. package/skills/wix-headless/references/SETUP.md +32 -103
  67. package/skills/wix-headless/references/astro.md +98 -0
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
  70. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
  71. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
  72. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
  73. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
  74. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
  75. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
  76. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
  77. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
  78. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
  79. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
  80. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +213 -0
  81. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
  82. package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
  83. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +232 -0
  84. package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
  85. package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
  86. package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
  87. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +192 -0
  88. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +155 -0
  89. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
  90. package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +73 -0
  91. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +197 -0
  92. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +136 -0
  93. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
  94. package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
  95. package/skills/wix-headless/references/managed/CONNECT.md +74 -0
  96. package/skills/wix-headless/references/managed/CREATE.md +130 -0
  97. package/skills/wix-headless/references/managed/DEPLOYMENT.md +79 -0
  98. package/skills/wix-headless/references/non-astro.md +59 -0
  99. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
  100. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +15 -0
  101. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
  102. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +71 -0
  103. package/skills/wix-manage/SKILL.md +29 -3
  104. package/skills/wix-manage/references/analytics/query-site-analytics.md +298 -0
  105. package/skills/wix-manage/references/app-installation/install-wix-apps.md +3 -0
  106. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
  107. package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +6 -5
  108. package/skills/wix-manage/references/bookings/create-course-service.md +30 -5
  109. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +299 -0
  110. package/skills/wix-manage/references/cms/cms-schema-management.md +6 -0
  111. package/skills/wix-manage/references/get-paid/how-to-setup-wix-payments.md +30 -7
  112. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +517 -0
  113. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +218 -0
  114. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
  115. package/skills/wix-manage/references/sites/site-import.md +270 -0
  116. package/skills/wix-manage/references/stores/create-product-from-image.md +8 -6
  117. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +57 -0
  118. package/skills/wix-vibe-headless/SKILL.md +142 -0
  119. package/skills/wix-vibe-headless/platforms/README.md +22 -0
  120. package/skills/wix-vibe-headless/platforms/base44.md +142 -0
  121. package/skills/wix-vibe-headless/platforms/generic.md +87 -0
  122. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
  123. package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
  124. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +157 -0
  125. package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
  126. package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +217 -0
  127. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
  128. package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
  129. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
  130. package/skills/wix-vibe-headless/references/events/wix-events-browse.js +136 -0
  131. package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
  132. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
  133. package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
  134. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
  135. package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +223 -0
  136. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
  137. package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
  138. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
  139. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
  140. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
  141. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
  142. package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
  143. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +164 -0
  144. package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
  145. package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +146 -0
  146. package/skills/wix-headless/references/BUILD-astro.md +0 -253
  147. package/skills/wix-headless/references/BUILD-own-build.md +0 -167
  148. package/skills/wix-headless/references/BUILD.md +0 -105
  149. package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
  150. package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
  151. package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
  152. package/skills/wix-headless/references/PLAN-connect.md +0 -19
  153. package/skills/wix-headless/references/PLAN-create.md +0 -17
  154. package/skills/wix-headless/references/PLAN.md +0 -92
  155. package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
  156. package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
  157. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
  158. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
  159. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
  160. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
  161. package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
  162. package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
  163. package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
  164. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
  165. package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
  166. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
  167. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
  168. package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
  169. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
  170. package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
  171. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
  172. package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
  173. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
  174. package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
  175. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
  176. package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
  177. package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
  178. package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
  179. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
  180. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
  181. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
  182. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
  183. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
  184. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
  185. package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
  186. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
  187. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
  188. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
  189. package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
  190. package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
  191. package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
  192. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
  193. package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
  194. package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
  195. package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
  196. package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
  197. package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
  198. package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
  199. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
  200. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
  201. package/skills/wix-headless/references/astro/templates/global.css +0 -288
  202. package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
  203. package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
  204. package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
  205. package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
  206. package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
  207. package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
  208. package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
  209. package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
  210. package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
  211. package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
  212. package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
  213. package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
  214. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
  215. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
  216. package/skills/wix-headless/references/bookings/FLOW.md +0 -246
  217. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
  218. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
  219. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
  220. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
  221. package/skills/wix-headless/references/commands/known-apps.json +0 -6
  222. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
  223. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
  224. package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
  225. package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
  226. package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
  227. package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
  228. package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
  229. package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
  230. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
  231. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
  232. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
  233. package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
  234. package/skills/wix-headless/references/seed-recipes.md +0 -49
  235. package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
  236. package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
  237. package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
  238. package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
  239. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
  240. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
  241. package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
  242. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
  243. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
  244. package/skills/wix-headless/references/shared/STYLING.md +0 -140
  245. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
  246. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
  247. package/skills/wix-headless/references/verticals/_schema.json +0 -74
  248. package/skills/wix-headless/references/verticals/_schema.md +0 -95
  249. package/skills/wix-headless/references/verticals/blog.md +0 -31
  250. package/skills/wix-headless/references/verticals/bookings.md +0 -41
  251. package/skills/wix-headless/references/verticals/cms.md +0 -30
  252. package/skills/wix-headless/references/verticals/ecom.md +0 -25
  253. package/skills/wix-headless/references/verticals/forms.md +0 -26
  254. package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
  255. package/skills/wix-headless/references/verticals/stores.md +0 -33
  256. package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
  257. package/skills/wix-headless/scripts/compose.mjs +0 -520
  258. package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
  259. package/skills/wix-headless/scripts/flatten.sh +0 -61
  260. package/skills/wix-headless/scripts/generate-images.mjs +0 -242
  261. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -154
  262. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
  263. package/skills/wix-headless/scripts/scaffold.sh +0 -139
  264. package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
  265. package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
  266. package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
  267. package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
  268. package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
@@ -0,0 +1,223 @@
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
+ try {
40
+ const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
41
+ method: "POST",
42
+ body: {
43
+ includePageUrl: true,
44
+ query: cursor
45
+ ? { cursorPaging: { limit, cursor } }
46
+ : {
47
+ filter: { hidden: false },
48
+ sort: [{ fieldName: "sortOrder", order: "ASC" }],
49
+ cursorPaging: { limit },
50
+ },
51
+ },
52
+ });
53
+ return {
54
+ collections: res?.collections ?? [],
55
+ nextCursor: res?.metadata?.cursors?.next ?? null,
56
+ };
57
+ } catch (err) {
58
+ // Degrade to an empty page instead of rethrowing: an uncaught read would leave a
59
+ // component's `loading` flag stuck true and hang the gallery on a spinner. Empty
60
+ // renders the same empty state as a genuinely empty backend.
61
+ console.error("queryCollections failed:", err);
62
+ return { collections: [], nextCursor: null };
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Get a single visible collection by its URL slug. Returns null if not found / hidden.
68
+ * Portfolio has no get-by-slug endpoint, so this queries with a slug filter.
69
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/query-collections.md
70
+ * @param {string} slug
71
+ * @returns {Promise<object|null>}
72
+ */
73
+ export async function getCollectionBySlug(slug) {
74
+ const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
75
+ method: "POST",
76
+ body: {
77
+ includePageUrl: true,
78
+ query: { filter: { slug, hidden: false }, cursorPaging: { limit: 1 } },
79
+ },
80
+ });
81
+ return res?.collections?.[0] ?? null;
82
+ }
83
+
84
+ /**
85
+ * Total number of visible collections. Used for empty-state logic
86
+ * (0 → prompt the user to add collections in their Wix dashboard).
87
+ * @returns {Promise<number>}
88
+ */
89
+ export async function countCollections() {
90
+ try {
91
+ const res = await wixApiRequest(COLLECTIONS_QUERY_URL, {
92
+ method: "POST",
93
+ body: { query: { filter: { hidden: false }, cursorPaging: { limit: 100 } } },
94
+ });
95
+ return res?.metadata?.total ?? (res?.collections?.length ?? 0);
96
+ } catch (err) {
97
+ // On failure treat as empty (0) rather than rethrowing — a thrown count would hang
98
+ // the empty-state check; 0 falls through to the "add collections" prompt.
99
+ console.error("countCollections failed:", err);
100
+ return 0;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Query visible projects (one page), sorted newest-first. Use for an "all work" gallery.
106
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/query-projects.md
107
+ * @param {{ limit?: number, cursor?: string }} [options]
108
+ * @returns {Promise<{ projects: object[], nextCursor: string|null }>}
109
+ */
110
+ export async function queryProjects({ limit = 100, cursor } = {}) {
111
+ try {
112
+ const res = await wixApiRequest(PROJECTS_QUERY_URL, {
113
+ method: "POST",
114
+ body: {
115
+ includePageUrl: true,
116
+ query: cursor
117
+ ? { cursorPaging: { limit, cursor } }
118
+ : {
119
+ filter: { hidden: false },
120
+ sort: [{ fieldName: "createdDate", order: "DESC" }],
121
+ cursorPaging: { limit },
122
+ },
123
+ },
124
+ });
125
+ return {
126
+ projects: res?.projects ?? [],
127
+ nextCursor: res?.metadata?.cursors?.next ?? null,
128
+ };
129
+ } catch (err) {
130
+ // Degrade to an empty page instead of rethrowing (see queryCollections) — an uncaught
131
+ // read hangs the gallery on an infinite spinner; empty renders the empty state instead.
132
+ console.error("queryProjects failed:", err);
133
+ return { projects: [], nextCursor: null };
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Query the visible projects that belong to a collection (one page), in dashboard order.
139
+ * Filters on `collectionIds` with `$hasSome`.
140
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/query-projects.md
141
+ * @param {string} collectionId `collection.id` from queryCollections / getCollectionBySlug.
142
+ * @param {{ limit?: number, cursor?: string }} [options]
143
+ * @returns {Promise<{ projects: object[], nextCursor: string|null }>}
144
+ */
145
+ export async function queryProjectsByCollection(collectionId, { limit = 100, cursor } = {}) {
146
+ try {
147
+ const res = await wixApiRequest(PROJECTS_QUERY_URL, {
148
+ method: "POST",
149
+ body: {
150
+ includePageUrl: true,
151
+ query: cursor
152
+ ? { cursorPaging: { limit, cursor } }
153
+ : {
154
+ filter: { hidden: false, collectionIds: { $hasSome: [collectionId] } },
155
+ cursorPaging: { limit },
156
+ },
157
+ },
158
+ });
159
+ return {
160
+ projects: res?.projects ?? [],
161
+ nextCursor: res?.metadata?.cursors?.next ?? null,
162
+ };
163
+ } catch (err) {
164
+ // Degrade to an empty page instead of rethrowing (see queryCollections) — an uncaught
165
+ // read hangs the collection page on an infinite spinner; empty renders the empty state.
166
+ console.error("queryProjectsByCollection failed:", err);
167
+ return { projects: [], nextCursor: null };
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Get a single visible project by its URL slug. Returns null if not found / hidden.
173
+ * Portfolio has no get-by-slug endpoint, so this queries with a slug filter.
174
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/query-projects.md
175
+ * @param {string} slug
176
+ * @returns {Promise<object|null>}
177
+ */
178
+ export async function getProjectBySlug(slug) {
179
+ const res = await wixApiRequest(PROJECTS_QUERY_URL, {
180
+ method: "POST",
181
+ body: {
182
+ includePageUrl: true,
183
+ query: { filter: { slug, hidden: false }, cursorPaging: { limit: 1 } },
184
+ },
185
+ });
186
+ return res?.projects?.[0] ?? null;
187
+ }
188
+
189
+ /**
190
+ * Get a single project by its GUID. Returns null if not found.
191
+ * Use when you already hold a project id (e.g. from a list) rather than a slug.
192
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/get-project.md
193
+ * @param {string} projectId
194
+ * @returns {Promise<object|null>}
195
+ */
196
+ export async function getProject(projectId) {
197
+ try {
198
+ const res = await wixApiRequest(`/portfolio/v1/projects/${encodeURIComponent(projectId)}`, {
199
+ method: "GET",
200
+ query: { includePageUrl: "true" },
201
+ });
202
+ return res?.project ?? null;
203
+ } catch {
204
+ return null;
205
+ }
206
+ }
207
+
208
+ /**
209
+ * List all media items (images/videos) of a project, in dashboard order.
210
+ * This is the project's gallery — call it on the project detail screen.
211
+ * https://dev.wix.com/docs/api-reference/business-solutions/portfolio/project-items/list-project-items.md
212
+ * @param {string} projectId `project.id`.
213
+ * @param {{ limit?: number, offset?: number }} [options] Project items use offset paging, not cursors.
214
+ * @returns {Promise<{ items: object[], total: number }>}
215
+ */
216
+ export async function listProjectItems(projectId, { limit = 100, offset = 0 } = {}) {
217
+ const res = await wixApiRequest(`/portfolio/v1/projectItems/${encodeURIComponent(projectId)}/items`, {
218
+ method: "GET",
219
+ query: { "paging.limit": String(limit), "paging.offset": String(offset) },
220
+ });
221
+ const items = (res?.items ?? []).slice().sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
222
+ return { items, total: res?.metadata?.total ?? items.length };
223
+ }
@@ -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
+ }
@@ -0,0 +1,138 @@
1
+
2
+ # Wix Restaurants Skill
3
+
4
+ > **Source files (in this skill):** the shared transport `references/shared/wix-client.js` and the helper file(s) you need from `references/restaurants/`. All helpers import from `"./wix-client.js"`, so copy them into the same folder (e.g. `src/rest/`).
5
+ >
6
+ > | Need | Copy |
7
+ > |---|---|
8
+ > | Menu display (always) | `wix-restaurants-menu.js` |
9
+ > | Online ordering (cart + checkout) | `wix-restaurants-ordering.js` |
10
+ > | Table reservations | `wix-restaurants-reservations.js` |
11
+
12
+ Builds a real, client-only Wix restaurant experience. The browser talks to Wix directly over a
13
+ public `WIX_CLIENT_ID`. Never mock the menu; never hand-build `/checkout` or reservation URLs —
14
+ always go through the official cart + redirect-session and the reservations hold/reserve flow.
15
+
16
+ ## When to use
17
+ - User wants a Wix restaurant site, an online food-ordering page, or a table-reservation page.
18
+ - User asks to "connect Wix Restaurants" or replace placeholder menu/ordering/booking UI with live data.
19
+ - Adding a menu, cart + checkout, or reservations over an existing Wix Restaurants setup.
20
+
21
+ ## Prerequisites
22
+ 1. A Wix site with the **Wix Restaurants Menus** app installed and **menu content already added**
23
+ (this skill is read-only over the menu — it does NOT create menus/items).
24
+ 2. For **online ordering**: at least one online-ordering **Operation** configured (Wix Restaurants
25
+ Orders). For **reservations**: the **Table Reservations** app installed with at least one location
26
+ and online reservations enabled. If a flow's backing app/config isn't set up, that flow returns
27
+ empty — flag it and continue; don't fabricate data.
28
+ 3. The site's public headless **`WIX_CLIENT_ID`**, provided in the handoff prompt (see the router `SKILL.md`).
29
+ Paste it into `src/rest/wix-client.js` in place of the placeholder. It is a buyer-facing
30
+ credential (it only mints anonymous visitor tokens), **not** a secret — hardcoding/committing
31
+ it is fine.
32
+ 4. The deployed app domain must be allow-listed on the OAuth client for Wix-hosted checkout to
33
+ return. This is a **separate Wix setup flow the user completes later** — out of this skill's
34
+ scope. If checkout return fails before that setup is done, that's expected; flag it and continue.
35
+
36
+ ## The API (copy as-is; do not re-derive it)
37
+ This skill ships only the REST layer — no UI components. Build the restaurant UI however the
38
+ project wants; wire it to these two snippets. Copy them into the app (e.g. `src/api/`) and only
39
+ adjust import paths:
40
+ - `src/rest/wix-client.js` — visitor-token mint/refresh + transport. Set `WIX_CLIENT_ID` to the id
41
+ from the prompt (replace the `<YOUR-CLIENT-ID>` placeholder). The visitor refresh token IS the
42
+ cart identity; it is persisted to localStorage. Do not re-mint anonymously per load or the cart
43
+ silently empties.
44
+ - `src/rest/wix-restaurants-menu.js` — **Menu (read-only):**
45
+ `getFullMenu` (the assembled tree — start here), `listMenus`, `listSections`, `listItems`,
46
+ `listVariants`, `listModifierGroups`, `listModifiers`, `listLabels`
47
+ - `src/rest/wix-restaurants-ordering.js` — **Online ordering:**
48
+ `listOperations`, `getDefaultOperation`, `addItemToCart`, `getCurrentCart`,
49
+ `updateCartItemQuantity`, `removeFromCart`, `checkout`
50
+ - `src/rest/wix-restaurants-reservations.js` — **Reservations:**
51
+ `listReservationLocations`, `getTimeSlots`, `createHeldReservation`, `reserveReservation`
52
+
53
+ The Menu, Item, ModifierGroup, Operation, Cart, ReservationLocation, TimeSlot, and Reservation
54
+ shapes are documented as JSDoc at the top of each helper file. Read the relevant file(s) before
55
+ building the UI — they describe the key fields and link to the full reference for anything not shown.
56
+
57
+ ## How to wire it (UI is the project's choice)
58
+ - **Menu page** — call `getFullMenu()` once. It returns `{ menus: [{ ...menu, sections: [{ ...section,
59
+ items: [assembledItem] }] }] }`, already ordered by `sectionIds` / `itemIds`. Render each item's
60
+ `name`, `description`, `image`, `labels` (`name` + `icon`), and `featured` flag. For price, show
61
+ `item.price` (single) or the `item.variants[]` (each `{ name, price }`). **Restaurants prices are
62
+ plain decimal strings with NO currency symbol** — format with the site's currency in the UI.
63
+ - **Item detail** — render `item.modifierGroups[]`: each group's `name`, its `rule`
64
+ (`required`, `minSelections`, `maxSelections`), and `modifiers[]` (`name`, `additionalCharge`,
65
+ `preSelected`, `inStock`). If `orderSettings.acceptSpecialRequests`, offer a free-text field.
66
+ - **Online ordering** — resolve an operation with `getDefaultOperation()` (or let the user pick from
67
+ `listOperations()`); if it's `null`, show an "ordering unavailable" state. Add a dish with
68
+ `addItemToCart(item.id, { operationId, menuId, sectionId, quantity })` — `menuId`/`sectionId` are
69
+ the menu and section the item was shown under. Read the cart back with `getCurrentCart()`; mutate
70
+ with `updateCartItemQuantity(lineItemId, qty)` / `removeFromCart(lineItemId)` using
71
+ `cart.lineItems[].id` (not the item id).
72
+ - **Checkout** — `window.location.href = await checkout()`. After the visitor returns, the order is
73
+ placed and the cart is empty — re-fetch with `getCurrentCart()` on return (e.g. on mount +
74
+ `visibilitychange`) to clear the UI.
75
+ - **Reservations** — `listReservationLocations()` for the picker (use `location` details for the
76
+ label; if a location's `configuration.onlineReservations.onlineReservationsEnabled` is false, hide
77
+ it). Then `getTimeSlots(locationId, dateISO, partySize)` — render `availableTimeSlots` (already
78
+ filtered to `AVAILABLE`). On slot pick, `createHeldReservation(locationId, slot.startDate,
79
+ partySize)` → keep the returned `id` + `revision`. Collect the visitor's details, then
80
+ `reserveReservation(id, revision, { firstName, phone, lastName?, email? })`. A `RESERVED` status is
81
+ confirmed; `REQUESTED` means the location requires manual approval — tell the user it's pending.
82
+ - **Empty state** — if `getFullMenu()` returns no menus, show an empty state telling the user to add
83
+ a menu in their Wix dashboard. Never invent menu items.
84
+
85
+ ## Hard rules (do not violate)
86
+ - ✅ Order ONLY through the cart: `addItemToCart()` → `checkout()` (`create-checkout` →
87
+ `/headless/v1/redirect-session` `fullUrl`), then redirect.
88
+ - ❌ Never hand-build `/checkout`, ordering, or reservation URLs.
89
+ - ❌ Never mock menus, items, prices, operations, locations, or time slots — render live Wix data or
90
+ the empty state.
91
+ - ❌ Never generate fake reviews, ratings, or testimonials. Empty review UI only.
92
+ - ✅ Set `WIX_CLIENT_ID` from the prompt's value (public client id — safe to hardcode).
93
+ - ✅ `addItemToCart` requires `operationId`, `menuId`, and `sectionId` — it throws if any is missing.
94
+ - ✅ `lineItemId` for cart mutations is `cart.lineItems[].id`, not the item id.
95
+ - ✅ Reservations: offer only `AVAILABLE` slots; a HELD reservation expires in 10 minutes — pass the
96
+ `revision` from the hold into `reserveReservation`, and restart the flow if it expired.
97
+ - ✅ Reservee `firstName` + `phone` (E.164, e.g. `+15551234567`) are mandatory to confirm.
98
+ - The engine fails loudly on purpose: `addItemToCart`/`checkout` throw on out-of-stock or empty
99
+ carts; reservation helpers throw on unavailable slots or expired holds. A green path means it is
100
+ really orderable/bookable — don't swallow these.
101
+
102
+ ## Beyond the snippets
103
+ The snippets cover the common menu / ordering / reservation paths. For the "20%" they don't cover,
104
+ make the call yourself with `wixApiRequest` — but look up the exact endpoint, HTTP method, and
105
+ request body in the **official Wix API reference** first; never guess:
106
+ - Restaurants API reference: https://dev.wix.com/docs/api-reference/business-solutions/restaurants.md
107
+ - Selecting a specific **price variant** or applying **modifier up-charges** on the cart line: the
108
+ restaurants `catalogReference.options` shape for these is not documented for client add-to-cart.
109
+ The menu UI still displays them; confirm the shape before wiring them into `addItemToCart`:
110
+ https://dev.wix.com/docs/api-reference/business-solutions/restaurants/online-orders/sample-flows.md
111
+ - Fulfillment methods, delivery-address validation, scheduled (preorder) time slots, service fees:
112
+ see the Online Orders section of the reference.
113
+ - **Member login + a "my orders" account view** → the **members** vertical
114
+ (`references/members/INSTRUCTIONS.md`): ordering/reserving works anonymously, but signing a member
115
+ in (custom login on your own UI) lets them see their own order/reservation history.
116
+
117
+ Keep the snippets as the default for everything they already do; reach for the API reference only
118
+ for the gap.
119
+
120
+ ## Point the user to their dashboard
121
+ In some cases, users need to access the Wix dashboard in order to edit the restaurant content for their site — across up to three apps. To facilitate this, provide the user with deep links directly to the relevant dashboard pages; only mention the apps the project actually uses. Those pages are:
122
+ - **Menu** (always) — `https://manage.wix.com/dashboard/{metaSiteId}/wix-restaurants-menus-new` (`Dashboard → Restaurant Menus`; click **Manage Items** to add dishes; only visible menus appear in the app)
123
+ - **Online ordering** (if wired) — `https://manage.wix.com/dashboard/{metaSiteId}/wix-restaurants-orders-new/settings` (`Dashboard → Restaurant Orders → Settings`). Enable at least one fulfillment method before the site accepts orders — each has its own page: pickup `https://manage.wix.com/dashboard/{metaSiteId}/wix-restaurants-orders-new/settings/pickup`, delivery `.../wix-restaurants-orders-new/settings/delivery`, dine-in `.../wix-restaurants-orders-new/settings/dine-in`.
124
+ - **Table reservations** (if wired) — `https://manage.wix.com/dashboard/{metaSiteId}/wix-table-reservations/table-reservations` (`Dashboard → Table Reservations` → **Settings**; configure tables, availability, and enable online reservations)
125
+
126
+ Substitute the site's `metaSiteId` to complete the links (you have it from the handoff / `ListWixSites`). Include the in-dashboard navigation as a fallback.
127
+
128
+ ## Verification checklist (before declaring done)
129
+ - [ ] `WIX_CLIENT_ID` set to the prompt's value (not the `<YOUR-CLIENT-ID>` placeholder)
130
+ - [ ] Visitor token persists across reload (cart survives reload, same visitor)
131
+ - [ ] `getFullMenu()` renders real sections/items with prices, variants, modifiers, and labels
132
+ - [ ] Empty state shown when there are no menus (never invented items)
133
+ - [ ] Add to cart works with a real `operationId`/`menuId`/`sectionId`; out-of-stock items throw
134
+ - [ ] Quantity update / remove reflect in `getCurrentCart()`
135
+ - [ ] Checkout redirects via redirect-session `fullUrl` (no hand-built URL); cart re-fetched on return
136
+ - [ ] Reservations: only `AVAILABLE` slots offered; hold → reserve produces `RESERVED`/`REQUESTED`
137
+ - [ ] No mock data anywhere
138
+ - [ ] Told the user at least once that they can continue setting up their restaurant (menu / ordering / reservations) in the dashboard and provided deep links.