@wix/agent-skills 1.17.0 → 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 (246) 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 +14 -3
  9. package/skills/wix-app/references/SITE_PLUGIN.md +12 -0
  10. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +74 -68
  11. package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +79 -0
  12. package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +73 -0
  13. package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +52 -0
  14. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +184 -0
  15. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +12 -11
  16. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +1 -0
  17. package/skills/wix-app/references/editor-react-component/BROWSER-SUPPORT.md +56 -0
  18. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +16 -8
  19. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +19 -1
  20. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +3 -0
  21. package/skills/wix-base44-connector/SKILL.md +133 -44
  22. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +78 -0
  23. package/skills/wix-base44-connector/scripts/utils.js +216 -30
  24. package/skills/wix-headless/entry/skill.md +1 -1
  25. package/skills/wix-headless/references/CAPABILITIES.md +9 -1
  26. package/skills/wix-headless/references/DESIGN.md +1 -0
  27. package/skills/wix-headless/references/DISCOVERY.md +2 -1
  28. package/skills/wix-headless/references/IMAGE_GENERATION.md +1 -0
  29. package/skills/wix-headless/references/SDK_HANDOFF.md +4 -1
  30. package/skills/wix-headless/references/SEED.md +2 -1
  31. package/skills/wix-headless/references/SETUP.md +1 -0
  32. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +2 -2
  33. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +26 -8
  34. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +26 -10
  35. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +8 -8
  36. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +1 -1
  37. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +1 -1
  38. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +254 -0
  39. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +13 -0
  40. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +254 -0
  41. package/skills/wix-headless/references/non-astro.md +1 -1
  42. package/skills/wix-headless-fast/SKILL.md +166 -0
  43. package/skills/wix-headless-fast/entry/skill.md +99 -0
  44. package/skills/wix-headless-fast/install/deploy.mjs +433 -0
  45. package/skills/wix-headless-fast/install/fast-path.mjs +141 -0
  46. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +137 -0
  47. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +137 -0
  48. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +113 -0
  49. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +42 -0
  50. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +123 -0
  51. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +70 -0
  52. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +99 -0
  53. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +76 -0
  54. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +62 -0
  55. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +40 -0
  56. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +99 -0
  57. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +24 -0
  58. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +16156 -0
  59. package/skills/wix-headless-fast/references/blog/seed/SEED.md +72 -0
  60. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +287 -0
  61. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +129 -0
  62. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +143 -0
  63. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +119 -0
  64. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +138 -0
  65. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +54 -0
  66. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +206 -0
  67. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +96 -0
  68. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +70 -0
  69. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +40 -0
  70. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +76 -0
  71. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +22 -0
  72. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +11962 -0
  73. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +61 -0
  74. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +302 -0
  75. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +179 -0
  76. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +83 -0
  77. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +57 -0
  78. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +151 -0
  79. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +75 -0
  80. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +41 -0
  81. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +11262 -0
  82. package/skills/wix-headless-fast/references/cms/seed/SEED.md +103 -0
  83. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +324 -0
  84. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +149 -0
  85. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +66 -0
  86. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +176 -0
  87. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +118 -0
  88. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +117 -0
  89. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +59 -0
  90. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +136 -0
  91. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +128 -0
  92. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +61 -0
  93. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +40 -0
  94. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +12 -0
  95. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +80 -0
  96. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +21 -0
  97. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +11884 -0
  98. package/skills/wix-headless-fast/references/events/seed/SEED.md +86 -0
  99. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +276 -0
  100. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +150 -0
  101. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +317 -0
  102. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +269 -0
  103. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +231 -0
  104. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +135 -0
  105. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +10593 -0
  106. package/skills/wix-headless-fast/references/forms/seed/SEED.md +108 -0
  107. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +320 -0
  108. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +63 -0
  109. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +60 -0
  110. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +155 -0
  111. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +78 -0
  112. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +47 -0
  113. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +66 -0
  114. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +88 -0
  115. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +53 -0
  116. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +122 -0
  117. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +50 -0
  118. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +21 -0
  119. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +42 -0
  120. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +10 -0
  121. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +11 -0
  122. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +10329 -0
  123. package/skills/wix-headless-fast/references/members/seed/SEED.md +39 -0
  124. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +94 -0
  125. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +134 -0
  126. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
  127. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
  128. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +115 -0
  129. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +59 -0
  130. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +39 -0
  131. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +58 -0
  132. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +165 -0
  133. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +55 -0
  134. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
  135. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
  136. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +21 -0
  137. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +29 -0
  138. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +10197 -0
  139. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +78 -0
  140. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +258 -0
  141. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +133 -0
  142. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +58 -0
  143. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +126 -0
  144. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +37 -0
  145. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +39 -0
  146. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +75 -0
  147. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +45 -0
  148. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +30 -0
  149. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
  150. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +40 -0
  151. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +21 -0
  152. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +11226 -0
  153. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +71 -0
  154. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +279 -0
  155. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +165 -0
  156. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +142 -0
  157. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
  158. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
  159. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +155 -0
  160. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +55 -0
  161. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +43 -0
  162. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +177 -0
  163. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +165 -0
  164. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +103 -0
  165. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +254 -0
  166. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +146 -0
  167. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +168 -0
  168. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
  169. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +22 -0
  170. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +12 -0
  171. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +12560 -0
  172. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +81 -0
  173. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +479 -0
  174. package/skills/wix-headless-fast/references/shared/CONTENT.md +22 -0
  175. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +73 -0
  176. package/skills/wix-headless-fast/references/shared/DESIGN.md +26 -0
  177. package/skills/wix-headless-fast/references/shared/app/styles/global.css +52 -0
  178. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +15 -0
  179. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +27 -0
  180. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +24 -0
  181. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +76 -0
  182. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
  183. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +46 -0
  184. package/skills/wix-headless-fast/references/shared/seed/images.mjs +145 -0
  185. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +149 -0
  186. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +26 -0
  187. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +121 -0
  188. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +100 -0
  189. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +130 -0
  190. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +48 -0
  191. package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +66 -0
  192. package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +103 -0
  193. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +48 -0
  194. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +140 -0
  195. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +80 -0
  196. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +101 -0
  197. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +221 -0
  198. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +215 -0
  199. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +109 -0
  200. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +46 -0
  201. package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +56 -0
  202. package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +23 -0
  203. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +12247 -0
  204. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +85 -0
  205. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +415 -0
  206. package/skills/wix-manage/SKILL.md +18 -2
  207. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +141 -0
  208. package/skills/wix-manage/references/google-business-profile/connect-google-business-profile.md +134 -0
  209. package/skills/wix-manage/references/google-business-profile/manage-google-business-profile-locations.md +182 -0
  210. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +3 -0
  211. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +21 -6
  212. package/skills/wix-manage/references/stores/update-product-with-options.md +83 -0
  213. package/skills/wix-vibe-headless/SKILL.md +18 -4
  214. package/skills/wix-vibe-headless/install/deploy.cjs +12 -4
  215. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +2 -1
  216. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +3 -1
  217. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +3 -1
  218. package/skills/wix-vibe-headless/platforms/base44.md +23 -61
  219. package/skills/wix-vibe-headless/platforms/generic.md +6 -3
  220. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +43 -0
  221. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +67 -0
  222. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +128 -0
  223. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +5 -3
  224. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +250 -0
  225. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +12 -5
  226. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +41 -0
  227. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.js +267 -0
  228. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +6 -3
  229. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +470 -0
  230. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +425 -0
  231. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +187 -0
  232. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +238 -0
  233. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +108 -0
  234. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1762 -0
  235. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +13 -0
  236. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +137 -84
  237. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +15 -8
  238. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +37 -0
  239. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +18 -6
  240. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +30 -7
  241. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +46 -10
  242. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +0 -110
  243. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +0 -51
  244. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +0 -49
  245. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +0 -92
  246. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +0 -139
@@ -0,0 +1,86 @@
1
+ # Events — seeding
2
+
3
+ Seed by **running `seed-events.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 Wix Events app if needed, resolves the site currency, and creates
6
+ everything in the one order that works (create DRAFT → tiers → publish — the registration
7
+ type is immutable and publishing is one-way).
8
+
9
+ ```bash
10
+ # from the project root (where wix.config.json lives):
11
+ node <SKILL_ROOT>/references/events/seed/seed-events.mjs plan.json
12
+ ```
13
+
14
+ `plan.json` is plain data — write it from the brief. **Default to 3 events** (the seed shows
15
+ the shape; the owner adds the rest in the dashboard) and make them exercise the UI: mix
16
+ `TICKETING` and `RSVP` (≥1 of each), give a ticketed event 2 tiers, and give every event an
17
+ image (an events page without images looks broken) — the default is an `imagePrompt`
18
+ (AI-generated, ~1 Wix AI credit per image, account-billed): brand-contextual — subject,
19
+ aesthetic/mood, palette, lighting — always ending "no text, no watermarks". At least one image in the set shows the real subject of the business — the actual product/space/service, not abstract decoration. For an asset the user actually
20
+ supplied use `imagePath` (a file on this machine — uploaded to Wix Media) or `imageUrl`
21
+ (their own hosted URL; verify it with `curl -sI` → 200) — never a stock-photo or guessed URL. Images resolve in parallel and never block the
22
+ seed; a failed image leaves that event text-only.
23
+
24
+ ```json
25
+ {
26
+ "events": [
27
+ { "type": "TICKETING", "title": "Summer Synth Festival",
28
+ "shortDescription": "One night of analog sound under the stars.",
29
+ "startDate": "2026-11-07T03:30:00.000Z", "endDate": "2026-11-07T07:00:00.000Z",
30
+ "timeZoneId": "America/Los_Angeles",
31
+ "location": { "name": "The Echo Lot", "type": "VENUE",
32
+ "address": { "addressLine": "120 Harbor St", "city": "Seattle", "subdivision": "US-WA", "postalCode": "98101", "country": "US" } },
33
+ "ticketTiers": [
34
+ { "name": "General Admission", "price": "45.00", "initialLimit": 200 },
35
+ { "name": "Front Row", "price": "85.00", "description": "First two rows.", "initialLimit": 40 }
36
+ ],
37
+ "category": "Concerts", "imageUrl": "https://…" },
38
+ { "type": "TICKETING", "title": "Vinyl Mixing Workshop",
39
+ "shortDescription": "Hands-on turntable session, decks provided.",
40
+ "startDate": "2026-11-14T18:00:00.000Z", "endDate": "2026-11-14T20:00:00.000Z",
41
+ "timeZoneId": "America/Los_Angeles",
42
+ "location": { "name": "Studio B", "type": "VENUE",
43
+ "address": { "addressLine": "9 Pine Ave", "city": "Seattle", "subdivision": "US-WA", "postalCode": "98101", "country": "US" } },
44
+ "ticketTiers": [{ "name": "Workshop Seat", "price": "30.00", "initialLimit": 16 }],
45
+ "category": "Workshops", "imageUrl": "https://…" },
46
+ { "type": "RSVP", "title": "Community Listening Night",
47
+ "shortDescription": "Free open-deck evening — bring a record.",
48
+ "startDate": "2026-11-20T19:00:00.000Z", "endDate": "2026-11-20T22:00:00.000Z",
49
+ "timeZoneId": "America/Los_Angeles",
50
+ "location": { "name": "The Back Room", "type": "VENUE",
51
+ "address": { "addressLine": "120 Harbor St", "city": "Seattle", "subdivision": "US-WA", "postalCode": "98101", "country": "US" } },
52
+ "category": "Community", "imageUrl": "https://…" }
53
+ ]
54
+ }
55
+ ```
56
+
57
+ - `type` — `TICKETING` (paid tiers; buyers pay on Wix's hosted checkout) or `RSVP` (free;
58
+ the built-in name+email form — seed NO form fields). **Immutable after create** — decide
59
+ from the brief, never plan to convert.
60
+ - **Dates are future ISO-8601 UTC** (`…Z`), `endDate` after `startDate`, `timeZoneId` an
61
+ IANA tz. A past event isn't registerable and won't show in the live listing; no date in
62
+ the brief → default ~60–90 days out and say so.
63
+ - `ticketTiers` — TICKETING only, created before publish. `price` is a **decimal STRING**
64
+ (`"45.00"`, never a number), `name` ≤ 30 chars, omit `initialLimit` for unlimited. Tier
65
+ currency is the site currency (resolved automatically).
66
+ - `location` — `{ name, type: "VENUE", address }` (address `subdivision` is ISO-3166-2 like
67
+ `US-WA`, `country` ISO alpha-2), `{ name, type: "ONLINE" }`, or
68
+ `{ locationTbd: true, name }`.
69
+ - `category` — a name; created and assigned for you. Skip when the brief has no grouping.
70
+ - `rsvpResponseType` — `"YES_AND_NO"` to let guests decline (default `"YES_ONLY"`).
71
+
72
+ The result JSON carries a `notes` array — when any event is ticketed it reminds that
73
+ **completing a paid purchase needs a premium plan + a configured payment method** in the
74
+ dashboard. That's an owner step, not a seeding failure; relay it.
75
+
76
+ **Seeding is additive — never delete or overwrite existing content**; ask first if a cleanup
77
+ seems needed.
78
+
79
+ ## Escape hatch — individual functions
80
+ `setupEvents` composes exported steps — `installEventsApp`, `getSiteCurrency`, `createEvent`,
81
+ `createTicketTiers`, `publishEvent`, `createEventCategories`, `assignEventsToCategory`,
82
+ `importImage`, `setEventMainImage`, plus `makeCtx()` — import them only for a partial re-seed.
83
+
84
+ ## Reference
85
+ Unexpected shape or an uncovered operation → read the live Wix API reference; the
86
+ authoritative source recipe is `wix-headless/references/inline-recipes/setup-events.md`.
@@ -0,0 +1,276 @@
1
+ // Events 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/events/seed/seed-events.mjs plan.json
5
+ //
6
+ // It mints its own site token via the Wix CLI, installs the Wix Events app if needed,
7
+ // resolves the site currency, then per event: create DRAFT → (TICKETING) add ticket tiers →
8
+ // publish — the order two one-way constraints force (registration.initialType is immutable
9
+ // after create; publishing is one-way). Then it creates + assigns categories and
10
+ // imports+attaches images. Prints a JSON result to stdout.
11
+ //
12
+ // Plan shape (see SEED.md):
13
+ // { "events": [{ "title", "shortDescription"?, "type": "TICKETING"|"RSVP",
14
+ // "startDate", "endDate" (future ISO-8601 UTC), "timeZoneId",
15
+ // "location" ({name,type:"VENUE",address} | {name,type:"ONLINE"} | {locationTbd:true,name}),
16
+ // "ticketTiers"?: [{ "name" (≤30 chars), "price" (decimal STRING), "description"?, "initialLimit"? }],
17
+ // "category"? (name), "imageUrl"? | "imagePrompt"?, "rsvpResponseType"? }] }
18
+ //
19
+ // Seeding is ADDITIVE — never deletes or overwrites existing content. Unexpected shapes →
20
+ // read the live API reference; authoritative source recipe:
21
+ // wix-headless/references/inline-recipes/setup-events.md.
22
+ import { execFileSync } from "node:child_process";
23
+ import { readFileSync } from "node:fs";
24
+ import { resolveItemImages } from "../../shared/seed/images.mjs";
25
+
26
+ const API = "https://www.wixapis.com";
27
+ const EVENTS_APP_ID = "140603ad-af8d-84a5-2c80-a0f60cb47351";
28
+
29
+ export function makeCtx({ cwd = process.cwd() } = {}) {
30
+ const config = JSON.parse(readFileSync(`${cwd}/wix.config.json`, "utf8"));
31
+ const siteId = config.siteId ?? config.projectId;
32
+ if (!siteId) throw new Error("wix.config.json has no siteId — is this a Wix CLI project?");
33
+ const token = execFileSync("npx", ["@wix/cli@latest", "token", "--site", siteId], {
34
+ encoding: "utf8",
35
+ cwd,
36
+ }).trim();
37
+ if (!token) throw new Error("The Wix CLI returned no token — run `npx @wix/cli@latest login` first.");
38
+ return { token, siteId };
39
+ }
40
+
41
+ async function req(ctx, path, { method = "POST", body } = {}) {
42
+ const res = await fetch(API + path, {
43
+ method,
44
+ headers: {
45
+ Authorization: `Bearer ${ctx.token}`,
46
+ "wix-site-id": ctx.siteId,
47
+ "Content-Type": "application/json",
48
+ },
49
+ body: body ? JSON.stringify(body) : undefined,
50
+ });
51
+ const json = await res.json().catch(() => ({}));
52
+ if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
53
+ return json;
54
+ }
55
+
56
+ // {type:"TICKETING"|"RSVP", …} -> the registration block. TICKETING carries a tickets{}
57
+ // config; RSVP carries rsvp{responseType} and seeds NO form fields (name+email is built-in).
58
+ // initialType is IMMUTABLE after create — set from the plan, never plan to convert.
59
+ function buildRegistration(ev) {
60
+ if (ev.type === "TICKETING") {
61
+ return {
62
+ initialType: "TICKETING",
63
+ tickets: {
64
+ ticketLimitPerOrder: ev.ticketLimitPerOrder ?? 8,
65
+ currency: ev.currency ?? "USD", // setupEvents threads the site currency; USD is the last resort
66
+ reservationDurationInMinutes: ev.reservationDurationInMinutes ?? 20,
67
+ },
68
+ };
69
+ }
70
+ return {
71
+ initialType: "RSVP",
72
+ rsvp: { responseType: ev.rsvpResponseType ?? "YES_ONLY" }, // "YES_ONLY" | "YES_AND_NO"
73
+ };
74
+ }
75
+
76
+ // ---- operations ----------------------------------------------------------------------------------
77
+
78
+ // Idempotent: re-installing an already-installed app returns 200.
79
+ // docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
80
+ export async function installEventsApp(ctx) {
81
+ try {
82
+ await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
83
+ tenant: { tenantType: "SITE", id: ctx.siteId },
84
+ appInstance: { appDefId: EVENTS_APP_ID, enabled: true },
85
+ } });
86
+ } catch {
87
+ /* already installed is fine */
88
+ }
89
+ }
90
+
91
+ // The ticket-definitions API REQUIRES currency and uses whatever you pass verbatim (it does
92
+ // NOT fall back to the site currency) — resolve it once, or a non-USD site gets mis-priced.
93
+ // docs: https://dev.wix.com/docs/api-reference/business-management/site-properties/properties/get-site-properties.md
94
+ export async function getSiteCurrency(ctx) {
95
+ try {
96
+ const r = await req(ctx, "/site-properties/v4/properties", { method: "GET" });
97
+ return r?.properties?.paymentCurrency || "USD";
98
+ } catch {
99
+ return "USD";
100
+ }
101
+ }
102
+
103
+ /**
104
+ * STEP 1 — create ONE event as a draft (no bulk endpoint; loop for multiple). Dates MUST be
105
+ * in the future — a past event isn't registerable and won't show in the live listing.
106
+ * Returns { id, slug } — id feeds the tier/publish steps; slug is the URL identifier.
107
+ * docs: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/create-event.md
108
+ */
109
+ export async function createEvent(ctx, ev) {
110
+ const body = {
111
+ draft: true,
112
+ event: {
113
+ title: ev.title,
114
+ shortDescription: ev.shortDescription,
115
+ location: ev.location,
116
+ dateAndTimeSettings: {
117
+ startDate: ev.startDate,
118
+ endDate: ev.endDate,
119
+ timeZoneId: ev.timeZoneId,
120
+ showTimeZone: ev.showTimeZone ?? true,
121
+ },
122
+ registration: buildRegistration(ev),
123
+ },
124
+ fields: ["DETAILS", "TEXTS", "REGISTRATION", "URLS"],
125
+ };
126
+ const r = await req(ctx, "/events/v3/events", { body });
127
+ return { id: r.event?.id, slug: r.event?.slug };
128
+ }
129
+
130
+ /**
131
+ * STEP 2 — ticket tiers for a TICKETING event (skip for RSVP). Must run BEFORE publish —
132
+ * publishing a ticketed event with no tiers ships an event with nothing to buy, and there is
133
+ * no un-publish. price is a decimal STRING ("65.00", never a number); name ≤ 30 chars; omit
134
+ * initialLimit for unlimited. Tiers are independent — fired as one parallel batch.
135
+ * docs: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/ticket-definitions-v3/create-ticket-definition.md
136
+ */
137
+ export async function createTicketTiers(ctx, eventId, tiers) {
138
+ return Promise.all(tiers.map(async (t) => {
139
+ const body = {
140
+ ticketDefinition: {
141
+ eventId,
142
+ name: t.name,
143
+ description: t.description,
144
+ ...(t.initialLimit != null ? { initialLimit: t.initialLimit } : {}),
145
+ pricingMethod: { fixedPrice: { value: String(t.price), currency: t.currency ?? "USD" } },
146
+ feeType: t.feeType ?? "FEE_INCLUDED",
147
+ },
148
+ fields: ["SALES_DETAILS"],
149
+ };
150
+ const r = await req(ctx, "/events/v3/ticket-definitions", { body });
151
+ return { id: r.ticketDefinition?.id };
152
+ }));
153
+ }
154
+
155
+ // STEP 3 — publish (one-way; for TICKETING only after its tiers exist).
156
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/publish-draft-event.md
157
+ export async function publishEvent(ctx, eventId) {
158
+ return req(ctx, `/events/v3/events/${eventId}/publish`, { body: {} });
159
+ }
160
+
161
+ // STEP 4 (optional) — group events by a format/track. Categories are the v1 API (NOT v3).
162
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/categories/create-category.md
163
+ export async function createEventCategories(ctx, names) {
164
+ const out = [];
165
+ for (const name of names) {
166
+ const r = await req(ctx, "/events/v1/categories", { body: { category: { name } } });
167
+ out.push({ id: r.category?.id, name });
168
+ }
169
+ return out;
170
+ }
171
+
172
+ // Assign events to a category. Path is /{categoryId}/events (NOT /assign); body key is
173
+ // `eventId` — an ARRAY despite the singular name.
174
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/categories/assign-events.md
175
+ export async function assignEventsToCategory(ctx, categoryId, eventIds) {
176
+ return req(ctx, `/events/v1/categories/${categoryId}/events`, { body: { eventId: eventIds } });
177
+ }
178
+
179
+ // Events binds mainImage by Wix Media file ID — an external url must be imported first
180
+ // (a raw url as the id stores 200 but renders nothing); a plan `imagePrompt` is generated
181
+ // (Wix AI, 1 credit) then imported. Both live in the shared util (parallel, resilient,
182
+ // never blocks the seed).
183
+ export { importImage } from "../../shared/seed/images.mjs";
184
+
185
+ // mainImage is an Image OBJECT; height/width are REQUIRED or it won't render. Events V3 uses
186
+ // NO revision — partial PATCH keyed by event.id. Works before OR after publish.
187
+ // docs: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/update-event.md
188
+ export async function setEventMainImage(ctx, it) {
189
+ return req(ctx, `/events/v3/events/${it.eventId}`, {
190
+ method: "PATCH",
191
+ body: {
192
+ event: {
193
+ id: it.eventId,
194
+ mainImage: { id: it.id, url: it.url, height: it.height ?? 1024, width: it.width ?? 1024, altText: it.altText },
195
+ },
196
+ fields: ["DETAILS"], // mainImage reads back only under DETAILS
197
+ },
198
+ });
199
+ }
200
+
201
+ /**
202
+ * ONE-CALL seed: install → site currency → per event create DRAFT → tiers → publish →
203
+ * categories → images, ids threaded in memory. The default path.
204
+ */
205
+ export async function setupEvents(ctx, { events = [] } = {}) {
206
+ await installEventsApp(ctx);
207
+ const siteCurrency = await getSiteCurrency(ctx);
208
+
209
+ const created = [];
210
+ for (const ev of events) {
211
+ const e = await createEvent(ctx, { ...ev, currency: ev.currency ?? siteCurrency });
212
+ if (!e.id) throw new Error(`Event "${ev.title}" was not created — no id returned.`);
213
+ const tiers = ev.type === "TICKETING" && ev.ticketTiers?.length
214
+ ? await createTicketTiers(ctx, e.id, ev.ticketTiers.map((t) => ({ ...t, currency: t.currency ?? siteCurrency })))
215
+ : [];
216
+ await publishEvent(ctx, e.id);
217
+ created.push({ ...e, category: ev.category, imageUrl: ev.imageUrl, imagePrompt: ev.imagePrompt, ticketCount: tiers.length });
218
+ }
219
+
220
+ const names = [...new Set(created.map((e) => e.category).filter(Boolean))];
221
+ const categories = names.length ? await createEventCategories(ctx, names) : [];
222
+ for (const c of categories) {
223
+ const eventIds = created.filter((e) => e.category === c.name).map((e) => e.id);
224
+ if (eventIds.length) await assignEventsToCategory(ctx, c.id, eventIds);
225
+ }
226
+
227
+ // Pass 2 — images: resolve (import by url / generate by prompt) in one parallel wave, then
228
+ // attach. Failures leave the event text-only; the seed's exit never depends on images.
229
+ const files = await resolveItemImages(ctx, created.map((e) => ({
230
+ url: e.imageUrl,
231
+ path: e.imagePath,
232
+ prompt: e.imagePrompt,
233
+ displayName: `${e.slug || "event"}.png`,
234
+ })));
235
+ let imagesAttached = 0;
236
+ for (let i = 0; i < created.length; i++) {
237
+ const e = created[i];
238
+ if (!files[i]) continue;
239
+ try {
240
+ await setEventMainImage(ctx, { eventId: e.id, id: files[i].id, url: files[i].url, height: 1024, width: 1024, altText: e.slug });
241
+ imagesAttached++;
242
+ } catch {
243
+ /* never block on image failure — the event stays text-only */
244
+ }
245
+ }
246
+
247
+ return {
248
+ events: created.map((e) => ({ id: e.id, slug: e.slug, ticketCount: e.ticketCount, category: e.category ?? null })),
249
+ categories,
250
+ imagesAttached,
251
+ // Completing a PAID purchase needs a premium plan + a configured payment method in the
252
+ // dashboard — not a seeding failure; surface it to the owner. Free/RSVP need neither.
253
+ notes: created.some((e) => e.ticketCount > 0)
254
+ ? ["Paid tickets require a premium plan + a configured payment method in the dashboard to complete a purchase."]
255
+ : [],
256
+ };
257
+ }
258
+
259
+ // ---- CLI entry ----------------------------------------------------------------------------------
260
+
261
+ const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
262
+ if (invokedDirectly) {
263
+ const planPath = process.argv[2];
264
+ if (!planPath) {
265
+ console.error("usage: node seed-events.mjs <plan.json> (run from the project root)");
266
+ process.exit(1);
267
+ }
268
+ const plan = JSON.parse(readFileSync(planPath, "utf8"));
269
+ const ctx = makeCtx();
270
+ setupEvents(ctx, plan)
271
+ .then((result) => console.log(JSON.stringify(result, null, 2)))
272
+ .catch((e) => {
273
+ console.error(e.message);
274
+ process.exit(1);
275
+ });
276
+ }
@@ -0,0 +1,150 @@
1
+ # Forms — playbook
2
+
3
+ The machinery ships as files — the schema read flattened into render-ready fields, upload +
4
+ submit, schema-driven validation, and server violations mapped onto controls, correct
5
+ end-to-end. A form is **schema-driven**: the owner picks the fields in their dashboard, so
6
+ every form has a different field set and no "contact form" component could ship for it.
7
+ **You render the fields; you never write the reading, validating or submitting.**
8
+
9
+ ## The file map (deployed into `src/`)
10
+
11
+ **Don't read the shipped files** — this table and the contracts below are everything you need.
12
+ Open a shipped file's source only on a real fallback (runtime error / uncovered field kind).
13
+
14
+ | file | what it is |
15
+ |---|---|
16
+ | `wix/config.ts` · `wix/sdk.ts` · `wix/media.ts` · `wix/money.ts` | shared auth seam + helpers (deploy configures; nothing to set) |
17
+ | `wix/forms/types.ts` | the DTOs (`FormDto`, `FormFieldDto`, `FormValues`, `FormErrors`) — contracts below |
18
+ | `wix/forms/forms.ts` | `getForm`, `listForms` — the raw schema flattened into `FormFieldDto[]` |
19
+ | `wix/forms/submissions.ts` | `uploadFiles`, `toSubmissionValues`, `createSubmission`, `submissionErrors`, `normalizePhone` |
20
+ | `hooks/forms/useWixForm.ts` | the whole form as state — contract below |
21
+ | `styles/global.css` | the design system: Tailwind v4 + the `@theme` token block (shared across verticals) |
22
+
23
+ There are **no shipped components and no shipped pages** — every control is yours.
24
+
25
+ ## What you build — the design job
26
+
27
+ Read the seed plan first: its forms and their fields are what the page renders.
28
+
29
+ 1. **A form surface per seeded form** — your layout, your labels' typography, your error
30
+ styling, mapping `form.fields` to controls. **Never name a field in code**: the owner can
31
+ rename, reorder, add or require one from their dashboard, and the page must follow with no
32
+ code change. That is the entire point of this vertical.
33
+ 2. **A success state** — the resolved `submit()` IS the confirmation (a visitor cannot read
34
+ submissions back). Show a thank-you; never a "check your submissions" link.
35
+ 3. **The home page and wherever the form lives** — hero, copy, the form section.
36
+
37
+ Plus the **theme** (`@theme` block, one edit) and the **chrome** (`SiteLayout`, one pass).
38
+
39
+ ### The contracts your components consume
40
+
41
+ ```ts
42
+ // FormDto — one form, ready to render
43
+ // { id, name, fields: FormFieldDto[], submitText } // submitText "" ⇒ write your own
44
+
45
+ // FormFieldDto — one visible input, flattened (settings nest 2 levels deep upstream)
46
+ // { target, // the input's name, the key in values, the root of error keys
47
+ // label, // never empty; rich-content labels already flattened to text
48
+ // control, // text|textarea|number|rating|email|phone|url|date|time|datetime
49
+ // // |select|radio|checkbox|checkboxGroup|tags|address|file|signature
50
+ // // |payment|appointment|unknown
51
+ // required, placeholder?, description?,
52
+ // defaultValue, // "" | [] | {} | the owner's prefill — already the right SHAPE
53
+ // choices: [{ value, label }], // select/radio/checkboxGroup/tags — else []
54
+ // addressParts: [{ sub, label, required }], // address — else []
55
+ // validation: { format?, minLength?, maxLength?, pattern?, minimum?, maximum?,
56
+ // fileLimit?, minItems?, maxItems? },
57
+ // phoneCountry?, // phone only
58
+ // identifier, // TEXT_AREA, IMAGE_CHOICE, CONTACTS_EMAIL … when control isn't enough
59
+ // inputType, componentType }
60
+ ```
61
+
62
+ ```ts
63
+ // useWixForm(formId, { initialForm? })
64
+ // → { form, // FormDto | null — null while loading; render a skeleton, not an empty form
65
+ // values, // target → value; arrays for multi-choice/files, objects for an address
66
+ // setValues, // setValues(v => ({ ...v, [target]: next }))
67
+ // bind, // spread onto a text-ish control: <input {...bind(f.target)} />
68
+ // submit, // onSubmit handler; resolves TRUE when the submission was created
69
+ // validate, // validate(target) | validate("addr/city") | validate() for the whole form
70
+ // errors, // target (or target/sub) → visitor-facing message; errors[FORM_ERROR] is form-level
71
+ // loading } // loading the schema, or submitting
72
+ ```
73
+
74
+ `bind` covers input / textarea / select. A **checkbox or radio group** carries `checked`
75
+ instead of `value`, and a **file input cannot be controlled at all** — wire those by hand,
76
+ keeping the same `name`, `onBlur: () => validate(target)` and `aria-describedby` contract.
77
+
78
+ ### Which control each field kind wants
79
+
80
+ | `control` | render |
81
+ |---|---|
82
+ | `text` `email` `url` `phone` | `<input>` with the matching `type` — spread `bind` |
83
+ | `textarea` | `<textarea>` — spread `bind` |
84
+ | `number` `rating` | `<input type="number">`, or your own star control writing a number |
85
+ | `date` `time` `datetime` | `<input type="date" / "time" / "datetime-local">` |
86
+ | `select` | `<select>` over `choices` — spread `bind` |
87
+ | `radio` | one `<input type="radio">` per choice, all sharing `name={f.target}` |
88
+ | `checkbox` | a single `<input type="checkbox">`; its value is a **boolean** |
89
+ | `checkboxGroup` `tags` | one checkbox per choice; the value is an **array** of chosen values |
90
+ | `address` | one control per `addressParts` entry; the value is an **object** keyed by `sub`, and its error keys are `target/sub` |
91
+ | `file` `signature` | `<input type="file">` (uncontrolled) — put the `File` objects in `values[target]`; the hook uploads them on submit |
92
+ | `payment` `appointment` `unknown` | out of scope for a plain form — a payment field needs the payment flow, an appointment field needs the `bookings` vertical. Render a disabled note rather than an input that submits the wrong thing |
93
+
94
+ ### Wiring — Astro (default)
95
+
96
+ Fetch in frontmatter so the first paint has the schema, and hand it to the island:
97
+
98
+ ```astro
99
+ ---
100
+ import { getForm } from "@/wix/forms/forms";
101
+ const form = await getForm(FORM_ID); // FORM_ID from the seed plan
102
+ ---
103
+ <ContactForm client:load initialForm={form} />
104
+ ```
105
+
106
+ The island calls `useWixForm(form.id, { initialForm })` — no second fetch, no loading flash.
107
+
108
+ ### Wiring — React SPA (Vite etc.)
109
+
110
+ `useWixForm(FORM_ID)` with no `initialForm`; render a skeleton while `form` is null.
111
+
112
+ ## Hard rules
113
+
114
+ - **Never name a field in code.** Map `form.fields`. A page with `values.email` hardcoded
115
+ breaks the moment the owner renames or removes that field — and the owner editing fields
116
+ without a code change is what this vertical is for.
117
+ - **Never build a form without reading the schema.** A hand-built `<form>` posting to Wix Data
118
+ or an email service silently drops real enquiries and loses the dashboard form builder,
119
+ spam protection, notifications and CRM contact mapping.
120
+ - **The visitor token is enough.** Both the schema read and the submission return 200 on an
121
+ anonymous visitor, even though the spec lists them under owner scopes. Never add a backend,
122
+ a connector token, or `auth.elevate` to make a form work.
123
+ - **Submissions are write-only from a visitor.** Reading them back genuinely 403s. If the app
124
+ must LIST what visitors submitted, that is the `cms` vertical.
125
+ - **All three success statuses are a success** — `CONFIRMED`, `PENDING`, `PAYMENT_WAITING`
126
+ all mean the submission exists. Showing an error instead invites a second submit, and the
127
+ owner gets duplicates for an entry they already have.
128
+ - **Never mock, fail loudly.** A form that cannot load is a setup problem — surface it; never
129
+ fall back to a hand-built form.
130
+
131
+ ## Point the user to their dashboard
132
+
133
+ The owner edits fields, sees submissions, and sets notifications at
134
+ `https://manage.wix.com/dashboard/<siteId>/form/forms`. Say so when you hand the site over —
135
+ the whole value of this vertical is that their edits land on the site with no code change.
136
+
137
+ ## Seeding
138
+
139
+ `seed/SEED.md` is the contract: a plain-data plan in, created forms out. Read it when drafting
140
+ the plan; the seed writes the form ids your pages import.
141
+
142
+ **⚠️ Build the UI only after the seed has run** — the form id comes from it, and the field set
143
+ you are rendering is the one it created.
144
+
145
+ ## Verify (before declaring done)
146
+
147
+ - The rendered controls match the seeded fields — same labels, same order, same required marks.
148
+ - A submit with an empty required field shows YOUR inline message, and focus moves to it.
149
+ - A valid submit resolves and shows the thank-you; the entry appears in the owner's dashboard.
150
+ - Renaming a field in the dashboard changes the page on reload, with no code change.