@wix/agent-skills 1.16.3 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +115 -12
  3. package/skills/wix-app/references/APP_MARKET_REVIEW.md +1 -1
  4. package/skills/wix-app/references/BACKEND_API.md +18 -0
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +6 -0
  6. package/skills/wix-app/references/DASHBOARD_MODAL.md +10 -2
  7. package/skills/wix-app/references/DASHBOARD_PAGE.md +32 -70
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +145 -127
  9. package/skills/wix-app/references/SITE_PLUGIN.md +14 -2
  10. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +74 -68
  11. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
  12. package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +79 -0
  13. package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +73 -0
  14. package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +52 -0
  15. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +184 -0
  16. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
  17. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +94 -49
  18. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +16 -6
  19. package/skills/wix-app/references/editor-react-component/BROWSER-SUPPORT.md +56 -0
  20. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
  21. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +35 -40
  22. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +167 -445
  23. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +56 -29
  24. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
  25. package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
  26. package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
  27. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +11 -3
  28. package/skills/wix-app/references/editor-react-component/PARTS.md +46 -24
  29. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
  30. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
  31. package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
  32. package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
  33. package/skills/wix-base44-connector/SKILL.md +156 -50
  34. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +78 -0
  35. package/skills/wix-base44-connector/scripts/utils.js +239 -45
  36. package/skills/wix-headless/entry/bootstrap.mjs +9 -2
  37. package/skills/wix-headless/entry/skill.md +1 -1
  38. package/skills/wix-headless/references/CAPABILITIES.md +9 -1
  39. package/skills/wix-headless/references/DESIGN.md +1 -0
  40. package/skills/wix-headless/references/DISCOVERY.md +2 -1
  41. package/skills/wix-headless/references/IMAGE_GENERATION.md +1 -0
  42. package/skills/wix-headless/references/SDK_HANDOFF.md +5 -2
  43. package/skills/wix-headless/references/SEED.md +2 -1
  44. package/skills/wix-headless/references/SETUP.md +1 -0
  45. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +2 -2
  46. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +68 -31
  47. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +26 -10
  48. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +8 -8
  49. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +1 -1
  50. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +1 -1
  51. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
  52. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +254 -0
  53. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
  54. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +13 -0
  55. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +254 -0
  56. package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
  57. package/skills/wix-headless/references/non-astro.md +1 -1
  58. package/skills/wix-headless-fast/SKILL.md +166 -0
  59. package/skills/wix-headless-fast/entry/skill.md +99 -0
  60. package/skills/wix-headless-fast/install/deploy.mjs +433 -0
  61. package/skills/wix-headless-fast/install/fast-path.mjs +141 -0
  62. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +137 -0
  63. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +137 -0
  64. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +113 -0
  65. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +42 -0
  66. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +123 -0
  67. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +70 -0
  68. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +99 -0
  69. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +76 -0
  70. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +62 -0
  71. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +40 -0
  72. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +99 -0
  73. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +24 -0
  74. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +16156 -0
  75. package/skills/wix-headless-fast/references/blog/seed/SEED.md +72 -0
  76. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +287 -0
  77. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +129 -0
  78. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +143 -0
  79. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +119 -0
  80. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +138 -0
  81. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +54 -0
  82. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +206 -0
  83. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +96 -0
  84. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +70 -0
  85. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +40 -0
  86. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +76 -0
  87. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +22 -0
  88. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +11962 -0
  89. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +61 -0
  90. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +302 -0
  91. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +179 -0
  92. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +83 -0
  93. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +57 -0
  94. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +151 -0
  95. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +75 -0
  96. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +41 -0
  97. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +11262 -0
  98. package/skills/wix-headless-fast/references/cms/seed/SEED.md +103 -0
  99. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +324 -0
  100. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +149 -0
  101. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +66 -0
  102. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +176 -0
  103. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +118 -0
  104. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +117 -0
  105. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +59 -0
  106. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +136 -0
  107. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +128 -0
  108. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +61 -0
  109. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +40 -0
  110. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +12 -0
  111. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +80 -0
  112. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +21 -0
  113. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +11884 -0
  114. package/skills/wix-headless-fast/references/events/seed/SEED.md +86 -0
  115. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +276 -0
  116. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +150 -0
  117. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +317 -0
  118. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +269 -0
  119. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +231 -0
  120. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +135 -0
  121. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +10593 -0
  122. package/skills/wix-headless-fast/references/forms/seed/SEED.md +108 -0
  123. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +320 -0
  124. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +63 -0
  125. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +60 -0
  126. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +155 -0
  127. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +78 -0
  128. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +47 -0
  129. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +66 -0
  130. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +88 -0
  131. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +53 -0
  132. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +122 -0
  133. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +50 -0
  134. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +21 -0
  135. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +42 -0
  136. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +10 -0
  137. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +11 -0
  138. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +10329 -0
  139. package/skills/wix-headless-fast/references/members/seed/SEED.md +39 -0
  140. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +94 -0
  141. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +134 -0
  142. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
  143. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
  144. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +115 -0
  145. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +59 -0
  146. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +39 -0
  147. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +58 -0
  148. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +165 -0
  149. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +55 -0
  150. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
  151. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
  152. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +21 -0
  153. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +29 -0
  154. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +10197 -0
  155. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +78 -0
  156. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +258 -0
  157. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +133 -0
  158. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +58 -0
  159. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +126 -0
  160. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +37 -0
  161. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +39 -0
  162. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +75 -0
  163. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +45 -0
  164. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +30 -0
  165. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
  166. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +40 -0
  167. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +21 -0
  168. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +11226 -0
  169. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +71 -0
  170. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +279 -0
  171. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +165 -0
  172. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +142 -0
  173. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
  174. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
  175. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +155 -0
  176. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +55 -0
  177. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +43 -0
  178. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +177 -0
  179. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +165 -0
  180. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +103 -0
  181. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +254 -0
  182. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +146 -0
  183. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +168 -0
  184. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
  185. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +22 -0
  186. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +12 -0
  187. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +12560 -0
  188. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +81 -0
  189. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +479 -0
  190. package/skills/wix-headless-fast/references/shared/CONTENT.md +22 -0
  191. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +73 -0
  192. package/skills/wix-headless-fast/references/shared/DESIGN.md +26 -0
  193. package/skills/wix-headless-fast/references/shared/app/styles/global.css +52 -0
  194. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +15 -0
  195. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +27 -0
  196. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +24 -0
  197. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +76 -0
  198. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
  199. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +46 -0
  200. package/skills/wix-headless-fast/references/shared/seed/images.mjs +145 -0
  201. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +149 -0
  202. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +26 -0
  203. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +121 -0
  204. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +100 -0
  205. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +130 -0
  206. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +48 -0
  207. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +66 -0
  208. package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +103 -0
  209. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +48 -0
  210. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +140 -0
  211. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +80 -0
  212. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +101 -0
  213. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +221 -0
  214. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +215 -0
  215. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +109 -0
  216. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +46 -0
  217. package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +56 -0
  218. package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +23 -0
  219. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +12247 -0
  220. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +85 -0
  221. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +415 -0
  222. package/skills/wix-manage/SKILL.md +28 -2
  223. package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
  224. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
  225. package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
  226. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +141 -0
  227. package/skills/wix-manage/references/google-business-profile/connect-google-business-profile.md +134 -0
  228. package/skills/wix-manage/references/google-business-profile/manage-google-business-profile-locations.md +182 -0
  229. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +3 -0
  230. package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
  231. package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
  232. package/skills/wix-manage/references/sites/query-sites.md +72 -161
  233. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +21 -6
  234. package/skills/wix-manage/references/stores/update-product-with-options.md +83 -0
  235. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
  236. package/skills/wix-vibe-headless/SKILL.md +18 -4
  237. package/skills/wix-vibe-headless/install/deploy.cjs +12 -4
  238. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +2 -1
  239. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +16 -10
  240. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +13 -8
  241. package/skills/wix-vibe-headless/platforms/base44.md +27 -62
  242. package/skills/wix-vibe-headless/platforms/generic.md +6 -3
  243. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +45 -0
  244. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +67 -0
  245. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +128 -0
  246. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +5 -3
  247. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
  248. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +250 -0
  249. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +12 -5
  250. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +41 -0
  251. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.js +267 -0
  252. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +6 -3
  253. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +470 -0
  254. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +425 -0
  255. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +187 -0
  256. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +238 -0
  257. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +108 -0
  258. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1762 -0
  259. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +13 -0
  260. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
  261. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
  262. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
  263. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
  264. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +152 -92
  265. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
  266. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
  267. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +15 -8
  268. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +37 -0
  269. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
  270. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +18 -6
  271. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +30 -7
  272. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +46 -10
  273. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
  274. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
  275. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -516
  276. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
  277. package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
  278. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
  279. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +0 -110
  280. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +0 -51
  281. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +0 -49
  282. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +0 -92
  283. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +0 -139
@@ -1,7 +1,6 @@
1
- // Wix docs helpers for the Base44 sandbox — the scratch-lane set. Small results return
2
- // inline; anything over ~4,000 chars (exec results clip at ~5,000) is saved under the
3
- // scratch dir and comes back as { path, bytes, lines, outline } with the read tools
4
- // pre-pointed at it.
1
+ // Wix docs helpers for the Base44 sandbox. Small results return inline; anything over
2
+ // ~4,000 chars (exec results clip at ~5,000) is saved under .agents/skills/wix-base44-connector/tmp and comes
3
+ // back as { path, bytes, lines, outline } with the read tools pre-pointed at it.
5
4
  //
6
5
  // Load per exec (execs share no state) — from disk, network only as first-touch fallback:
7
6
  // const fs = require("fs"), P = ".agents/skills/wix-base44-connector/utils.js";
@@ -14,14 +13,13 @@
14
13
  // to find, read_file(<path>) with offset/limit to window (numbered lines, 45K cap — no exec
15
14
  // round needed), pipelines for the rest (GNU grep/sed; awk is mawk; no rg).
16
15
  //
17
- // API responses are site data and stay OUT of scratch (scratch ships with the app):
18
- // post() never saves — project responses to facts.
16
+ // API responses are site data and never saved — post() projects them to facts.
19
17
 
20
18
  const fs = require("fs");
21
19
  const path = require("path");
22
20
 
23
21
  const BUDGET = 4000;
24
- const SCRATCH = ".agents/skills/wix-base44-connector/scratch";
22
+ const SCRATCH = ".agents/skills/wix-base44-connector/tmp";
25
23
 
26
24
  const clip = (out) => {
27
25
  if (typeof out === "string")
@@ -33,10 +31,12 @@ const clip = (out) => {
33
31
  return s.length <= BUDGET ? JSON.parse(s) : { truncated: true, total: s.length, head: s.slice(0, BUDGET) };
34
32
  };
35
33
 
36
- // One transport for every JSON call — Content-Type, optional Bearer, ok-guard.
37
- // Admin calls are this with the connector token: post(publicUrl, body, accessToken).
38
- async function post(url, body, token) {
39
- const r = await fetch(url, { method: "POST", body: JSON.stringify(body),
34
+ // One transport for every JSON call — Content-Type, optional Bearer, ok-guard. One per verb, so a
35
+ // PATCH/GET/PUT/DELETE endpoint is a helper call, never a hand-rolled fetch. Admin calls are these
36
+ // with the connector token: patch(publicUrl, body, accessToken).
37
+ async function req(method, url, body, token) {
38
+ const r = await fetch(url, { method,
39
+ ...(body !== undefined && { body: JSON.stringify(body) }),
40
40
  headers: { "Content-Type": "application/json", ...(token && { Authorization: `Bearer ${token}` }) } });
41
41
  if (!r.ok) {
42
42
  const head = (await r.text()).slice(0, 300);
@@ -46,9 +46,14 @@ async function post(url, body, token) {
46
46
  }
47
47
  return r.json();
48
48
  }
49
+ const post = (url, body, token) => req("POST", url, body, token);
50
+ const get = (url, token) => req("GET", url, undefined, token);
51
+ const patch = (url, body, token) => req("PATCH", url, body, token);
52
+ const put = (url, body, token) => req("PUT", url, body, token);
53
+ const del = (url, token) => req("DELETE", url, undefined, token);
49
54
 
50
55
  function save(name, text) {
51
- const dir = path.join(process.cwd(), SCRATCH);
56
+ const dir = SCRATCH;
52
57
  fs.mkdirSync(dir, { recursive: true });
53
58
  fs.writeFileSync(path.join(dir, name), text);
54
59
  return { path: SCRATCH + "/" + name, bytes: Buffer.byteLength(text), lines: text.split("\n").length };
@@ -60,15 +65,18 @@ const outlineOf = (lines, cap = 30) => {
60
65
  return { outline: heads.slice(0, cap), outlineOmitted: Math.max(0, heads.length - cap) };
61
66
  };
62
67
 
63
- // A ref is a scratch path or the URL it came from — resolve to lines, fetching+saving
68
+ // A ref is a saved path or the URL it came from — resolve to lines, fetching+saving
64
69
  // URLs on first touch (the .md suffix is appended for extensionless docs URLs).
65
- const slugOf = (url) => url.replace(/\?.*$/, "").split("/").pop().replace(/\.md$/, "") + ".md";
70
+ // two path segments, not one: doc leaves repeat across products (every API has an
71
+ // introduction.md), and a one-segment name makes resolveRef's cache return the WRONG document
72
+ const slugOf = (url) => url.replace(/\?.*$/, "").replace(/\.md$/, "")
73
+ .split("/").filter(Boolean).slice(-2).join("-") + ".md";
66
74
  async function resolveRef(ref) {
67
75
  const isUrl = /^https?:/.test(ref);
68
76
  const name = isUrl ? slugOf(ref) : ref.split("/").pop();
69
- const file = path.join(process.cwd(), SCRATCH, name);
77
+ const file = path.join(SCRATCH, name);
70
78
  if (fs.existsSync(file)) return { path: SCRATCH + "/" + name, lines: fs.readFileSync(file, "utf8").split("\n") };
71
- if (!isUrl) throw new Error("no such scratch file: " + ref + " — pass a returned path or the source URL");
79
+ if (!isUrl) throw new Error("no such saved file: " + ref + " — pass a returned path or the source URL");
72
80
  const mdUrl = /\.[a-z]{2,5}$/.test(ref.replace(/\?.*$/, "")) ? ref : ref.replace(/\?.*$/, "") + ".md";
73
81
  const res = await fetch(mdUrl);
74
82
  if (!res.ok) throw new Error(res.status + " on " + mdUrl + " — not a docs page; take URLs from output, don't compose");
@@ -94,6 +102,40 @@ async function context(token, section) {
94
102
  return clip({ total: markdown.length, section: m ? m[0] : "not found — call context(token) for the outline" });
95
103
  }
96
104
 
105
+ // The wix-manage skill, when it is installed in the sandbox, is these same recipes on disk —
106
+ // a read_file instead of a fetch. Indexed by frontmatter name AND filename slug, because the
107
+ // docs title drifts from the local one ("…Connect a domain" vs "…Connect").
108
+ const RECIPE_ROOT = ".agents/skills/wix-manage/references";
109
+ const rkey = (s) => String(s || "").toLowerCase().replace(/[^a-z0-9]/g, "");
110
+ let LOCAL_RECIPES;
111
+ function localRecipes() {
112
+ if (LOCAL_RECIPES) return LOCAL_RECIPES;
113
+ LOCAL_RECIPES = new Map();
114
+ if (!fs.existsSync(RECIPE_ROOT)) return LOCAL_RECIPES;
115
+ const walk = (rel) => {
116
+ for (const e of fs.readdirSync(RECIPE_ROOT + rel, { withFileTypes: true })) {
117
+ if (e.isDirectory()) { walk(rel + "/" + e.name); continue; }
118
+ if (!e.name.endsWith(".md")) continue;
119
+ const file = RECIPE_ROOT + rel + "/" + e.name;
120
+ const name = (fs.readFileSync(file, "utf8").slice(0, 600).match(/^name:\s*"?(.+?)"?\s*$/m) || [])[1];
121
+ if (name) LOCAL_RECIPES.set(rkey(name), file);
122
+ LOCAL_RECIPES.set(rkey(e.name.replace(/\.md$/, "")), file);
123
+ }
124
+ };
125
+ walk("");
126
+ return LOCAL_RECIPES;
127
+ }
128
+ // title, else the docsUrl slug, else either one as a prefix of the other
129
+ function recipeFile(title, docsUrl) {
130
+ const idx = localRecipes();
131
+ if (!idx.size) return undefined;
132
+ const slug = (docsUrl || "").replace(/\/+$/, "").split("/").pop();
133
+ for (const k of [rkey(title), rkey(slug)]) if (k && idx.has(k)) return idx.get(k);
134
+ const t = rkey(title);
135
+ if (t.length >= 12) for (const [k, v] of idx) if (k.startsWith(t) || t.startsWith(k)) return v;
136
+ return undefined;
137
+ }
138
+
97
139
  // ── find what to read ─────────────────────────────────────────────────────────
98
140
 
99
141
  // Browse the docs tree — deterministic. menuUrl alone orients (children + counts);
@@ -108,35 +150,106 @@ async function browse(menuUrl, { include, filter, depth } = {}) {
108
150
  return { ...s, next: `wx.bash("grep -in 'term' ${s.path} | head -40") // one line per node — or re-browse with a filter` };
109
151
  }
110
152
 
111
- // Semantic search — ranks, never says "no match". The reduced hits come back inline
112
- // AND the full raw content is saved for grep/window follow-ups.
113
- async function search(term, { type = "REST", max = 5, lines = 6 } = {}) {
114
- const { content } = await post("https://www.wixapis.com/mcp-docs-search/v1/docs/search/markdown",
115
- { search_term: term, document_type: type, maximum_results: max, lines_in_each_result: lines });
116
- const hits = content.split(/\n---\n+(?=#### )/).map(b => ({
117
- method: (b.match(/^# Method: (.+)$/m) || [])[1],
118
- endpoint: (b.match(/^# Method API Endpoint: (.+)$/m) || [])[1], // callable
119
- docsUrl: (b.match(/#### \[[^\]]+\]\((https:[^)]+)\)/) || [])[1],
153
+ // Semantic search — ranks, never says "no match". The reduced hits come back inline AND the full
154
+ // raw content is saved for grep/window follow-ups. { type } picks the corpus, one per request:
155
+ // REST (default) · SKILLS · WIX_HEADLESS · SDK · VELO · CLI · WDS · BUILD_APPS · OVERVIEW ·
156
+ // BUSINESS_SOLUTIONS. A REST search also runs SKILLS — the management recipes rank as their own
157
+ // hits, ahead of the methods, and land in the saved file whole. Each method hit lists the worked
158
+ // requests the docs publish for it; every line number reads with read_file(path, offset: <line>).
159
+ async function search(term, { type = "REST", max = 5, lines = 0, recipes = type === "REST" } = {}) {
160
+ const ask = (document_type, maximum_results) =>
161
+ post("https://www.wixapis.com/mcp-docs-search/v1/docs/search/markdown",
162
+ // lines_in_each_result 0 skips the server's per-section budget, which otherwise cuts every
163
+ // code example after the first 30 lines and the rest after 5, and every recipe at 20 —
164
+ // the saved file would carry stubs instead of the requests and flows the hits point at
165
+ { search_term: term, document_type, maximum_results, lines_in_each_result: lines });
166
+ const [main, skills] = await Promise.all([ask(type, max),
167
+ recipes ? ask("SKILLS", 3).catch(() => null) : null]); // a recipe corpus miss must not fail the search
168
+ const recipeText = skills?.content ? skills.content.trimEnd() + "\n" : "";
169
+ const content = recipeText + main.content;
170
+ const nl = []; // newline offsets — a match's char offset becomes its line in the saved file
171
+ for (let i = content.indexOf("\n"); i >= 0; i = content.indexOf("\n", i + 1)) nl.push(i);
172
+ const lineAt = (off) => { let lo = 0, hi = nl.length; while (lo < hi) { const m = (lo + hi) >> 1; nl[m] < off ? lo = m + 1 : hi = m; } return lo + 1; };
173
+ // recipes are articles — no "# Method:" header, no code-example delimiters, and no fixed body
174
+ // shape. Two things every one of them has: headings, and the endpoints it calls. Those are the
175
+ // outline — enough to tell whether this is the recipe for the task without reading 400 lines.
176
+ const recipeHits = !recipeText ? [] : recipeText.split(/\n---\n+(?=#### )/).map(b => {
177
+ const at = content.indexOf(b), rows = b.split("\n");
178
+ const steps = [], calls = [];
179
+ let verb = null;
180
+ for (const t of rows) {
181
+ if (/^#{1,4} /.test(t) && !/^#### \[|^## (Resource|Article|Article Link|Article Content):/.test(t))
182
+ steps.push(t.replace(/^#+ /, "").trim().slice(0, 52));
183
+ const c = t.match(/curl\s+-X\s+(GET|POST|PATCH|PUT|DELETE)/i);
184
+ const u = t.match(/https:\/\/www\.wixapis\.com\/[^\s"'`)\\]+/);
185
+ if (c && !u) { verb = c[1].toUpperCase(); continue; } // curl -X VERB, url on the next line
186
+ if (!u) continue;
187
+ const v = (c && c[1].toUpperCase()) || (t.match(/\b(GET|POST|PATCH|PUT|DELETE)\b/) || [])[1] || verb || "";
188
+ verb = null;
189
+ const call = (v + " " + u[0].replace(/\{[^}]*\}|<[^>]*>/g, "{id}")).trim();
190
+ if (!calls.includes(call)) calls.push(call);
191
+ }
192
+ const title = (b.match(/^## Resource: (.+)$/m) || [])[1];
193
+ const docsUrl = (b.match(/#### \[[^\]]+\]\((https:[^)]+)\)/) || [])[1];
194
+ return { recipe: title, docsUrl,
195
+ ...(recipeFile(title, docsUrl) && { file: recipeFile(title, docsUrl) }),
196
+ line: at < 0 ? 1 : lineAt(at), lines: rows.length,
197
+ ...(steps.length && { steps: steps.slice(0, 6) }),
198
+ ...(calls.length && { calls: calls.slice(0, 4) }) };
199
+ }).filter(h => h.docsUrl && h.recipe);
200
+ let cursor = recipeText.length;
201
+ const hits = main.content.split(/\n---\n+(?=#### )/).map(b => {
202
+ const start = content.indexOf(b, cursor); cursor = start + b.length;
203
+ const examples = [...b.matchAll(/--- Code Example: (.+?) ---/g)]
204
+ .map(m => ({ title: m[1].trim(), line: lineAt(start + m.index) }));
205
+ const docsUrl = (b.match(/#### \[[^\]]+\]\((https:[^)]+)\)/) || [])[1];
206
+ const method = (b.match(/^# Method: (.+)$/m) || [])[1];
207
+ // the REST corpus mixes guides in with the methods — an article has no method header, so
208
+ // name it from its own title rather than returning a row of nulls
209
+ if (!method) return { article: (b.match(/^## (?:Resource|Article): (.+)$/m) || [])[1], docsUrl,
210
+ line: start < 0 ? 1 : lineAt(start) };
211
+ return {
212
+ method,
213
+ endpoint: (b.match(/^# Method API Endpoint: (.+)$/m) || [])[1], // "VERB url" — read the verb + url; call wx.<verb>(url, body, token)
214
+ docsUrl,
120
215
  gist: ((b.match(/## Method Description:\s*\n([\s\S]{0,400})/) || [])[1] || "")
121
216
  .trim().replace(/\s+/g, " ").slice(0, 220),
122
- })).filter(h => h.docsUrl);
217
+ ...(examples.length && { examples }),
218
+ }; }).filter(h => h.docsUrl);
123
219
  const saved = save("search-" + term.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 40) + ".md", content);
124
- if (!hits.length) return clip({ ...saved, head: content.slice(0, 1200),
220
+ if (!hits.length && !recipeHits.length) return clip({ ...saved, head: content.slice(0, 1200),
125
221
  note: `no method blocks parsed — raw head above; wx.bash("grep -in 'term' ${saved.path}") for the rest` });
126
- return clip({ ...saved, hits });
222
+ // one URL, one row: a long article is indexed in chunks that rank separately, and a stray skills
223
+ // page sits in the REST corpus, so the same page can rank two or three times
224
+ const seen = new Set();
225
+ const recipeRows = recipeHits.filter(r => !seen.has(r.docsUrl) && seen.add(r.docsUrl));
226
+ const uniq = hits.filter(h => !seen.has(h.docsUrl) && seen.add(h.docsUrl));
227
+ const out = { ...saved, ...(recipeRows.length && { recipes: recipeRows }), hits: uniq };
228
+ // over budget, shed enrichment rather than structure — clip would drop the whole shape, and
229
+ // every title, URL and line number stays useful with the outlines gone
230
+ for (const shed of [() => recipeRows.forEach(r => delete r.calls),
231
+ () => recipeRows.forEach(r => delete r.steps),
232
+ () => uniq.forEach(h => { if (h.examples) h.examples = h.examples.slice(0, 3); }),
233
+ () => uniq.forEach(h => delete h.examples)]) {
234
+ if (JSON.stringify(out).length <= BUDGET) break;
235
+ shed();
236
+ }
237
+ return clip(out);
127
238
  }
128
239
 
129
240
  // ── read a page (docs pages and recipes alike) ────────────────────────────────
130
241
 
131
242
  // Fetch + save + map in one round: whole text inline when small, else
132
243
  // { path, bytes, lines, outline } — the outline's line numbers feed grep and read_file windows.
244
+ // Examples come back as their own title+line list, so the outline's cap can never drop them.
133
245
  async function page(url) {
134
246
  const { path: p, lines } = await resolveRef(url);
135
247
  const text = lines.join("\n");
136
248
  if (text.length <= BUDGET) return text;
137
249
  const o = outlineOf(lines);
138
250
  const bytes = Buffer.byteLength(text);
139
- return { path: p, bytes, lines: lines.length, ...o,
251
+ const ex = pageExamples(lines);
252
+ return { path: p, bytes, lines: lines.length, ...(ex.length && { examples: ex }), ...o,
140
253
  next: [
141
254
  `wx.bash("grep -in 'term' ${p} | head -40")`,
142
255
  bytes <= 45000 ? `read_file ${p} // whole (fits the 45K cap), or a window via offset/limit`
@@ -144,9 +257,21 @@ async function page(url) {
144
257
  ] };
145
258
  }
146
259
 
260
+ // The page's Examples section, as titles + line numbers — listed on their own so the
261
+ // outline's cap can never drop them.
262
+ function pageExamples(lines) {
263
+ const heads = [];
264
+ lines.forEach((t, i) => { const m = /^(#{1,6}) (.+)$/.exec(t); if (m) heads.push({ line: i + 1, level: m[1].length, text: m[2].trim() }); });
265
+ const at = heads.findIndex(h => /^(examples?|method code examples)$/i.test(h.text));
266
+ if (at < 0) return [];
267
+ const sec = heads[at], rest = heads.slice(at + 1);
268
+ const end = (rest.find(h => h.level < sec.level) || { line: lines.length + 1 }).line;
269
+ return rest.filter(h => h.line < end).map(h => ({ title: h.text, line: h.line }));
270
+ }
271
+
147
272
  // ── shell ─────────────────────────────────────────────────────────────────────
148
273
 
149
- // Compose native pipelines over scratch — grep -n, sed -n, mawk, sort, uniq, wc
274
+ // Compose native pipelines over .agents/skills/wix-base44-connector/tmp — grep -n, sed -n, mawk, sort, uniq, wc
150
275
  // (GNU grep/sed; awk is mawk; no rg). Cap your own output (| head -40); the return
151
276
  // clips regardless. grep's exit 1 means no match, not failure — the return says so.
152
277
  function bash(cmd) {
@@ -163,35 +288,96 @@ function bash(cmd) {
163
288
  }
164
289
  }
165
290
 
291
+ // ── request examples ──────────────────────────────────────────────────────────
292
+
293
+ // The docs' own working requests: the code-mode index carries them at
294
+ // methods[].legacyExamples[].content, a doc page under its Examples heading. Both are saved
295
+ // whole and come back as titles + line numbers — read the one you need with read_file.
296
+ const examplesOf = (result) => {
297
+ const methods = result?.methods?.length ? result.methods : (result?.legacyExamples ? [result] : []);
298
+ const out = [];
299
+ for (const m of methods) for (const e of m.legacyExamples || []) {
300
+ const c = e.content || e;
301
+ if (c.request) out.push({ title: c.title || "", request: typeof c.request === "string" ? c.request : JSON.stringify(c.request, null, 1) });
302
+ }
303
+ return out;
304
+ };
305
+
306
+ // One file, one heading per example — the returned line is where its body starts.
307
+ const saveExamples = (exs, name) => {
308
+ const parts = [];
309
+ let line = 1, index = [];
310
+ for (const e of exs) {
311
+ const block = "## " + e.title + "\n\n" + e.request + "\n";
312
+ index.push({ title: e.title, line: line + 2 });
313
+ parts.push(block);
314
+ line += block.split("\n").length;
315
+ }
316
+ return { ...save("examples-" + name + ".md", parts.join("\n")), index };
317
+ };
318
+
166
319
  // ── the spec index ────────────────────────────────────────────────────────────
167
320
 
168
- // Run a query over the API spec index. In scope: lightIndex (RESOURCES with
169
- // .methods — operationId, summary, httpMethod, path [PARTIAL — never call it],
170
- // publicUrl [callable], docsUrl) and getResourceSchemaByUrl(docsUrl). Arrive with
171
- // a docsUrl and match by it — also the only proof an API does NOT exist.
172
- // A big result is saved as JSON; grep it for the keys you saw in its head.
173
- async function spec(code) {
174
- if (!/^\s*async function/.test(code)) code = `async function(){ ${code} }`;
321
+ // Inspect a method's schema — request body, responses, enums, filterable-fields map — plus the
322
+ // titles of the docs' own request examples, saved together at examplesPath: read the one that
323
+ // matches your task with read_file(examplesPath, offset: <its line>). Pass a docsUrl
324
+ // (from search/browse — a direct load, no scan) and spec returns that method's schema. Or pass raw
325
+ // `async function(){…}` to query the index yourself: lightIndex (RESOURCES with .methods —
326
+ // operationId, summary, httpMethod, publicUrl [callable], docsUrl) and getResourceSchemaByUrl(docsUrl)
327
+ // → s.methods (each with requestBody, responses, legacyExamples,
328
+ // queryMethodData.queryFieldsCapabilitiesMap; $circular via s.components.schemas). A big result is
329
+ // saved as JSON; grep it for the keys you saw in its head.
330
+ async function spec(arg) {
331
+ const s = String(arg).trim();
332
+ const code = /^async function/.test(s) ? s
333
+ : /^https:\/\/dev\.wix\.com\/docs\//.test(s) ? "async function(){ return await getResourceSchemaByUrl(" + JSON.stringify(s) + "); }"
334
+ : "async function(){ " + s + " }";
175
335
  const { result } = await post("https://mcp.wix.com/api/code-mode/search", { code });
176
336
  if (result == null || (Array.isArray(result) && !result.length))
177
- return { result, note: "empty — the query missed the shape, not proof of absence; find the resource by docsUrl on lightIndex" };
337
+ return { result, note: "empty — the query missed the shape; match your docsUrl against s.methods[].docsUrl" };
178
338
  const text = JSON.stringify(result, null, 1);
179
339
  if (text.length <= BUDGET) return result;
180
- return { ...save("spec.json", text),
340
+ let h = 5381;
341
+ for (const ch of code) h = ((h * 33) ^ ch.charCodeAt(0)) >>> 0; // same query → same file
342
+ const exs = examplesOf(result);
343
+ const ex = exs.length ? saveExamples(exs, h.toString(36)) : null;
344
+ return { ...save("spec-" + h.toString(36) + ".json", text),
181
345
  shape: Array.isArray(result) ? `Array(${result.length})` : Object.keys(result || {}).slice(0, 15),
346
+ ...(ex && { examplesPath: ex.path, examples: ex.index }),
182
347
  head: text.slice(0, 600) };
183
348
  }
184
349
 
185
350
  // ── management recipes ────────────────────────────────────────────────────────
186
351
 
187
- // ~100 curated multi-step admin flows. No arg → categories with counts; a category
188
- // name → its recipes; any other term → search every recipe's name + gist for it.
352
+ // ~100 curated multi-step MANAGEMENT (admin) flows across 23 categories — ecommerce,
353
+ // bookings, stores, cms, contacts, sites, get-paid, marketing, pricing-plans, events,
354
+ // blog, forms, restaurants, domains, media, … No arg → categories with counts; a
355
+ // category name → its recipes; any other term → search every recipe's name + gist.
189
356
  // Read the chosen url with page(url), then grep/window/fields.
190
- async function recipes(q) {
191
- const { base, files } = await (await fetch("https://dev.wix.com/docs/skills/manage.manifest.json")).json();
357
+ async function mgmtRecipes(q) {
358
+ // the recipes ARE the wix-manage skill's references — when that skill is installed, both the
359
+ // listing and the files come straight off disk; the manifest fetch is only the not-installed path
360
+ const ROOT = ".agents/skills/wix-manage/references";
361
+ let files;
362
+ if (fs.existsSync(ROOT)) {
363
+ files = [];
364
+ const walk = rel => {
365
+ for (const e of fs.readdirSync(ROOT + rel, { withFileTypes: true })) {
366
+ if (e.isDirectory()) { walk(rel + "/" + e.name); continue; }
367
+ const file = ROOT + rel + "/" + e.name, head = fs.readFileSync(file, "utf8").slice(0, 1000);
368
+ files.push({ path: "references" + rel + "/" + e.name, file, size: fs.statSync(file).size,
369
+ name: (head.match(/^name:\s*"?(.+?)"?\s*$/m) || [])[1] || e.name,
370
+ description: (head.match(/^description:\s*"?(.+?)"?\s*$/m) || [])[1] || "" });
371
+ }
372
+ };
373
+ walk("");
374
+ } else {
375
+ const { base, files: manifest } = await (await fetch("https://dev.wix.com/docs/skills/manage.manifest.json")).json();
376
+ files = manifest.map(f => ({ ...f, url: base + f.path }));
377
+ }
192
378
  const cat = f => (f.path.match(/^references\/([^/]+)\//) || [])[1];
193
379
  const row = f => ({ name: f.name, cat: cat(f), gist: (f.description || "").slice(0, 120),
194
- url: base + f.path, kb: Math.round(f.size / 1024) });
380
+ ...(f.file ? { file: f.file } : { url: f.url }), kb: Math.round(f.size / 1024) });
195
381
  if (!q) {
196
382
  const cats = {};
197
383
  for (const f of files) { const c = cat(f); if (c) cats[c] = (cats[c] || 0) + 1; }
@@ -209,4 +395,12 @@ async function recipes(q) {
209
395
  return clip(m.map(row));
210
396
  }
211
397
 
212
- module.exports = { post, clip, context, browse, search, page, bash, spec, recipes };
398
+ // Install a Wix app on the site (Apps Installer). Use when discovery finds an API but its app is
399
+ // not installed yet — that is a one-call prerequisite, not a dead end. appDefId from search or the
400
+ // Apps-Created-by-Wix table; siteId from context (the site report).
401
+ async function installApp(appDefId, siteId, token) {
402
+ return post("https://www.wixapis.com/apps-installer-service/v1/app-instance/install",
403
+ { tenant: { tenantType: "SITE", id: siteId }, appInstance: { appDefId } }, token);
404
+ }
405
+
406
+ module.exports = { req, post, get, patch, put, del, clip, context, browse, search, page, bash, spec, mgmtRecipes, installApp };
@@ -40,7 +40,14 @@ function checkCli() {
40
40
  emit('cli_ok', { version });
41
41
  }
42
42
 
43
- // ── 2. Login (human-in-the-loop device code; forward the CLI's own events) ───
43
+ // ── 2. Reuse an existing session, or start device login ──────────────────────
44
+ function hasExistingSession() {
45
+ const r = capture(WIX[0], [...WIX.slice(1), 'whoami']);
46
+ if (r.status !== 0) return false;
47
+ emit('logged_in');
48
+ return true;
49
+ }
50
+
44
51
  function login() {
45
52
  return new Promise((resolve) => {
46
53
  const child = spawn(WIX[0], [...WIX.slice(1), 'login'], { shell: isWin, env: AGENT_ENV });
@@ -90,4 +97,4 @@ function login() {
90
97
 
91
98
  // ── main ────────────────────────────────────────────────────────────────────
92
99
  checkCli();
93
- await login();
100
+ if (!hasExistingSession()) await login();
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wix-headless-entry
3
- description: "Build a complete Wix Managed Headless site from a single prompt, then connect Wix Business Solutions. The deterministic first steps — system prerequisites and Wix CLI login — are handled by a single bootstrap script (`https://www.wix.com/skills/headless/entry/bootstrap.mjs`); the agent then installs the skill and hands the run to it. Triggers: build me a site, create a website, make me a website, new website, online store, I want to sell X, start a business online, launch a site, ecommerce, portfolio, business website, sell online, online shop, connect this to Wix Headless, add Wix Headless to this project, host this on Wix, deploy this to Wix, implement the features of this project using Wix Headless. Use this skill instead of the WixSiteBuilder MCP tool for new-site requests."
3
+ description: "Build a complete Wix Managed Headless site from a single prompt, then connect Wix Business Solutions. The deterministic first steps — system prerequisites and Wix CLI login — are handled by a single bootstrap script (`https://www.wix.com/skills/headless/entry/bootstrap.mjs`); the agent then installs the skill and hands the run to it. Triggers: build me a site, create a website, make me a website, new website, online store, I want to sell X, start a business online, launch a site, ecommerce, portfolio, business website, sell online, online shop, rental site, rentals, connect this to Wix Headless, add Wix Headless to this project, host this on Wix, deploy this to Wix, implement the features of this project using Wix Headless. Use this skill instead of the WixSiteBuilder MCP tool for new-site requests."
4
4
  ---
5
5
 
6
6
  # Wix Headless Skill — cold-start entry
@@ -19,7 +19,7 @@ Each built vertical has three parts (the latter two scoped to `create`/backend-o
19
19
 
20
20
  ## Built verticals — installed, seeded, and described in the Handoff
21
21
 
22
- The verticals the skill operates end-to-end today: **stores · blog · cms · forms · events · bookings · pricing-plans · restaurants · portfolio** (with `forms` as the floor when nothing richer is named).
22
+ The verticals the skill operates end-to-end today: **stores · blog · cms · forms · events · bookings · rentals · pricing-plans · restaurants · portfolio** (with `forms` as the floor when nothing richer is named).
23
23
 
24
24
  ### stores — sell products
25
25
  - **Intent:** sell / shop / products / catalog / merch / store.
@@ -63,9 +63,17 @@ The verticals the skill operates end-to-end today: **stores · blog · cms · fo
63
63
  ### bookings — appointments and classes
64
64
  - **Intent:** book / appointment / schedule / class / session / reserve a slot — a **service or appointment with a provider** (a stylist, trainer, tutor, clinic, studio).
65
65
  - **Not bookings — route to `restaurants` instead:** a **table at a restaurant** is a Table Reservations concern, not a bookable service; and a **special dining occasion guests reserve** — a wine tasting, cheese pairing, chef's table, or tasting-menu evening at a restaurant — is a **restaurants → Table Reservations *experience*** (see the restaurants entry), **not** a bookings service. Reach for `bookings` only when what's booked is a standalone service/class with a provider, never a seat at a restaurant.
66
+ - **Not bookings — route to `rentals` instead:** when the **customer chooses how long** they want something, and what's booked is a **thing rather than a person** — a room by the hour, a desk for three days, a van for the weekend. The tell is a duration *range* the customer picks within. A 60-minute haircut is `bookings`; a meeting room booked for 1–8 hours is `rentals`.
66
67
  - **Required site features:** a list of services; a page per service; a way to pick a time and book it.
67
68
  - **Implementation checklist:** show each service's name, duration, and price; show the staff or provider; show the available time slots; a book action; a confirmation after booking.
68
69
 
70
+ ### rentals — rent a room, vehicle, or piece of equipment
71
+ - **Intent:** rent / rental / hire / lease / "by the hour" / "by the day" / hourly or daily rate / **customer picks how long** — plus the things people rent: meeting room, conference room, co-working desk, hot desk, studio, hall, venue, workspace, vehicle, van, car, boat, bike, equipment, gear, camera, tool. Reach for it whenever what's booked is a **resource** (a room, vehicle, or item) for a **length the customer selects within a range**, not a fixed session with a provider.
72
+ - **Not rentals — route to `bookings` instead:** a session whose length the **business** fixes, delivered by a **person** (a 60-minute massage, a class, a consultation). The word "rent" in a brief sometimes describes the *business model* ("we rent out desks") while the thing being sold is really a fixed session — decide on the **duration model**, not the vocabulary.
73
+ - **Required site features:** a list of rentable items; a page per item; a way to pick a start **and a length** (an end time or an end date) and book it. A rental is priced per hour or per day, so the site must show the **computed total for the chosen length** before the customer commits — a per-unit price alone is not enough.
74
+ - **Implementation checklist:** show each item's name, description, and **per-hour or per-day rate** (say which); show the item's attributes where they exist (capacity, amenities, equipment type); show available start times, then the valid lengths for the chosen start; show the running total for the selected length; a book action; a confirmation after booking.
75
+ - **One unit type per item** — an item is rented by the hour *or* by the day, never both. When a brief wants both for the same room, that's **two** rentals, each with its own rate.
76
+
69
77
  ### pricing-plans — memberships and subscriptions
70
78
  - **Intent:** membership / subscription / plans / paid tiers.
71
79
  - **Required site features:** a plans / pricing page; a way to choose and subscribe to a plan. **Subscribing requires a logged-in member** — the plans grid is public, but the *subscribe* action and any *my subscription* surface need the **members** cross-cutting capability (below); it's a hard dependency, not optional.
@@ -34,6 +34,7 @@ Hold these as the run's design tokens. Reuse them literally in the themed-block
34
34
  | forms | The form itself — clear single-column, one obvious submit |
35
35
  | events | Event list, event detail + RSVP |
36
36
  | bookings | Service list, booking widget/flow |
37
+ | rentals | Rentable-item grid, item detail (rate + attributes), date/length picker showing the running total |
37
38
  | pricing-plans | Plan comparison, checkout/signup |
38
39
  | restaurants | Menu, reservation/ordering flow |
39
40
  | portfolio | Project grid, case-study/project detail |
@@ -32,7 +32,7 @@ Discovery is pure inference — it needs **no authentication** and is **agnostic
32
32
 
33
33
  Read the **user intent** (+ optional project signals: `package.json` name, README, visible copy) against the vertical index in `references/CAPABILITIES.md` — each entry there carries the intent signals that point to it. Pick every vertical that genuinely fits → `verticals[]`. Multiple signals → multiple capabilities. On ambiguity, prefer the more specific vertical; if nothing dynamic is named, fall to the **forms** floor (a contact form). **Never return an empty set.**
34
34
 
35
- Resolve to the skill's operational set — **stores · blog · cms · forms · events · bookings · pricing-plans · restaurants · portfolio** (`CAPABILITIES.md` § "Built verticals"). If intent points squarely at a vertical outside that set, note it plainly as not-yet-wired (per the index) and resolve the rest; don't force an unrelated capability in its place.
35
+ Resolve to the skill's operational set — **stores · blog · cms · forms · events · bookings · rentals · pricing-plans · restaurants · portfolio** (`CAPABILITIES.md` § "Built verticals"). If intent points squarely at a vertical outside that set, note it plainly as not-yet-wired (per the index) and resolve the rest; don't force an unrelated capability in its place.
36
36
 
37
37
  ## 2 · Infer brand
38
38
 
@@ -50,6 +50,7 @@ For each capability, build its `intent.<cap>` block — the inputs the seed step
50
50
  | forms | `{ forms: [{ purpose, fields: [...] }] }` | one `contact` form: name, email, message |
51
51
  | events | `{ eventCount, titles: [] }` | `eventCount: 2`, titles brand-derived, future dates |
52
52
  | bookings | `{ serviceCount, servicesNamed: [] }` | `serviceCount: 2`, brand-derived service names |
53
+ | rentals | `{ unitType, serviceCount, resourceCount, servicesNamed: [] }` | `unitType: "HOUR"` (`"DAY"` if the brief rents by the day), `serviceCount: 2`, `resourceCount: 2`, brand-derived item names |
53
54
  | pricing-plans | `{ planCount, tiersNamed: [] }` | `planCount: 2` (e.g. Basic / Pro), monthly billing |
54
55
  | restaurants | `{ menuName, sections: [{ name, itemCount }], ordering?, reservations?, experiences?: [{ name }] }` | one menu, 2 sections, `itemCount: 3` each; add-ons only when the brief names them. **`experiences[]`** = special dining occasions guests reserve (wine/cheese pairing, chef's table) — a restaurant *reservation that is an experience*, **not** the `bookings` vertical (see `CAPABILITIES.md`). |
55
56
  | portfolio | `{ collections: [{ name }], projectCount }` | one brand-derived collection, `projectCount: 3` |
@@ -54,6 +54,7 @@ The pass-2 **write shape is per-entity earned knowledge and lives in each capabi
54
54
  | Blog post cover | `setup-blog.md` | **Attach images** |
55
55
  | CMS item | `setup-cms.md` | **Attach images** |
56
56
  | Bookings service | `setup-bookings.md` | **Attach images** |
57
+ | Rental service | `setup-rentals.md` | **Attach images** |
57
58
  | Portfolio project / collection | `setup-portfolio.md` | **Attach images** (cover + gallery) |
58
59
  | Restaurant menu item | `setup-restaurants.md` | **Attach images** |
59
60
  | Event hero (`mainImage`) | `setup-events.md` | **Attach images** |
@@ -32,7 +32,9 @@ For the current `createClient` + auth-strategy shape, link:
32
32
  ### 3 · Per-capability packages + API docs (package from the map; recipe for shapes)
33
33
  For each loaded capability, give the host the **package(s)** from the map below and point it at the capability's **inline recipe** (`references/inline-recipes/how-to-code-*.md`) — the pinned API shape, methods, version, and failure modes live there; don't re-summarize them here. The map is the source of truth for *which* packages; the recipe is the source of truth for *how* to call them. **The recipes are local — Read them with the file tool, don't curl.**
34
34
 
35
- | Capability | Package(s) | Recipe — the pinned frontend contract |
35
+ Before implementing a capability, Read the local recipe linked in its row.
36
+
37
+ | Capability | Package(s) | Required recipe |
36
38
  |---|---|---|
37
39
  | stores | `@wix/stores` (+ `@wix/ecom`, `@wix/redirects` for cart/checkout) | `how-to-code-a-store.md` — Catalog V3 read + cart/checkout. |
38
40
  | blog | `@wix/blog` (+ `@wix/ricos` to render `richContent`; **`@wix/comments` + `@wix/members`** when the blog has comments/members; `@wix/blog` `likes` when the site has members) | `how-to-code-a-blog.md` — Blog V3 read/render + member features (likes, comments). Supplement: <https://dev.wix.com/docs/sdk/business-solutions/blog.md>. |
@@ -40,6 +42,7 @@ For each loaded capability, give the host the **package(s)** from the map below
40
42
  | forms | `@wix/forms` | `how-to-code-forms.md` — schema-driven render (read the live form schema, visitor token/no elevate) + Form Submissions v4 write contract. |
41
43
  | events | `@wix/events` (+ `@wix/redirects` for the ticketed hosted-checkout redirect) | `how-to-code-events.md` — Events V3 read + the `TICKETING`-vs-`RSVP` branch. |
42
44
  | bookings | `@wix/bookings` (+ `@wix/auto_sdk_ecom_cart-v-2`, `@wix/redirects` for the cart/checkout that holds the seat; `@wix/forms` for the schema-driven booking form) | `how-to-code-bookings.md` — Services V2 read + `createBooking → ecom Cart V2 → checkout-or-place`. |
45
+ | rentals | **`@wix/bookings`** — the same package set as bookings (`@wix/auto_sdk_ecom_cart-v-2`, `@wix/redirects`, `@wix/forms`). **There is NO `@wix/rentals` package** and its absence is not a missing capability: Wix Rentals ships no APIs of its own and runs on the Bookings APIs with rentals-specific field values. Never report rentals as "not buildable headlessly". | `how-to-code-rentals.md` — a **delta** on `how-to-code-bookings.md`: filter the catalog by the rentals `appId` (`ff5d6eb1-65e4-4f9a-8b14-64d34c12cc2e`), two-call hourly availability (start slots → end options), the consecutive-day walk for daily, duration-based `previewPrice`, then the **unchanged** booking/cart/checkout sequence carrying the rentals `appId` on `catalogReference`. |
43
46
  | pricing-plans | `@wix/pricing-plans` (+ `@wix/members` — login is a hard dep; and for the Bookings-membership integration `@wix/bookings` + `@wix/ecom` (+ `@wix/redirects`)). **Use `@wix/pricing-plans`, NOT the Wix-site `@wix/site-pricing-plans` (`startOnlinePurchase` is site page-code, not headless).** | `how-to-code-pricing-plans.md` — Plans V3 grid + login-gated order/subscribe + book-with-membership. |
44
47
  | restaurants | `@wix/restaurants` (menu display — **no `@wix/ecom`** unless online ordering is in the run; reservations are a separate app) | `how-to-code-restaurants.md` — Menus V1 display-only read. |
45
48
  | restaurants — online ordering (add-on; only when the Orders app is in the run) | add `@wix/ecom` + `@wix/redirects` to the row above | `how-to-code-restaurant-orders.md` — ordering cart/checkout on top of the menu display. |
@@ -68,7 +71,7 @@ Everything else the host resolves live from the queries in §3. (Static platform
68
71
  - Frontend CMS access is **read**; visitor writes go through **Forms** submissions.
69
72
  - **Blog comments are member-gated — read public, write authenticated.** Querying/rendering comments is public, so list them server-side in SSR. **Submitting** needs a logged-in member, so don't gate the form behind an upfront login check (that branch is what burns deliberation): render the form always and resolve identity at submit — POST to a backend endpoint (`src/pages/api/*.ts`) that calls `createComment` with the request session; if the caller isn't a member, redirect to the built-in `/api/auth/login?returnUrl=…`. **Do not build the comment form as a client island** — the API-endpoint + session path is the documented shape and avoids the browser-auth detour. The comment API keys (post `referenceId`, Blog appDefId, author lookup via `post.memberId`) are in `how-to-code-a-blog.md`.
70
73
  - **Member auth is one mechanism split on the frontend axis (the §3 members note routes to the right recipe), and orthogonal to elevation.** Sign-up and log-in are the *same* flow (the Wix login page logs in **or** registers); log-out is its inverse. Two layers stay separate: **identity** (logged-in vs not — no app install) vs **profile** (name/photo/roles — needs the **Wix Members Area app** installed, `SETUP.md`). **pricing-plans is a hard dependency**: subscribing requires a logged-in member; for the other verticals, member login is a soft add-on for their "my …" surfaces only. **A member reading their own data (own orders/bookings/subscriptions, plan-gated content) uses the member token with NO `auth.elevate`** — elevation is the separate admin/permission axis (site-wide reads, server-side only), not something member features need.
71
- - **Gating is a LIVE signal, never a hardcoded id list.** Whenever content is gated (members-only articles, plan-eligible class booking, any "premium" surface), decide eligibility from a signal read **at request time** — a queryable flag carried on the content (a `members-only` blog category/tag or a boolean CMS field) and live coverage/eligibility (`checkout.membershipOptions.eligibleMemberships`, or the member's active-order `planId`s matched against **live** Benefit-Program coverage). **Never** gate on a frozen set of "premium" slugs/ids or a seed-time `plan→service` map: a gated post or a newly-covered service the owner adds later would silently read as public/ineligible. See `how-to-code-a-blog.md` (member features) and `how-to-code-pricing-plans.md` (coverage read).
74
+ - **Gating is a LIVE signal, never a hardcoded id list.** Whenever content is gated (members-only articles, plan-eligible class booking, any "premium" surface), decide eligibility from a signal read **at request time** — a queryable flag carried on the content (a `members-only` blog category/tag or a boolean CMS field) and live coverage/eligibility (Cart V2's `currentCartV2.calculateCurrentCart()` → `summary.paymentSummary.memberships`, or the member's active-order `planId`s matched against **live** Benefit-Program coverage). **Never** gate on a frozen set of "premium" slugs/ids or a seed-time `plan→service` map: a gated post or a newly-covered service the owner adds later would silently read as public/ineligible. See `how-to-code-a-blog.md` (member features) and `how-to-code-pricing-plans.md` (coverage read).
72
75
 
73
76
  ### 6 · What a complete site must include (per loaded capability)
74
77
  For each loaded capability, carry its **Required site features** and **Implementation checklist** from `references/CAPABILITIES.md` into the guide — in plain product language, lightly tailored to what was seeded. **This is the build spec, not optional polish:** the host should build every *required feature* and cover every *checklist* item. For example, a blog must show the **author** (name + photo), the publish date and reading time, the cover image, and the **full formatted content** (not flattened text) — a posts-list-plus-plain-text-body is incomplete. The host maps these onto its own components using the packages/docs in §3 and the seeded schema in §4.
@@ -37,6 +37,7 @@ Each entry states only the entities, where their count/content comes from, the p
37
37
  - **forms** — *Visitor-fillable forms.* Recipe: **`setup-forms.md`**. One form per `intent.forms.forms` entry; fields from the entry, `purpose` names the form. **Keep (→ handoff):** `formIds[]` + each form's field **`target`** keys — *structural* (the frontend binds each input's `name` = target to submit; targets are **immutable**, so they don't go stale when an owner relabels a field).
38
38
  - **events** — *A ticketed or RSVP occasion, or upcoming events.* Recipe: **`setup-events.md`**. Each event is **either `TICKETING`** (paid — it has ticket tiers) **or `RSVP`** (free — the registration form is built-in, so don't seed form fields) per intent. For an **RSVP occasion** (a wedding, party, gathering): one RSVP event with the occasion's real details (title, a **future** date/time, location). For a **ticketed** event: the event plus its ticket tiers (default a single `"General Admission"` tier if none named). For a **listing** site: `intent.events.eventCount` events with brand-appropriate titles and **future** start dates (a default location/timezone is fine). Text-only. **Keep:** nothing for the handoff — events and tiers are discovered **live** (`queryEvents`, `getEventBySlug`, `queryAvailableTickets`); track `eventIds`/`ticketDefinitionIds` only transiently.
39
39
  - **bookings** — *Bookable services.* Recipe: **`setup-bookings.md`**. `intent.bookings.serviceCount` services (name + short description fitting `brand`, a simple duration and price); keep the schedule minimal. **Keep:** `serviceIds[]` as **seed-time state** (pricing-plans' coverage step keys on them, below); nothing for the handoff — services are discovered **live** (`queryServices`).
40
+ - **rentals** — *Rentable resources.* Recipe: **`setup-rentals.md`**. A resource **type** per kind of thing rented (rooms, vans, cameras), then `intent.rentals.resourceCount` **resources** inside it (Room A / Room B — parallel capacity comes from more resources, not higher capacity), then `intent.rentals.serviceCount` **rental services**, each carrying the Wix Rentals `appId`, `serviceResources` naming its resource type, a `primaryResourceType`, and a `durationRange` (`HOUR` or `DAY`) with the min/max the request implies — defaulting to **60/480 minutes** hourly and **1/5 days** daily when the brief doesn't say — and a **per-unit** price. **No category** — unlike bookings, rental services don't use one; don't create or assign one. **Order is load-bearing: resource type → resources → services** — a service whose resource type holds no resources has permanently empty availability. Seed resources **24/7** (no working-hours schedule) unless the request names opening hours; that keeps a multi-day rental to a single booking. **Keep:** `resourceTypeIds[]` as seed-time state (services key on them); nothing for the handoff — rentals are discovered **live** (`queryServicesByFilters` filtered by the rentals `appId`).
40
41
  - **pricing-plans** — *Membership tiers.* Recipe: **`setup-pricing-plans.md`**. `intent.pricing-plans.planCount` recurring plans (name, price, a monthly billing cycle) fitting `brand`. **When bookings is also in this run and the intent is a membership that covers services** (a studio/gym/class pass), also **attach the covered bookings services to the plan** — seed the bookings services first, since coverage keys on their service ids (see the recipe). **Keep:** the bookings coverage only transiently, to wire it during seeding; nothing for the handoff — plans are discovered **live** (`queryPlans`) and plan→service coverage is read **live** at checkout, never from a frozen map (see `how-to-code-pricing-plans.md`).
41
42
  - **restaurants** — *A menu.* Recipe: **`setup-restaurants.md`** (add-ons have their own recipes, below). Create the `itemCount` items per section first (name, description, price fitting `brand`), then the `intent.restaurants.sections` referencing those item ids, then the menu referencing the section ids — **items → sections → menu** (build bottom-up: a section is created with its `itemIds`, a menu with its `sectionIds`, so each child must exist before its parent — see `setup-restaurants.md` STEP 1–3). Text-only. **Keep (seed-time only):** `menuId`, `sectionIds[]`, `itemIds[]` to build the tree; nothing goes to the handoff — the frontend reads menus **live** (`listMenus`/`listSections`/`listItems`). **Online ordering (add-on, on demand)** — only when the request calls for ordering (not just a displayed menu): install the Orders app (per `SETUP.md` §2) and follow **`setup-restaurant-orders.md`**; **seed the menu FIRST, then ordering, in the same unit** (ordering auto-provisions per menu either way — see the concurrency note above — but keeping them one unit gives the ordering verify a menu to confirm against). **Configure the business-location address (`setup-restaurant-orders.md` STEP 0) — required for ordering to work end-to-end; without it Wix limits ordering to "testing only" and checkout breaks.** If the brief gives no address, set a placeholder and flag the owner in the handoff. Completing a *paid* order additionally needs premium + a payment method (dashboard/premium — surface, don't fail). **Keep:** nothing for the handoff — read **live** (`listOperations`/`listFulfillmentMethods`); track `operationId`/`fulfillmentMethodIds[]` transiently. **Table reservations (add-on, on demand, INDEPENDENT of ordering/menu)** — only when the request calls for reservations: install the Table Reservations app (per `SETUP.md` §2) and follow **`setup-restaurant-reservations.md`**; **no menu dependency** (reservations bind to a location, not a menu — do NOT apply the menu-first rule) and **nothing to bulk-seed** (visitors create reservations at runtime); **configure the business-location address (`setup-restaurant-reservations.md` STEP 0)** — the reservation location is the site's business location, so set a real address (placeholder + owner flag if the brief names none; shared with ordering if both are present); enabling online reservations is **premium-gated** (record the precondition, don't fail). **Keep:** nothing for the handoff — read **live** (`listReservationLocations`); track `reservationLocationId` transiently. **Experiences (add-on within Table Reservations, on demand)** — only when the request names **special dining occasions guests reserve** (wine/cheese pairing, chef's table, tasting-menu evening — an *experience*, not a `bookings` service; see `CAPABILITIES.md`): they need the **Table Reservations app** (no extra install) and a configured **business-location address** (`setup-restaurant-reservations.md` STEP 0, same as reservations) and, unlike plain reservations, they **are** seeded — create one Experience per named occasion on the default reservation location, following **`setup-restaurant-experiences.md`**. Booking an experience is **premium-gated** like online reservations (record the precondition, don't fail). **Keep:** nothing for the handoff — experiences are read **live** (`queryExperiences`); track `experienceId`(s) transiently.
42
43
  - **portfolio** — *A project showcase.* Recipe: **`setup-portfolio.md`**. Create the `intent.portfolio.collections` (title + short description fitting `brand`), then `intent.portfolio.projectCount` projects assigned to them — **collections before projects** (a project's `collectionIds` must hold real collection ids; see the recipe). Text-only by default (omit `coverImage`; images only when `imagery` is on — §1, §4). **Keep (seed-time only):** `collectionIds{<name>}` to assign projects into their collections; nothing goes to the handoff — the frontend lists collections and projects **live** (`collections.queryCollections` / `projects.queryProjects`), so owner-added content appears with no code change.
@@ -59,7 +60,7 @@ Don't silently skip a required feature — a bare list-and-detail with none of i
59
60
 
60
61
  ## 4 · Entity images (opt-in)
61
62
 
62
- **Only if `imagery` is on** (from `DISCOVERY.md`). For each seeded image-bearing capability — stores products, blog covers, CMS items, **bookings services**, restaurant items, **portfolio projects + collection covers**, event heroes — generate a brand-contextual image per entity and **attach it as a required pass-2 step** (the seeder created the entity text-first in §2; this writes the image onto it), following `references/IMAGE_GENERATION.md` (generate → import to Wix Media → attach). **The per-entity attach shape lives in that capability's own seed recipe** (`setup-<capability>.md`), next to its create shape — read it there; `IMAGE_GENERATION.md` §3 is a navigation table (entity → recipe → step) that carries no shapes. Use the IDs already in the `seeded` map. Image failures never block — skip and continue (the entity stays text-only). When `imagery` is off, skip this step entirely.
63
+ **Only if `imagery` is on** (from `DISCOVERY.md`). For each seeded image-bearing capability — stores products, blog covers, CMS items, **bookings services**, **rental services**, restaurant items, **portfolio projects + collection covers**, event heroes — generate a brand-contextual image per entity and **attach it as a required pass-2 step** (the seeder created the entity text-first in §2; this writes the image onto it), following `references/IMAGE_GENERATION.md` (generate → import to Wix Media → attach). **The per-entity attach shape lives in that capability's own seed recipe** (`setup-<capability>.md`), next to its create shape — read it there; `IMAGE_GENERATION.md` §3 is a navigation table (entity → recipe → step) that carries no shapes. Use the IDs already in the `seeded` map. Image failures never block — skip and continue (the entity stays text-only). When `imagery` is off, skip this step entirely.
63
64
 
64
65
  ## Aggregate
65
66
 
@@ -23,6 +23,7 @@ For each capability in `verticals[]`, install its app by `appDefId` (these are t
23
23
  - **forms** → `225dd912-7dea-4738-8688-4b8c6955ffc2`
24
24
  - **events** → `140603ad-af8d-84a5-2c80-a0f60cb47351`
25
25
  - **bookings** → `13d21c63-b5ec-5912-8397-c3a5ddb27a97`
26
+ - **rentals** → `ff5d6eb1-65e4-4f9a-8b14-64d34c12cc2e` (Wix Rentals). Rentals provisions the Bookings infrastructure it runs on, so a Rentals-only install is enough — its availability comes back without adding Wix Bookings separately. Rentals has **no APIs of its own**: it is Services V2 with rentals-specific field values (`setup-rentals.md`), and its frontend package is `@wix/bookings` — there is no `@wix/rentals`. Rentals uses no categories; to also offer plain fixed-duration services, install Wix Bookings (`13d21c63-b5ec-5912-8397-c3a5ddb27a97`) as well, seed those with `setup-bookings.md`, and filter every catalog read by `appId` so the two sets stay separate.
26
27
  - **pricing-plans** → `1522827f-c56c-a5c9-2ac9-00f9e6ae12d3`
27
28
  - **restaurants** → `b278a256-2757-4f19-9313-c05c783bec92` (Wix Restaurants **Menus** — the seedable core). Online ordering and table reservations are **separate optional apps**, install only if intent calls for them: Orders (New) → `9a5d83fd-8570-482e-81ab-cfa88942ee60`, Table Reservations → `f9c07de2-5341-40c6-b096-8eb39de391fb`. **Experiences** (special dining occasions guests reserve — wine tastings, chef's tables; see `CAPABILITIES.md`) are a **feature of the Table Reservations app, not a separate install** — installing Table Reservations is all that's needed to create and book them (`setup-restaurant-experiences.md`).
28
29
  - **portfolio** → `d90652a2-f5a1-4c7c-84c4-d4cdcc41f130` (Wix Portfolio; the install ships a default sample collection + projects — `setup-portfolio.md` STEP 0 cleans them)
@@ -63,7 +63,7 @@ const { items } = await posts
63
63
  .limit(20)
64
64
  .find();
65
65
  ```
66
- Doc: <https://dev.wix.com/docs/api-reference/business-solutions/blog/posts/query-posts.md?apiView=SDK>
66
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/blog/posts-stats/query-posts.md?apiView=SDK>
67
67
 
68
68
  **⚠️ CRITICAL: request the `RICH_CONTENT` fieldset, or `post.richContent` is `undefined`.** `queryPosts` omits the body by default; without `fieldsets: ["RICH_CONTENT"]` the post comes back with no `richContent`, and the detail page renders blank. (Add `"URL"` to get `post.url`/`slug` for links.)
69
69
 
@@ -114,7 +114,7 @@ export default function RicosContentViewer({ content }) {
114
114
  return <div className="ricos-content"><RicosViewer content={content} plugins={plugins} /></div>;
115
115
  }
116
116
  ```
117
- Doc: <https://dev.wix.com/docs/sdk/business-solutions/blog/introduction.md?apiView=SDK> (follow it to the current Ricos viewer API; verify with `SearchWixSDKDocumentation "ricos viewer"`).
117
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/blog/introduction.md?apiView=SDK> (follow it to the current Ricos viewer API; verify with `SearchWixSDKDocumentation "ricos viewer"`).
118
118
 
119
119
  **⚠️ CRITICAL (Astro): render the viewer with `client:only="react"`.** `@wix/ricos` is a React component that breaks under SSR. `<RicosViewer client:only="react" content={post.richContent} />` makes it render client-side only. `@wix/ricos` accepts the camelCase `richContent` from the `@wix/blog` SDK directly — no key renaming.
120
120