@wix/agent-skills 1.16.3 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +115 -12
  3. package/skills/wix-app/references/APP_MARKET_REVIEW.md +1 -1
  4. package/skills/wix-app/references/BACKEND_API.md +18 -0
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +6 -0
  6. package/skills/wix-app/references/DASHBOARD_MODAL.md +10 -2
  7. package/skills/wix-app/references/DASHBOARD_PAGE.md +32 -70
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +145 -127
  9. package/skills/wix-app/references/SITE_PLUGIN.md +14 -2
  10. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +74 -68
  11. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
  12. package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +79 -0
  13. package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +73 -0
  14. package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +52 -0
  15. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +184 -0
  16. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
  17. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +94 -49
  18. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +16 -6
  19. package/skills/wix-app/references/editor-react-component/BROWSER-SUPPORT.md +56 -0
  20. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
  21. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +35 -40
  22. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +167 -445
  23. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +56 -29
  24. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
  25. package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
  26. package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
  27. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +11 -3
  28. package/skills/wix-app/references/editor-react-component/PARTS.md +46 -24
  29. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
  30. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
  31. package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
  32. package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
  33. package/skills/wix-base44-connector/SKILL.md +156 -50
  34. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +78 -0
  35. package/skills/wix-base44-connector/scripts/utils.js +239 -45
  36. package/skills/wix-headless/entry/bootstrap.mjs +9 -2
  37. package/skills/wix-headless/entry/skill.md +1 -1
  38. package/skills/wix-headless/references/CAPABILITIES.md +9 -1
  39. package/skills/wix-headless/references/DESIGN.md +1 -0
  40. package/skills/wix-headless/references/DISCOVERY.md +2 -1
  41. package/skills/wix-headless/references/IMAGE_GENERATION.md +1 -0
  42. package/skills/wix-headless/references/SDK_HANDOFF.md +5 -2
  43. package/skills/wix-headless/references/SEED.md +2 -1
  44. package/skills/wix-headless/references/SETUP.md +1 -0
  45. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +2 -2
  46. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +68 -31
  47. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +26 -10
  48. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +8 -8
  49. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +1 -1
  50. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +1 -1
  51. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
  52. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +254 -0
  53. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
  54. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +13 -0
  55. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +254 -0
  56. package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
  57. package/skills/wix-headless/references/non-astro.md +1 -1
  58. package/skills/wix-headless-fast/SKILL.md +166 -0
  59. package/skills/wix-headless-fast/entry/skill.md +99 -0
  60. package/skills/wix-headless-fast/install/deploy.mjs +433 -0
  61. package/skills/wix-headless-fast/install/fast-path.mjs +141 -0
  62. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +137 -0
  63. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +137 -0
  64. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +113 -0
  65. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +42 -0
  66. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +123 -0
  67. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +70 -0
  68. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +99 -0
  69. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +76 -0
  70. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +62 -0
  71. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +40 -0
  72. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +99 -0
  73. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +24 -0
  74. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +16156 -0
  75. package/skills/wix-headless-fast/references/blog/seed/SEED.md +72 -0
  76. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +287 -0
  77. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +129 -0
  78. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +143 -0
  79. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +119 -0
  80. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +138 -0
  81. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +54 -0
  82. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +206 -0
  83. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +96 -0
  84. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +70 -0
  85. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +40 -0
  86. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +76 -0
  87. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +22 -0
  88. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +11962 -0
  89. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +61 -0
  90. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +302 -0
  91. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +179 -0
  92. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +83 -0
  93. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +57 -0
  94. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +151 -0
  95. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +75 -0
  96. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +41 -0
  97. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +11262 -0
  98. package/skills/wix-headless-fast/references/cms/seed/SEED.md +103 -0
  99. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +324 -0
  100. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +149 -0
  101. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +66 -0
  102. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +176 -0
  103. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +118 -0
  104. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +117 -0
  105. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +59 -0
  106. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +136 -0
  107. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +128 -0
  108. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +61 -0
  109. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +40 -0
  110. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +12 -0
  111. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +80 -0
  112. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +21 -0
  113. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +11884 -0
  114. package/skills/wix-headless-fast/references/events/seed/SEED.md +86 -0
  115. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +276 -0
  116. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +150 -0
  117. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +317 -0
  118. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +269 -0
  119. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +231 -0
  120. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +135 -0
  121. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +10593 -0
  122. package/skills/wix-headless-fast/references/forms/seed/SEED.md +108 -0
  123. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +320 -0
  124. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +63 -0
  125. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +60 -0
  126. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +155 -0
  127. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +78 -0
  128. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +47 -0
  129. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +66 -0
  130. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +88 -0
  131. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +53 -0
  132. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +122 -0
  133. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +50 -0
  134. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +21 -0
  135. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +42 -0
  136. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +10 -0
  137. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +11 -0
  138. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +10329 -0
  139. package/skills/wix-headless-fast/references/members/seed/SEED.md +39 -0
  140. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +94 -0
  141. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +134 -0
  142. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
  143. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
  144. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +115 -0
  145. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +59 -0
  146. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +39 -0
  147. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +58 -0
  148. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +165 -0
  149. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +55 -0
  150. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
  151. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
  152. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +21 -0
  153. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +29 -0
  154. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +10197 -0
  155. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +78 -0
  156. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +258 -0
  157. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +133 -0
  158. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +58 -0
  159. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +126 -0
  160. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +37 -0
  161. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +39 -0
  162. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +75 -0
  163. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +45 -0
  164. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +30 -0
  165. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
  166. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +40 -0
  167. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +21 -0
  168. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +11226 -0
  169. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +71 -0
  170. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +279 -0
  171. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +165 -0
  172. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +142 -0
  173. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
  174. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
  175. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +155 -0
  176. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +55 -0
  177. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +43 -0
  178. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +177 -0
  179. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +165 -0
  180. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +103 -0
  181. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +254 -0
  182. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +146 -0
  183. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +168 -0
  184. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
  185. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +22 -0
  186. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +12 -0
  187. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +12560 -0
  188. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +81 -0
  189. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +479 -0
  190. package/skills/wix-headless-fast/references/shared/CONTENT.md +22 -0
  191. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +73 -0
  192. package/skills/wix-headless-fast/references/shared/DESIGN.md +26 -0
  193. package/skills/wix-headless-fast/references/shared/app/styles/global.css +52 -0
  194. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +15 -0
  195. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +27 -0
  196. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +24 -0
  197. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +76 -0
  198. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
  199. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +46 -0
  200. package/skills/wix-headless-fast/references/shared/seed/images.mjs +145 -0
  201. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +149 -0
  202. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +26 -0
  203. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +121 -0
  204. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +100 -0
  205. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +130 -0
  206. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +48 -0
  207. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +66 -0
  208. package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +103 -0
  209. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +48 -0
  210. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +140 -0
  211. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +80 -0
  212. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +101 -0
  213. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +221 -0
  214. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +215 -0
  215. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +109 -0
  216. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +46 -0
  217. package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +56 -0
  218. package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +23 -0
  219. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +12247 -0
  220. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +85 -0
  221. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +415 -0
  222. package/skills/wix-manage/SKILL.md +28 -2
  223. package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
  224. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
  225. package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
  226. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +141 -0
  227. package/skills/wix-manage/references/google-business-profile/connect-google-business-profile.md +134 -0
  228. package/skills/wix-manage/references/google-business-profile/manage-google-business-profile-locations.md +182 -0
  229. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +3 -0
  230. package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
  231. package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
  232. package/skills/wix-manage/references/sites/query-sites.md +72 -161
  233. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +21 -6
  234. package/skills/wix-manage/references/stores/update-product-with-options.md +83 -0
  235. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
  236. package/skills/wix-vibe-headless/SKILL.md +18 -4
  237. package/skills/wix-vibe-headless/install/deploy.cjs +12 -4
  238. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +2 -1
  239. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +16 -10
  240. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +13 -8
  241. package/skills/wix-vibe-headless/platforms/base44.md +27 -62
  242. package/skills/wix-vibe-headless/platforms/generic.md +6 -3
  243. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +45 -0
  244. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +67 -0
  245. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +128 -0
  246. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +5 -3
  247. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
  248. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +250 -0
  249. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +12 -5
  250. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +41 -0
  251. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.js +267 -0
  252. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +6 -3
  253. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +470 -0
  254. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +425 -0
  255. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +187 -0
  256. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +238 -0
  257. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +108 -0
  258. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1762 -0
  259. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +13 -0
  260. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
  261. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
  262. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
  263. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
  264. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +152 -92
  265. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
  266. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
  267. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +15 -8
  268. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +37 -0
  269. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
  270. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +18 -6
  271. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +30 -7
  272. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +46 -10
  273. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
  274. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
  275. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -516
  276. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
  277. package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
  278. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
  279. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +0 -110
  280. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +0 -51
  281. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +0 -49
  282. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +0 -92
  283. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +0 -139
@@ -0,0 +1,61 @@
1
+ # Bookings — seeding
2
+
3
+ Seed by **running `seed-bookings.mjs` with a plan file** — don't hand-write the REST calls.
4
+ The script mints its own site token via the Wix CLI (logged-in session + `wix.config.json`
5
+ required), installs the Bookings app if needed, resolves a staff resource (polling — a fresh
6
+ install provisions the owner asynchronously), and creates everything in the right order.
7
+
8
+ ```bash
9
+ # from the project root (where wix.config.json lives):
10
+ node <SKILL_ROOT>/references/bookings/seed/seed-bookings.mjs plan.json
11
+ ```
12
+
13
+ `plan.json` is plain data — write it from the brief. **Default to 3 services** (the seed
14
+ shows the shape; the owner adds the rest in the dashboard) and make them exercise the UI:
15
+ mix APPOINTMENT and CLASS when it fits the business, include ≥1 free/pay-in-person service,
16
+ and give every service an image — the default is an `imagePrompt` (AI-generated, ~1 Wix AI
17
+ credit per image, account-billed): brand-contextual — subject, aesthetic/mood, palette,
18
+ lighting — always ending "no text, no watermarks". At least one image in the set shows the real subject of the business — the actual product/space/service, not abstract decoration. For an asset the user actually supplied use `imagePath` (a file on this
19
+ machine — uploaded to Wix Media) or `imageUrl` (their own hosted URL; verify it with
20
+ `curl -sI` → 200) — never a stock-photo or guessed URL. Images resolve in parallel and never block the seed; a failed
21
+ image leaves that service text-only.
22
+
23
+ ```json
24
+ {
25
+ "services": [
26
+ { "type": "APPOINTMENT", "name": "Deep Tissue Massage", "tagLine": "60 minutes of relief",
27
+ "description": "…", "price": 85, "duration": 60, "category": "Massage",
28
+ "imageUrl": "https://…" },
29
+ { "type": "APPOINTMENT", "name": "Intro Consultation", "description": "…", "free": true,
30
+ "duration": 30, "category": "Massage", "imageUrl": "https://…" },
31
+ { "type": "CLASS", "name": "Morning Yoga", "description": "…", "price": 20, "capacity": 12,
32
+ "category": "Classes", "imageUrl": "https://…",
33
+ "sessions": [
34
+ { "start": "2026-09-01T09:00:00", "end": "2026-09-01T10:00:00" },
35
+ { "start": "2026-09-03T09:00:00", "end": "2026-09-03T10:00:00" }
36
+ ] }
37
+ ]
38
+ }
39
+ ```
40
+
41
+ - `type` — `APPOINTMENT` (visitor picks a free slot; needs `duration` in minutes) or `CLASS`
42
+ (fixed `sessions` you schedule here — **future local wall-clock** `YYYY-MM-DDThh:mm:ss`, no Z;
43
+ a CLASS without sessions shows no bookable times).
44
+ - `price` — a number; omit or `free: true` → a no-fee, pay-in-person service (books without
45
+ checkout). The site currency wins over `currency`.
46
+ - `category` — a name; created idempotently. Every service gets one (required for live-site
47
+ visibility) — uncategorized services fall into a default "Services" category.
48
+ - Staff: appointments are auto-assigned to the site's default staff resource; the flow books
49
+ with ANY_RESOURCE when the visitor doesn't choose.
50
+
51
+ **Seeding is additive — never delete or overwrite existing content**; ask first if a cleanup
52
+ seems needed.
53
+
54
+ ## Escape hatch — individual functions
55
+ `setupBookings` composes exported steps — `installBookingsApp`, `queryStaffWithRetry`,
56
+ `createCategories`, `createServices`, `scheduleClassSessions`, `importImage`,
57
+ `attachServiceImage`, plus `makeCtx()` — import them only for a partial re-seed.
58
+
59
+ ## Reference
60
+ Unexpected shape or an uncovered operation → read the live Wix API reference; the
61
+ authoritative source recipe is `wix-headless/references/inline-recipes/setup-bookings.md`.
@@ -0,0 +1,302 @@
1
+ // Bookings seed — a BUILD-TIME script, never shipped in the app. Run from the project root
2
+ // (where wix.config.json lives) with a plan file:
3
+ //
4
+ // node <SKILL_ROOT>/references/bookings/seed/seed-bookings.mjs plan.json
5
+ //
6
+ // It mints its own site token via the Wix CLI, installs the Wix Bookings app if needed,
7
+ // resolves a staff resource (polling — a fresh install provisions the owner async), creates
8
+ // categories (idempotent by name) and services (bulk; APPOINTMENT + CLASS mixed), schedules
9
+ // CLASS sessions, and imports+attaches images. Prints a JSON result to stdout.
10
+ //
11
+ // Plan shape (see SEED.md):
12
+ // { "services": [{ "type": "APPOINTMENT"|"CLASS", "name", "description", "tagLine"?,
13
+ // "price"?, "free"?, "duration"? (APPOINTMENT, minutes), "capacity"?,
14
+ // "category"? (name), "imageUrl"? | "imagePrompt"?,
15
+ // "sessions"?: [{ "start", "end", "capacity"? }] }] } // CLASS only; local "YYYY-MM-DDThh:mm:ss"
16
+ //
17
+ // Seeding is ADDITIVE — never deletes or overwrites existing content. Unexpected shapes →
18
+ // read the live API reference; authoritative source recipe:
19
+ // wix-headless/references/inline-recipes/setup-bookings.md.
20
+ import { execFileSync } from "node:child_process";
21
+ import { readFileSync } from "node:fs";
22
+ import { resolveItemImages } from "../../shared/seed/images.mjs";
23
+
24
+ const API = "https://www.wixapis.com";
25
+ const BOOKINGS_APP_ID = "13d21c63-b5ec-5912-8397-c3a5ddb27a97";
26
+
27
+ export function makeCtx({ cwd = process.cwd() } = {}) {
28
+ const config = JSON.parse(readFileSync(`${cwd}/wix.config.json`, "utf8"));
29
+ const siteId = config.siteId ?? config.projectId;
30
+ if (!siteId) throw new Error("wix.config.json has no siteId — is this a Wix CLI project?");
31
+ const token = execFileSync("npx", ["@wix/cli@latest", "token", "--site", siteId], {
32
+ encoding: "utf8",
33
+ cwd,
34
+ }).trim();
35
+ if (!token) throw new Error("The Wix CLI returned no token — run `npx @wix/cli@latest login` first.");
36
+ return { token, siteId };
37
+ }
38
+
39
+ async function req(ctx, path, { method = "POST", body } = {}) {
40
+ const res = await fetch(API + path, {
41
+ method,
42
+ headers: {
43
+ Authorization: `Bearer ${ctx.token}`,
44
+ "wix-site-id": ctx.siteId,
45
+ "Content-Type": "application/json",
46
+ },
47
+ body: body ? JSON.stringify(body) : undefined,
48
+ });
49
+ const json = await res.json().catch(() => ({}));
50
+ if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
51
+ return json;
52
+ }
53
+
54
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
55
+
56
+ function slugify(name) {
57
+ return String(name || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
58
+ }
59
+
60
+ // plain service -> flat Services V2 create object. price omitted / free:true -> NO_FEE.
61
+ function buildService(s) {
62
+ const isAppointment = s.type === "APPOINTMENT";
63
+ const free = s.free === true || s.price == null;
64
+ const out = {
65
+ type: s.type,
66
+ name: s.name,
67
+ description: s.description,
68
+ tagLine: s.tagLine,
69
+ defaultCapacity: s.capacity ?? (isAppointment ? 1 : undefined),
70
+ onlineBooking: { enabled: true, requireManualApproval: false, allowMultipleRequests: false },
71
+ payment: free
72
+ ? { rateType: "NO_FEE", options: { online: false, inPerson: true } }
73
+ : {
74
+ rateType: "FIXED",
75
+ fixed: { price: { value: String(s.price), currency: s.currency ?? "USD" } },
76
+ options: { online: true, inPerson: false },
77
+ },
78
+ category: { id: s.categoryId }, // mandatory for live-site visibility
79
+ locations: [{ type: "BUSINESS" }], // never OWNER_BUSINESS on the services endpoint
80
+ };
81
+ if (isAppointment) {
82
+ out.schedule = { availabilityConstraints: { sessionDurations: [s.duration ?? 60] } };
83
+ out.staffMemberIds = s.staffMemberIds; // resourceId(s) — non-empty or MISSING_APPOINTMENT_RESOURCES
84
+ }
85
+ return out;
86
+ }
87
+
88
+ // ---- operations ----------------------------------------------------------------------------------
89
+
90
+ // docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
91
+ export async function installBookingsApp(ctx) {
92
+ try {
93
+ await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
94
+ tenant: { tenantType: "SITE", id: ctx.siteId },
95
+ appInstance: { appDefId: BOOKINGS_APP_ID, enabled: true },
96
+ } });
97
+ } catch {
98
+ /* already installed is fine */
99
+ }
100
+ }
101
+
102
+ // ⚠️ staffMemberIds takes resourceId, NOT the staff id.
103
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/staff-members/staff-members/query-staff-members.md
104
+ export async function queryStaff(ctx) {
105
+ const r = await req(ctx, "/bookings/v1/staff-members/query", {
106
+ body: { query: {}, fields: ["RESOURCE_DETAILS"] },
107
+ });
108
+ return (r.staffMembers ?? []).map((m) => ({ resourceId: m.resourceId, id: m.id, name: m.name }));
109
+ }
110
+
111
+ // A fresh install provisions the default "Business Owner" resource ASYNC — poll until it lands.
112
+ export async function queryStaffWithRetry(ctx, { tries = 15, delayMs = 2000 } = {}) {
113
+ let lastErr;
114
+ for (let i = 0; i < tries; i++) {
115
+ try {
116
+ const s = await queryStaff(ctx);
117
+ if (s.length) return s;
118
+ } catch (e) {
119
+ lastErr = e;
120
+ }
121
+ if (i < tries - 1) await sleep(delayMs);
122
+ }
123
+ if (lastErr) throw lastErr;
124
+ return [];
125
+ }
126
+
127
+ // Every service needs a category.id or it's invisible on the live site. Idempotent by name.
128
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/query-categories.md
129
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/categories-v2/create-category.md
130
+ export async function createCategories(ctx, names) {
131
+ const existing = await req(ctx, "/bookings/v2/categories/query", { body: { query: {} } });
132
+ const byName = new Map((existing.categories ?? []).map((c) => [c.name, { id: c.id, name: c.name }]));
133
+ const out = [];
134
+ for (const name of names) {
135
+ let cat = byName.get(name);
136
+ if (!cat) {
137
+ const r = await req(ctx, "/bookings/v2/categories", { body: { category: { name } } });
138
+ cat = { id: r.category?.id, name };
139
+ byName.set(name, cat);
140
+ }
141
+ out.push(cat);
142
+ }
143
+ return out;
144
+ }
145
+
146
+ // Bulk-create services (APPOINTMENT + CLASS mixed). Run AFTER staff + categories.
147
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/bulk-create-services.md
148
+ export async function createServices(ctx, services) {
149
+ const body = { services: services.map(buildService), returnEntity: true };
150
+ const r = await req(ctx, "/bookings/v2/bulk/services/create", { body });
151
+ return (r.results ?? []).map((res, i) => {
152
+ const item = res.item ?? {};
153
+ return {
154
+ id: item.id ?? res.itemMetadata?.id,
155
+ slug: item.mainSlug?.name ?? slugify(item.name ?? services[i]?.name),
156
+ revision: item.revision,
157
+ type: item.type ?? services[i]?.type,
158
+ scheduleId: item.schedule?.id,
159
+ success: res.itemMetadata?.success ?? false,
160
+ error: res.itemMetadata?.error,
161
+ };
162
+ });
163
+ }
164
+
165
+ // CLASS only: schedule sessions (bulk Calendar Events V3). start/end are LOCAL wall-clock
166
+ // "YYYY-MM-DDThh:mm:ss" (no Z), today-or-future.
167
+ // docs: https://dev.wix.com/docs/api-reference/business-management/calendar/events-v3/bulk-create-event.md
168
+ export async function scheduleClassSessions(ctx, sessions) {
169
+ const body = {
170
+ events: sessions.map((s) => ({
171
+ event: {
172
+ scheduleId: s.scheduleId,
173
+ type: "CLASS",
174
+ start: { localDate: s.start },
175
+ end: { localDate: s.end },
176
+ resources: [{ id: s.resourceId, permissionRole: "WRITER" }], // non-empty + WRITER, else UNKNOWN_ROLE
177
+ ...(s.capacity != null ? { totalCapacity: s.capacity } : {}),
178
+ },
179
+ })),
180
+ };
181
+ const r = await req(ctx, "/calendar/v3/bulk/events/create", { body });
182
+ return (r.results ?? []).map((res) => ({
183
+ id: res.itemMetadata?.id,
184
+ success: res.itemMetadata?.success ?? false,
185
+ error: res.itemMetadata?.error,
186
+ }));
187
+ }
188
+
189
+ // Bookings binds a service image by Wix Media file ID — an external url must be imported
190
+ // first; a plan `imagePrompt` is generated (Wix AI, 1 credit) then imported. Both live in the
191
+ // shared util (parallel, resilient, never blocks the seed).
192
+ export { importImage } from "../../shared/seed/images.mjs";
193
+
194
+ // Writes under media.mainMedia + media.coverMedia (writing media.image 200s but silently drops).
195
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/bookings/services/services-v2/update-service.md
196
+ export async function attachServiceImage(ctx, it) {
197
+ return req(ctx, `/bookings/v2/services/${it.serviceId}`, {
198
+ method: "PATCH",
199
+ body: {
200
+ service: {
201
+ id: it.serviceId,
202
+ revision: it.revision,
203
+ media: { mainMedia: { image: it.image }, coverMedia: { image: it.image } },
204
+ },
205
+ },
206
+ });
207
+ }
208
+
209
+ /**
210
+ * ONE-CALL seed: install → resolve staff (poll) → categories → services → CLASS sessions →
211
+ * images, ids threaded in memory. The default path.
212
+ */
213
+ export async function setupBookings(ctx, { services = [], staffResourceId } = {}) {
214
+ await installBookingsApp(ctx);
215
+
216
+ let resourceId = staffResourceId;
217
+ if (!resourceId) {
218
+ const staff = await queryStaffWithRetry(ctx);
219
+ resourceId = staff[0]?.resourceId;
220
+ }
221
+ if (!resourceId) throw new Error("No staff resource resolved — Bookings provisioning may still be in progress; re-run the seed.");
222
+
223
+ const catNames = [...new Set(services.map((s) => s.category).filter(Boolean))];
224
+ const cats = catNames.length ? await createCategories(ctx, catNames) : await createCategories(ctx, ["Services"]);
225
+ const catIdByName = new Map(cats.map((c) => [c.name, c.id]));
226
+ const defaultCatId = cats[0]?.id;
227
+
228
+ const created = await createServices(ctx, services.map((s) => ({
229
+ type: s.type,
230
+ name: s.name,
231
+ description: s.description,
232
+ tagLine: s.tagLine,
233
+ price: s.price,
234
+ currency: s.currency,
235
+ free: s.free,
236
+ duration: s.duration,
237
+ capacity: s.capacity,
238
+ categoryId: (s.category ? catIdByName.get(s.category) : undefined) ?? defaultCatId,
239
+ staffMemberIds: s.staffMemberIds ?? (s.type === "APPOINTMENT" ? [resourceId] : undefined),
240
+ })));
241
+
242
+ const sessions = [];
243
+ created.forEach((c, i) => {
244
+ const plan = services[i];
245
+ if (c.type === "CLASS" && c.scheduleId && Array.isArray(plan?.sessions)) {
246
+ for (const ses of plan.sessions) {
247
+ sessions.push({ scheduleId: c.scheduleId, resourceId, start: ses.start, end: ses.end, capacity: ses.capacity ?? plan.capacity });
248
+ }
249
+ }
250
+ });
251
+ const scheduled = sessions.length ? await scheduleClassSessions(ctx, sessions) : [];
252
+
253
+ // Pass 2 — images: resolve (import by url / generate by prompt) in one parallel wave, then
254
+ // attach. Failures leave the service text-only; the seed's exit never depends on images.
255
+ const files = await resolveItemImages(ctx, created.map((c, i) => ({
256
+ url: services[i]?.imageUrl,
257
+ path: services[i]?.imagePath,
258
+ prompt: services[i]?.imagePrompt,
259
+ displayName: `${c?.slug || "service"}.png`,
260
+ })));
261
+ let imagesAttached = 0;
262
+ for (let i = 0; i < created.length; i++) {
263
+ if (!files[i] || !created[i]?.id) continue;
264
+ try {
265
+ await attachServiceImage(ctx, {
266
+ serviceId: created[i].id,
267
+ revision: created[i].revision,
268
+ image: { id: files[i].id, url: files[i].url, width: 1024, height: 1024 },
269
+ });
270
+ imagesAttached++;
271
+ } catch {
272
+ /* never block on image failure — the service stays text-only */
273
+ }
274
+ }
275
+
276
+ return {
277
+ services: created,
278
+ categories: cats,
279
+ resourceId,
280
+ sessionsScheduled: scheduled.filter((s) => s.success).length,
281
+ imagesAttached,
282
+ };
283
+ }
284
+
285
+ // ---- CLI entry ----------------------------------------------------------------------------------
286
+
287
+ const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
288
+ if (invokedDirectly) {
289
+ const planPath = process.argv[2];
290
+ if (!planPath) {
291
+ console.error("usage: node seed-bookings.mjs <plan.json> (run from the project root)");
292
+ process.exit(1);
293
+ }
294
+ const plan = JSON.parse(readFileSync(planPath, "utf8"));
295
+ const ctx = makeCtx();
296
+ setupBookings(ctx, plan)
297
+ .then((result) => console.log(JSON.stringify(result, null, 2)))
298
+ .catch((e) => {
299
+ console.error(e.message);
300
+ process.exit(1);
301
+ });
302
+ }
@@ -0,0 +1,179 @@
1
+ # CMS — playbook
2
+
3
+ The data machinery ships as files — typed reads/writes over ANY collection, hooks, and the
4
+ normalization layer (dates → ISO strings, `wix:image://` → https URLs), correct end-to-end.
5
+ CMS is schema-generic, so unlike other verticals there are **no fixed pages**: the seed plan
6
+ (`plan.json`) is the site's content model, and **you design the pages from it** — a listing
7
+ surface and an item page per content collection, plus the home page and the brand. You never
8
+ write data-access logic; you never skip designing.
9
+
10
+ ## The file map (deployed into `src/`)
11
+
12
+ **Don't read the shipped files** — this table and the contracts below are everything you
13
+ need. Open a shipped file's source only on a real fallback (runtime error / uncovered field).
14
+
15
+ | file | what it is |
16
+ |---|---|
17
+ | `wix/config.ts` · `wix/sdk.ts` · `wix/media.ts` · `wix/money.ts` | shared auth seam + helpers (deploy configures; nothing to set) |
18
+ | `wix/cms/types.ts` | the DTOs (`CmsItem`, `CmsFilter`, `CmsSort`, `CmsQuery`, `CmsPage`) — contracts below |
19
+ | `wix/cms/items.ts` | `queryItems`, `getItemById`, `getItemBy`, `countItems`, `insertItem`, `updateItem`, `patchItemFields`, `removeItem` |
20
+ | `hooks/cms/useCollection.ts` | list state + skip paging — contract below |
21
+ | `hooks/cms/useItem.ts` | one item by `_id` or slug field — contract below |
22
+ | `styles/global.css` | the design system: Tailwind v4 + the `@theme` token block (shared across verticals) |
23
+
24
+ There are **no shipped components** — the data layer and hooks are the machinery; every
25
+ component is yours.
26
+
27
+ Astro stack additionally gets:
28
+
29
+ | file | what it is |
30
+ |---|---|
31
+ | `layouts/SiteLayout.astro` | site chrome — **yours to brand** (keep the `seo-tags` slot + global.css import). If another vertical is also deployed, its layout won — add your content nav links there |
32
+
33
+ There are **no shipped pages** — you author them (below).
34
+
35
+ ## What you build — the design job
36
+
37
+ Read the seed plan first: its collections, field keys, and permissions are the contract your
38
+ pages bind to (collection ids and field keys verbatim).
39
+
40
+ 1. **A listing surface per content collection** — your card (image, title, secondary fields)
41
+ and rhythm, with skeletons while loading and an honest empty state — on `useCollection`
42
+ (or SSR via `queryItems` alone when the page needs no interactivity).
43
+ 2. **An item page per collection with a `slug` field** — your detail layout on the DTO
44
+ (SSR fetch via `getItemBy`), with a real 404 on miss.
45
+ 3. **The home page** — hero, featured items (fetch in frontmatter → your components), brand
46
+ story.
47
+
48
+ Plus the **theme** (`@theme` block, one edit) and the **chrome** (`SiteLayout`, one pass).
49
+ Style everything with Tailwind utilities on the tokens.
50
+
51
+ ### The contracts your components consume
52
+
53
+ ```ts
54
+ // CmsItem — display-ready, fields FLAT on the item (never item.data.*):
55
+ // { _id, _createdDate?, _updatedDate?, _owner?, ...fields }
56
+ // TEXT/URL/EMAIL → string · NUMBER → number · BOOLEAN → boolean
57
+ // DATE/DATETIME → ISO string (render: new Date(iso).toLocaleDateString())
58
+ // IMAGE → resolved https URL (straight into <img src>; guard the absent case)
59
+ // RICH_TEXT → the stored HTML string (render via set:html on a wrapper you control)
60
+ // REFERENCE/MULTI_REFERENCE → id(s); full CmsItem(s) when queried with include
61
+
62
+ // queryItems(collectionId, { filters?, sort?, limit?, skip?, include?, withTotal? })
63
+ // → { items: CmsItem[], hasNext, total } // filters: [{ field, op, value }]
64
+ // ops: eq ne gt ge lt le contains startsWith hasSome hasAll isEmpty isNotEmpty
65
+ // DATE comparands must be Date objects (an ISO string matches nothing)
66
+ // getItemBy(collectionId, field, value) → CmsItem | null // slug routing
67
+ // getItemById(collectionId, id) → CmsItem | null
68
+ // countItems(collectionId, filters?) → number
69
+
70
+ // useCollection(collectionId, { filters?, sort?, limit?, include?, initialItems?, initialHasNext? })
71
+ // → { items: CmsItem[]|null /* null = loading → skeletons */,
72
+ // hasNext, loadMore(), loadingMore, error } // changing filters/sort refetches
73
+
74
+ // useItem(collectionId, { id } | { by: { field, value } }, { initialItem? })
75
+ // → { item: CmsItem|null, notFound, error } // notFound → your 404/miss state
76
+
77
+ // Writes (only when the collection's permissions allow the caller):
78
+ // insertItem(collectionId, data) // dates as Date objects; never set _owner
79
+ // patchItemFields(collectionId, id, fields) // the safe partial change
80
+ // updateItem(collectionId, item) // REPLACES the whole item — see hard rules
81
+ // removeItem(collectionId, id)
82
+ ```
83
+
84
+ ### Wiring — Astro (default)
85
+
86
+ 1. Set the `@theme` tokens (one edit); brand `SiteLayout.astro` (one pass) and add one nav
87
+ link per content surface.
88
+ 2. Author your pages under `src/pages/` — SSR fetch in the frontmatter, DTO props to your
89
+ islands (`client:load`; a page with no interactivity needs no island at all). Listing:
90
+
91
+ ```astro
92
+ ---
93
+ import SiteLayout from "../layouts/SiteLayout.astro";
94
+ import { queryItems } from "../wix/cms/items";
95
+ import type { CmsPage } from "../wix/cms/types";
96
+ let page: CmsPage = { items: [], hasNext: false, total: null };
97
+ try {
98
+ page = await queryItems("recipes", { sort: [{ field: "publishDate", direction: "desc" }] });
99
+ } catch {
100
+ // an unguarded SSR throw truncates the response mid-stream
101
+ }
102
+ ---
103
+ ```
104
+
105
+ Item page (`src/pages/recipes/[slug].astro`): `getItemBy("recipes", "slug", Astro.params.slug!)`
106
+ in the frontmatter; `return new Response(null, { status: 404 })` on null. SEO is plain
107
+ `<title>`/`<meta name="description">` from the DTO via the layout props — CMS collections
108
+ have **no owner-editable SEO item type**, so don't copy another vertical's
109
+ `wixMetadata`/`<SEO.Tags>` wiring.
110
+ 3. **Author your surfaces in as few messages as possible** — batch multiple Writes per
111
+ message (components and pages are independent files).
112
+
113
+ ### Wiring — React SPA (Vite etc.)
114
+
115
+ Import `./styles/global.css` once at the app entry (needs `@tailwindcss/vite` in the vite
116
+ plugins — deploy added the dep). Routes are yours: a list route per collection on
117
+ `useCollection`, a detail route on `useItem` with `by: { field: "slug", value }`.
118
+
119
+ ## Hard rules
120
+
121
+ - **Data only through the shipped exports** — never re-derive a Wix Data request, never
122
+ import `@wix/data` directly in your components, never hand-build a `static.wixstatic.com`
123
+ URL.
124
+ - **The id is `_id`, fields are flat** — `item.id` is undefined; `item.data.title` is the
125
+ REST shape and reads undefined.
126
+ - **Bind by the seed plan's ids and keys verbatim** — collection ids have no namespace; a
127
+ mistyped field key reads as a blank, not an error.
128
+ - **An empty read on a PUBLIC collection is a seed permissions bug** (`read` must be
129
+ `ANYONE`) — fix the seed, never reach for `auth.elevate` (it doesn't exist on this path).
130
+ On a member-scoped collection an empty anonymous read is the gate working, not a bug.
131
+ - **`updateItem` REPLACES the whole item** — omitted fields are wiped. Spread the full item,
132
+ or use `patchItemFields`. Date fields on any write are Date objects — a round-tripped ISO
133
+ string is silently stored as text and breaks date queries.
134
+ - **Writes 403 unless the collection was seeded with that verb open** — surface a 403 as a
135
+ permissions setup step (which permission, where in the dashboard), not a code bug.
136
+ - **User-created content is a CMS contribution flow.** For a member or visitor submission that
137
+ the app must later list, use the seeded CMS collection and its intended permission preset.
138
+ If the operation needs elevated access — especially a browser-created file that must enter
139
+ Media Manager — follow `references/shared/CUSTOM_OPERATIONS.md`: validate the caller and
140
+ input in a narrow server endpoint before elevating one documented operation. Never call a
141
+ privileged Media API directly from a client island.
142
+ - **Use the shipped upload capability when it fits.** Declare its named policy in
143
+ `plan.capabilities.mediaUpload`; Fast deploys the endpoint, client helper, dependencies, and
144
+ generated policy module. Your CMS surface calls `uploadMedia(policyId, file)` and stores the
145
+ returned Wix Media reference. Do not author another upload endpoint for that flow.
146
+ - **RICH_TEXT is HTML, not plain text** — render it with `set:html` (Astro) /
147
+ `dangerouslySetInnerHTML` (React) on a wrapper; never interpolate it as text.
148
+ - Reference fields hold ids unless the query passed `include` — don't render an id as
149
+ content.
150
+ - Guard absent IMAGE fields — render a fallback, never an empty/broken `<img>`.
151
+ - Theme via the `@theme` tokens; no parallel theme files, no hardcoded palettes.
152
+ - Live data or an honest empty state — never mock items or invent fields not in the plan.
153
+
154
+ ## Point the user to their dashboard
155
+
156
+ Give the owner the dashboard link — the deploy step's JSON printed `dashboardUrl`; append
157
+ `/wix-cms` for the collections area (items, fields, and More Actions → Permissions &
158
+ Privacy live there).
159
+
160
+ ## Seeding
161
+
162
+ Per `seed/SEED.md` — plain-data `plan.json` into `seed-cms.mjs` from the project root. The
163
+ plan is the content model your pages bind to: design collections that exercise the UI
164
+ (a `slug` field per detail page, an IMAGE field with a verified `imageUrl` per item, a DATE
165
+ field when the content is chronological).
166
+
167
+ ## Verify (before declaring done)
168
+
169
+ - [ ] Each listing page renders live items SSR (view-source shows titles) through YOUR
170
+ components; an empty collection shows your honest empty state (no mock items).
171
+ - [ ] Item pages resolve by slug with a real 404 on a bad slug.
172
+ - [ ] Images render (resolved https URLs, no raw `wix:image://`); absent images fall back
173
+ gracefully.
174
+ - [ ] Dates render formatted (no "Invalid Date", no raw ISO strings in copy).
175
+ - [ ] RICH_TEXT renders formatted (no visible HTML tags, no `[object Object]`).
176
+ - [ ] Any 403 surfaced as a permissions step with the dashboard link.
177
+ - [ ] Listing/item/home surfaces are YOUR designs on the tokens; data-layer/hook files
178
+ unedited.
179
+ - [ ] Dashboard link handed to the owner.
@@ -0,0 +1,83 @@
1
+ // One collection as list state. SSR-friendly: pass server-fetched items as `initialItems`
2
+ // (Astro frontmatter / server component) and no client fetch happens for the first page; a
3
+ // SPA passes nothing. Changing filters/sort (by value) refetches; loadMore() appends the
4
+ // next page (skip paging).
5
+ import { useCallback, useEffect, useRef, useState } from "react";
6
+ import { queryItems } from "../../wix/cms/items";
7
+ import type { CmsFilter, CmsItem, CmsSort } from "../../wix/cms/types";
8
+
9
+ export interface UseCollectionOptions {
10
+ filters?: CmsFilter[];
11
+ sort?: CmsSort[];
12
+ /** Page size (default 20). */
13
+ limit?: number;
14
+ /** Reference field keys to inline as full items. */
15
+ include?: string[];
16
+ /** Server-fetched first page — must come from the SAME query (filters/sort/limit/include). */
17
+ initialItems?: CmsItem[];
18
+ /** The server fetch's hasNext. Omitted → inferred (a full first page ⇒ assume more). */
19
+ initialHasNext?: boolean;
20
+ }
21
+
22
+ export interface UseCollection {
23
+ /** null while the first load is in flight — render skeletons, not an empty state. */
24
+ items: CmsItem[] | null;
25
+ hasNext: boolean;
26
+ loadMore: () => void;
27
+ loadingMore: boolean;
28
+ error: string | null;
29
+ }
30
+
31
+ export function useCollection(collectionId: string, options: UseCollectionOptions = {}): UseCollection {
32
+ const { filters, sort, limit = 20, include, initialItems, initialHasNext } = options;
33
+ // Query identity by value — Dates in filters serialize to ISO, so this is stable.
34
+ const key = JSON.stringify([collectionId, filters ?? null, sort ?? null, limit, include ?? null]);
35
+ const initialKey = useRef<string | null>(initialItems ? key : null);
36
+ const [items, setItems] = useState<CmsItem[] | null>(initialItems ?? null);
37
+ const [hasNext, setHasNext] = useState<boolean>(
38
+ initialHasNext ?? (initialItems ? initialItems.length >= limit : false),
39
+ );
40
+ const [loadingMore, setLoadingMore] = useState(false);
41
+ const [error, setError] = useState<string | null>(null);
42
+ const itemsRef = useRef<CmsItem[] | null>(items);
43
+ itemsRef.current = items;
44
+
45
+ useEffect(() => {
46
+ if (initialKey.current === key) return; // the SSR pass already answered this exact query
47
+ initialKey.current = null;
48
+ let alive = true;
49
+ setItems(null);
50
+ setError(null);
51
+ queryItems(collectionId, { filters, sort, limit, include })
52
+ .then((page) => {
53
+ if (!alive) return;
54
+ setItems(page.items);
55
+ setHasNext(page.hasNext);
56
+ })
57
+ .catch((e) => {
58
+ if (!alive) return;
59
+ setItems([]);
60
+ setError(e instanceof Error ? e.message : String(e));
61
+ });
62
+ return () => {
63
+ alive = false;
64
+ };
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ }, [key]);
67
+
68
+ const loadMore = useCallback(() => {
69
+ const current = itemsRef.current;
70
+ if (!current || loadingMore) return;
71
+ setLoadingMore(true);
72
+ queryItems(collectionId, { filters, sort, limit, include, skip: current.length })
73
+ .then((page) => {
74
+ setItems([...(itemsRef.current ?? []), ...page.items]);
75
+ setHasNext(page.hasNext);
76
+ })
77
+ .catch((e) => setError(e instanceof Error ? e.message : String(e)))
78
+ .finally(() => setLoadingMore(false));
79
+ // eslint-disable-next-line react-hooks/exhaustive-deps
80
+ }, [key, loadingMore]);
81
+
82
+ return { items, hasNext, loadMore, loadingMore, error };
83
+ }