@wix/agent-skills 1.13.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +4 -1
  2. package/package.json +1 -1
  3. package/skills/README.md +23 -0
  4. package/skills/wix-app/SKILL.md +10 -2
  5. package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +326 -0
  6. package/skills/wix-app/references/CODE_QUALITY.md +1 -0
  7. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +124 -115
  8. package/skills/wix-app/references/DASHBOARD_PAGE.md +3 -0
  9. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +23 -9
  10. package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
  11. package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
  12. package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
  13. package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
  14. package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
  15. package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
  16. package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
  17. package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
  18. package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
  19. package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
  20. package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
  21. package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
  22. package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
  23. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
  24. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
  25. package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
  26. package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
  27. package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
  28. package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
  29. package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
  30. package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
  31. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
  32. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
  33. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
  34. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +17 -105
  35. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
  36. package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
  37. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +15 -15
  38. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
  39. package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
  40. package/skills/wix-auth/SKILL.md +12 -0
  41. package/skills/wix-auth/references/device-flow.md +140 -0
  42. package/skills/wix-docs/SKILL.md +188 -0
  43. package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
  44. package/skills/wix-docs/references/EXTRACTING.md +120 -0
  45. package/skills/wix-headless/SKILL.md +84 -130
  46. package/skills/wix-headless/entry/bootstrap.mjs +93 -0
  47. package/skills/wix-headless/entry/skill.md +78 -0
  48. package/skills/wix-headless/references/AI_FEATURES.md +178 -0
  49. package/skills/wix-headless/references/CAPABILITIES.md +84 -0
  50. package/skills/wix-headless/references/DISCOVERY.md +34 -56
  51. package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
  52. package/skills/wix-headless/references/FEEDBACK.md +118 -0
  53. package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
  54. package/skills/wix-headless/references/SDK_HANDOFF.md +97 -0
  55. package/skills/wix-headless/references/SEED.md +44 -188
  56. package/skills/wix-headless/references/SETUP.md +32 -103
  57. package/skills/wix-headless/references/astro.md +98 -0
  58. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
  59. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
  60. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
  61. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
  62. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
  63. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
  64. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
  65. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
  66. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
  67. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
  70. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +173 -0
  71. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
  72. package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
  73. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +228 -0
  74. package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
  75. package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
  76. package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
  77. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +176 -0
  78. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +153 -0
  79. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
  80. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +161 -0
  81. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +117 -0
  82. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
  83. package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
  84. package/skills/wix-headless/references/managed/CONNECT.md +74 -0
  85. package/skills/wix-headless/references/managed/CREATE.md +130 -0
  86. package/skills/wix-headless/references/managed/DEPLOYMENT.md +57 -0
  87. package/skills/wix-headless/references/non-astro.md +59 -0
  88. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
  89. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +7 -0
  90. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
  91. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +63 -0
  92. package/skills/wix-manage/SKILL.md +24 -1
  93. package/skills/wix-manage/references/analytics/query-site-analytics.md +241 -0
  94. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
  95. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +265 -0
  96. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +436 -0
  97. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +209 -0
  98. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
  99. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +51 -0
  100. package/skills/wix-vibe-headless/SKILL.md +136 -0
  101. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
  102. package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
  103. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +153 -0
  104. package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
  105. package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +215 -0
  106. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
  107. package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
  108. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
  109. package/skills/wix-vibe-headless/references/events/wix-events-browse.js +135 -0
  110. package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
  111. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
  112. package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
  113. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
  114. package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +194 -0
  115. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
  116. package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
  117. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
  118. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
  119. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
  120. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
  121. package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
  122. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +155 -0
  123. package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
  124. package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +142 -0
  125. package/skills/wix-headless/references/BUILD-astro.md +0 -244
  126. package/skills/wix-headless/references/BUILD-own-build.md +0 -167
  127. package/skills/wix-headless/references/BUILD.md +0 -105
  128. package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
  129. package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
  130. package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
  131. package/skills/wix-headless/references/PLAN-connect.md +0 -19
  132. package/skills/wix-headless/references/PLAN-create.md +0 -17
  133. package/skills/wix-headless/references/PLAN.md +0 -92
  134. package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
  135. package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
  136. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
  137. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
  138. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
  139. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
  140. package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
  141. package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
  142. package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
  143. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
  144. package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
  145. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
  146. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
  147. package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
  148. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
  149. package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
  150. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
  151. package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
  152. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
  153. package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
  154. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
  155. package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
  156. package/skills/wix-headless/references/astro/templates/Footer.astro +0 -27
  157. package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
  158. package/skills/wix-headless/references/astro/templates/Navigation.astro +0 -38
  159. package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
  160. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
  161. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
  162. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
  163. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
  164. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
  165. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
  166. package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
  167. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
  168. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
  169. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
  170. package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
  171. package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
  172. package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
  173. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
  174. package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
  175. package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
  176. package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
  177. package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
  178. package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
  179. package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
  180. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
  181. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
  182. package/skills/wix-headless/references/astro/templates/global.css +0 -288
  183. package/skills/wix-headless/references/astro/templates/index.astro +0 -56
  184. package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
  185. package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
  186. package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
  187. package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
  188. package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
  189. package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
  190. package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
  191. package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
  192. package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
  193. package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
  194. package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
  195. package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
  196. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
  197. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
  198. package/skills/wix-headless/references/bookings/FLOW.md +0 -246
  199. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
  200. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
  201. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
  202. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
  203. package/skills/wix-headless/references/commands/known-apps.json +0 -6
  204. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
  205. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
  206. package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
  207. package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
  208. package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
  209. package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
  210. package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
  211. package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
  212. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
  213. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
  214. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
  215. package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
  216. package/skills/wix-headless/references/seed-recipes.md +0 -49
  217. package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
  218. package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
  219. package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
  220. package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
  221. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
  222. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
  223. package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
  224. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
  225. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
  226. package/skills/wix-headless/references/shared/STYLING.md +0 -141
  227. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
  228. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
  229. package/skills/wix-headless/references/verticals/_schema.json +0 -74
  230. package/skills/wix-headless/references/verticals/_schema.md +0 -95
  231. package/skills/wix-headless/references/verticals/blog.md +0 -31
  232. package/skills/wix-headless/references/verticals/bookings.md +0 -41
  233. package/skills/wix-headless/references/verticals/cms.md +0 -30
  234. package/skills/wix-headless/references/verticals/ecom.md +0 -25
  235. package/skills/wix-headless/references/verticals/forms.md +0 -26
  236. package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
  237. package/skills/wix-headless/references/verticals/stores.md +0 -33
  238. package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
  239. package/skills/wix-headless/scripts/compose.mjs +0 -525
  240. package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
  241. package/skills/wix-headless/scripts/flatten.sh +0 -61
  242. package/skills/wix-headless/scripts/generate-images.mjs +0 -242
  243. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -148
  244. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
  245. package/skills/wix-headless/scripts/scaffold.sh +0 -139
  246. package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
  247. package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
  248. package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
  249. package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
  250. package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
@@ -1,132 +0,0 @@
1
- # Phase 3 Components-CSS — Ecom
2
-
3
- **This stylesheet is pre-copied from the skill template by the orchestrator** (build-wave pre-batch, BUILD-astro.md § "Step 4.5") — there is no `components-css` subagent to dispatch. This file documents the CSS for reference so the ecom `components` scope (in the merged build agent) knows the class-name surface it targets.
4
-
5
- ## What this scope owns
6
-
7
- Exactly one file:
8
-
9
- - `src/styles/components-ecom.css` — scoped CSS for cart/checkout: cart-summary panel, cart-total row, checkout button (with `:disabled` and `:hover` states), empty state, cart-item line layout (image, name, qty controls, prices, modifiers, unavailable state, remove button), discount/applied-discount rows, and the cart-badge nav element. Imported by `Layout.astro` (the designer foundation sets up the import).
10
-
11
- ## What this scope does NOT own
12
-
13
- - Any `.tsx` or `.astro` file. Those are the `components` sibling scope (`./CART_WIRING.md`).
14
- - `src/styles/global.css` — owned by the designer foundation. **You read it (to audit for ecom-class leaks) but never write it.**
15
- - `src/styles/components-stores.css`, `src/styles/components-gift-cards.css` — owned by other packs' `components-css` (or `components`) scopes.
16
- - `src/utils/discounts.ts` — pre-copied by the orchestrator before this dispatch; not your concern.
17
-
18
- ## Reading set
19
-
20
- You only need:
21
-
22
- 1. **`<SKILL_ROOT>/references/astro/templates/ecom/components-ecom.css`** — the canonical template. Read it once.
23
- 2. **`<SKILL_ROOT>/references/shared/STYLING.md`** — the styling-contract conventions (how to use `@apply`, the `@theme` token utilities, the no-default-Tailwind-colors rule, and the global-vs-scoped CSS ownership boundary).
24
- 3. **`<SKILL_ROOT>/references/shared/RETURN_CONTRACT.md`** — the return JSON shape.
25
- 4. **`src/styles/global.css`** in the project — read to audit for ecom-class leaks (see § "Global-CSS leak audit" below).
26
- 5. **Design tokens (on disk)** — read the design tokens (the DESIGN.md vocabulary — `colors`/`typography`/`rounded`/`containers`; spacing is Tailwind's numeric scale, not a token) from `.wix/design-tokens.css` (gate-verified present before the wave). They are NOT inlined in your prompt.
27
-
28
- You do NOT need to read `INSTRUCTIONS.md`, `CART_WIRING.md`, the TSX templates, the `discounts.ts` util, or any other reference. Skipping those reads is the point of the split.
29
-
30
- ## Implementation
31
-
32
- ### 1. Read the template
33
-
34
- ```
35
- <SKILL_ROOT>/references/astro/templates/ecom/components-ecom.css
36
- ```
37
-
38
- This is the canonical scoped CSS for the ecom pack. Adapt sizing/spacing to the brand's aesthetic — use the design tokens from your prompt (`--color-bark`, `--color-cream`, `--radius-md`, `--font-display`, etc.); spacing uses Tailwind's numeric scale (`gap-4`, `py-24`), not a token. **Do not rename the class names or state modifiers** — they must match the contract keys the TSX components reference.
39
-
40
- ### 2. The two `@reference` directives are mandatory
41
-
42
- The first two non-comment lines of `components-ecom.css` MUST be:
43
-
44
- ```css
45
- @reference "tailwindcss";
46
- @reference "./global.css";
47
- ```
48
-
49
- Without these, Tailwind v4 fails the build with `"Cannot apply unknown utility class"` on any `@apply` rule that uses a utility like `size-6` or `gap-4`. The template ships them; do not remove.
50
-
51
- ### 3. Class ownership
52
-
53
- Classes defined in `components-ecom.css` (this is the **single source of truth** — the designer's `global.css` does NOT publish these):
54
-
55
- - **`.cart-summary` / `.cart-total` / `.cart-empty`** — the `/cart` page summary panel (sticky on desktop), total row, and empty-state. The `.cart-empty .checkout-btn` rule scopes the empty-state CTA to inline-flex with a max-width so it doesn't render full-width.
56
- - **`.checkout-btn`** — primary checkout button, with `:disabled` and `:hover:not(:disabled)` states. **Composes from `.btn-primary`** (which IS a designer-owned plain-CSS rule in `global.css`). Do **NOT** use `@apply btn-primary` here — Tailwind v4 only `@apply`s utilities declared with `@utility` (which `btn` is in `global.css`), not plain custom classes. The build fails with `Cannot apply unknown utility class 'btn-primary'` if you try. Use `composes` via flat property repetition or extend manually.
57
- - **`.cart-item-*`** — full row primitives: `cart-item-qty`, `qty-btn`, `qty-value`, `cart-item-unavailable`, `cart-item-actions`, `cart-item-prices`, `cart-item-full-price`, `cart-item-unit-price`, `cart-item-line-total`, `cart-item-remove`, `cart-item-image-link`, `cart-item-name-link`, `cart-item-option`, `cart-item-modifiers`. CartView.tsx references these by name; renaming breaks the page.
58
- - **`.cart-discount` / `.cart-discount-name` / `.cart-discount-amount`** — the discount row in the summary.
59
- - **`.cart-applied-discounts` / `.cart-applied-discounts-name`** — the name-only applied-discounts row (line-item automatic discounts).
60
- - **`.cart-badge` / `.cart-badge-count`** — the nav badge (mounted in `Navigation.astro` via the ecom `pages` scope's CartBadge).
61
-
62
- Classes you do NOT own:
63
-
64
- - `.btn`, `.btn-primary`, `.btn-secondary` — designer's `global.css` (`.btn` is a Tailwind v4 `@utility`).
65
- - Anything in `components-stores.css` (option pills, product card, product grid, offer callout) — owned by stores pack.
66
- - Anything in `components-gift-cards.css` — owned by gift-cards pack.
67
-
68
- ### 4. Global-CSS leak audit
69
-
70
- Before writing your file, **read `src/styles/global.css`** and grep for any class your scope owns. Ecom-specific rules sometimes leak into the designer's foundation:
71
-
72
- - Any `.cart-summary`, `.cart-total`, `.cart-empty`, `.checkout-btn` rule.
73
- - Any `.cart-item-*` rule.
74
- - Any `.cart-badge` rule.
75
- - Any `.cart-discount` / `.cart-applied-discounts` rule.
76
-
77
- If you find a leak, do NOT edit `global.css` (the designer owns it). Instead:
78
-
79
- 1. Override the rule with the complete declaration in `components-ecom.css` (later imports win in CSS cascade because Layout.astro imports `components-ecom.css` AFTER `global.css`).
80
- 2. Add `{code: "GLOBAL_CSS_LEAK", class: "<name>", file: "src/styles/global.css"}` to your return JSON's `errors` array — non-fatal but tracked.
81
-
82
- ### 5. Write the file
83
-
84
- Write the adapted CSS to `src/styles/components-ecom.css`. The orchestrator's post-Phase-3 manifest check verifies the file exists.
85
-
86
- ## Coordination: design tokens
87
-
88
- Read the design tokens from `.wix/design-tokens.css` (on disk, gate-verified present before the wave) — they are NOT inlined in your prompt.
89
-
90
- ## Return format
91
-
92
- ```json
93
- {
94
- "status": "complete",
95
- "phase": "ecom-components-css",
96
- "scope": "components-css",
97
- "summary": "Wrote components-ecom.css from template, adapted to brand tokens",
98
- "data": {
99
- "scopedCssFile": "src/styles/components-ecom.css",
100
- "scopedCssRules": 22,
101
- "scopedContractClassesDefined": [
102
- "cart-summary", "cart-total", "cart-empty", "checkout-btn",
103
- "cart-item-qty", "qty-btn", "qty-value", "cart-item-unavailable",
104
- "cart-item-actions", "cart-item-prices", "cart-item-full-price",
105
- "cart-item-unit-price", "cart-item-line-total", "cart-item-remove",
106
- "cart-item-image-link", "cart-item-name-link",
107
- "cart-item-option", "cart-item-modifiers",
108
- "cart-discount", "cart-discount-name", "cart-discount-amount",
109
- "cart-applied-discounts", "cart-applied-discounts-name",
110
- "cart-badge", "cart-badge-count"
111
- ]
112
- },
113
- "files": [
114
- "src/styles/components-ecom.css"
115
- ],
116
- "errors": []
117
- }
118
- ```
119
-
120
- If a leak was found and overridden, include `errors: [{code: "GLOBAL_CSS_LEAK", class: "<name>", file: "src/styles/global.css"}]`.
121
-
122
- ## Anti-patterns
123
-
124
- | WRONG | CORRECT |
125
- |-------|---------|
126
- | Read `INSTRUCTIONS.md`, `CART_WIRING.md`, or any `.tsx` template | Not needed — this scope only writes CSS |
127
- | Edit `src/styles/global.css` to fix a leak | Override in `components-ecom.css`; report the leak in `errors` |
128
- | Use default Tailwind colors (`bg-green-50`, `text-red-600`) | Brand `@theme` utilities (`bg-bark`, `text-cream`) or `var(--color-...)` |
129
- | `@apply btn-primary` on `.checkout-btn` | Tailwind v4 only `@apply`s `@utility` declarations, not plain CSS rules — build fails. Either repeat the properties manually or compose via `composes` |
130
- | Rename a class because the brand is "more elegant" with kebab variants | Class names are contract keys; renaming breaks every TSX import that references them |
131
- | Skip the leak audit | Skipping ships double-defined rules; the audit is < 5 s and prevents downstream visual regressions |
132
- | Drop the `@reference` directives | Tailwind v4 needs both — without them, `@apply size-6` and similar fail at build |
@@ -1,463 +0,0 @@
1
- # Recipe: Contact / Lead / Signup Form
2
-
3
- Build a complete form feature using `@wix/forms` — server-side schema fetching + client-side submission.
4
-
5
- > **Critical Rules — Read Before Starting**
6
- > 1. **Style migration mandatory** — when replacing `.astro` placeholder with a React island, copy the `<style is:global>` block to the page file or all form styles vanish (invisible inputs on dark sites).
7
- > 2. **Form creation is TWO steps** — POST to create, then PATCH to add `postSubmissionTriggers`. Skipping the PATCH means submissions are silently lost (no CRM Contact created).
8
- > 3. **Namespace propagation** — if form creation fails with `UNSUPPORTED_FORM_NAMESPACE`, wait 10s and retry up to 3 times. Do NOT fall back to hardcoded fields — a form without a `formId` cannot submit to Wix.
9
- > 4. **Discover forms via SDK** — use `forms.listForms("wix.form_app.form")` with `auth.elevate`. Never hardcode form field IDs or form ID.
10
-
11
- > **⚠️ CRITICAL — Style Migration Required:** When you replace the designed `.astro` form placeholder with a React island, the placeholder's `<style is:global>` block is no longer rendered and ALL form styles vanish. You MUST copy the entire `<style is:global>` block from the designed component into the page file. Without this, form inputs are invisible on dark sites. See Step 1.4 below.
12
-
13
- ## Prerequisites
14
-
15
- - Wix Forms app must be installed on the site (installed via the apps-installer REST endpoint after scaffolding, or manually in the Wix dashboard)
16
- - `@wix/forms` package installed: `npm install @wix/forms`
17
-
18
- > **Forms are auto-created during scaffolding.** When scaffolding with a forms template (e.g., the Registration template `e5d63bf1-cd06-48eb-ad77-0da9235adcf1`), a form is automatically created on the site with server-side privileges. Use `forms.listForms("wix.form_app.form")` with `auth.elevate` to discover it — no manual form ID needed. If no forms exist, use the REST API Form Setup below to create one (the Create Form API is not available to headless SDK calls, but the CLI-minted REST token can create forms).
19
-
20
- ## Form Setup (REST)
21
-
22
- Before writing any form code, ensure a contact form exists on the site via the form-schema REST API:
23
-
24
- 1. **List forms** — `REST: GET https://www.wixapis.com/form-schema-service/v4/forms?namespace=wix.form_app.form`
25
- 2. **If the API returns a "missing installed app" error** → install the Wix Forms app:
26
- ```
27
- REST: POST https://www.wixapis.com/apps-installer-service/v1/app-instance/install
28
- body: {
29
- "tenant": { "tenantType": "SITE", "id": "<siteId>" },
30
- "appInstance": { "appDefId": "225dd912-7dea-4738-8688-4b8c6955ffc2", "enabled": true }
31
- }
32
- ```
33
- > Translate this prose-HTTP form into the full `curl` tool-call shape — pass `body` as JSON in `-d` (NOT a stringified JSON). See `../../shared/AUTHENTICATION.md` for the standard REST headers.
34
-
35
- Then retry listing forms.
36
- 3. **If forms list is empty** → create a form. This is a two-step atomic operation (POST to create, then PATCH to add `postSubmissionTriggers`) — see step 4 for the full procedure and rationale.
37
-
38
- > **Namespace propagation:** If form creation fails with `UNSUPPORTED_FORM_NAMESPACE` immediately after installing the Forms app, the namespace hasn't propagated yet. Wait 10 seconds and retry up to 3 times. Do NOT silently fall back to static field definitions — forms without a `formId` cannot submit to Wix.
39
-
40
- Select only the fields needed for the form's purpose.
41
-
42
- **Field building blocks** — assemble the `formFields` array from these individual definitions:
43
-
44
- ```jsonc
45
- // EMAIL (required for all form types)
46
- {
47
- "id": "191b2fae-7313-467a-9d4f-fd85598b1bdb",
48
- "hidden": false, "identifier": "CONTACTS_EMAIL", "fieldType": "INPUT",
49
- "inputOptions": {
50
- "target": "email", "pii": true, "required": true, "inputType": "STRING", "readOnly": false,
51
- "stringOptions": { "validation": { "format": "EMAIL", "enum": [] }, "componentType": "TEXT_INPUT", "textInputOptions": { "label": "Email", "showLabel": true } }
52
- }
53
- }
54
-
55
- // FIRST_NAME
56
- {
57
- "id": "c16f3def-fc74-4950-3b72-46dbdc132a90",
58
- "hidden": false, "identifier": "CONTACTS_FIRST_NAME", "fieldType": "INPUT",
59
- "inputOptions": {
60
- "target": "first_name", "pii": true, "required": false, "inputType": "STRING", "readOnly": false,
61
- "stringOptions": { "validation": { "format": "UNKNOWN_FORMAT", "enum": [] }, "componentType": "TEXT_INPUT", "textInputOptions": { "label": "First name", "showLabel": true } }
62
- }
63
- }
64
-
65
- // LAST_NAME
66
- {
67
- "id": "84242617-c855-486f-4ec6-87443210fb4f",
68
- "hidden": false, "identifier": "CONTACTS_LAST_NAME", "fieldType": "INPUT",
69
- "inputOptions": {
70
- "target": "last_name", "pii": true, "required": false, "inputType": "STRING", "readOnly": false,
71
- "stringOptions": { "validation": { "format": "UNKNOWN_FORMAT", "enum": [] }, "componentType": "TEXT_INPUT", "textInputOptions": { "label": "Last name", "showLabel": true } }
72
- }
73
- }
74
-
75
- // PHONE
76
- {
77
- "id": "5f5995cc-2951-4ce9-ae89-82ff487b1619",
78
- "hidden": false, "identifier": "CONTACTS_PHONE", "fieldType": "INPUT",
79
- "inputOptions": {
80
- "target": "phone", "pii": true, "required": false, "inputType": "STRING", "readOnly": false,
81
- "stringOptions": { "validation": { "format": "PHONE", "enum": [] }, "componentType": "PHONE_INPUT", "phoneInputOptions": { "label": "Phone", "showLabel": true } }
82
- }
83
- }
84
-
85
- // MESSAGE
86
- // ⚠️ **Naming trap:** The MESSAGE field uses `identifier: "TEXT_AREA"` but its
87
- // `componentType` MUST be `"TEXT_INPUT"`. The API will reject `componentType: "TEXT_AREA"`
88
- // — that enum value does not exist in the Forms API. The `identifier` controls how the
89
- // Wix dashboard renders the field; `componentType` controls API schema validation.
90
- // Do not confuse the two.
91
- {
92
- "id": "ce6fc634-bc35-48ef-6f01-c2cded75d836",
93
- "hidden": false, "identifier": "TEXT_AREA", "fieldType": "INPUT",
94
- "inputOptions": {
95
- "target": "message", "pii": false, "required": false, "inputType": "STRING", "readOnly": false,
96
- "stringOptions": { "validation": { "format": "UNKNOWN_FORMAT", "enum": [] }, "componentType": "TEXT_INPUT", "textInputOptions": { "label": "Message", "showLabel": true } }
97
- }
98
- }
99
-
100
- // SUBMIT BUTTON (always include as the last field)
101
- {
102
- "id": "fe946b52-9719-4c57-57e8-a0791c29344f",
103
- "hidden": false, "identifier": "SUBMIT_BUTTON", "fieldType": "DISPLAY",
104
- "displayOptions": { "displayFieldType": "PAGE_NAVIGATION", "pageNavigationOptions": { "nextPageText": "Next", "previousPageText": "Back", "submitText": "Submit" } }
105
- }
106
- ```
107
-
108
- **Assembly by purpose:**
109
-
110
- | Purpose | Fields to include | Layout rows |
111
- |---------|------------------|-------------|
112
- | Waitlist / newsletter | EMAIL + SUBMIT | email row 0, submit row 1 |
113
- | Lead capture | FIRST_NAME + EMAIL + SUBMIT | first_name row 0, email row 1, submit row 2 |
114
- | Contact (full) | FIRST_NAME + LAST_NAME + EMAIL + PHONE + MESSAGE + SUBMIT | first+last row 0 (6+6 cols), email row 1, phone row 2, message row 3, submit row 4 |
115
-
116
- Build the `steps[0].layout.large.items` array to match — each field gets a `{ fieldId, row, column, width: 12, height: 1 }` entry. For side-by-side fields (first + last name), use `width: 6` with `column: 0` and `column: 6`.
117
-
118
- The `postSubmissionTriggers.upsertContact.fieldsMapping` must only include mappings for fields that exist on the form. For a waitlist form with email only:
119
- ```json
120
- "fieldsMapping": {
121
- "email": { "contactField": "EMAIL", "emailInfo": { "tag": "UNTAGGED" } }
122
- }
123
- ```
124
-
125
- Full REST call structure:
126
- ```
127
- REST: POST https://www.wixapis.com/form-schema-service/v4/forms
128
- body: {
129
- "form": {
130
- "formFields": [ <selected fields from above> ],
131
- "steps": [{ "id": "cfa7a3ed-ef11-4ae7-3a5b-7d450c86d217", "name": "Page 1", "hidden": false,
132
- "layout": { "large": { "items": [ <layout entries matching selected fields> ] }}
133
- }],
134
- "name": "<Form Name matching purpose>",
135
- "namespace": "wix.form_app.form",
136
- "spamFilterProtectionLevel": "ADVANCED",
137
- "enabled": true,
138
- "postSubmissionTriggers": {
139
- "upsertContact": {
140
- "fieldsMapping": { <only mappings for included contact fields> },
141
- "labels": []
142
- }
143
- },
144
- "submitSettings": {
145
- "submitSuccessAction": "THANK_YOU_MESSAGE",
146
- "thankYouMessageOptions": {
147
- "durationInSeconds": 8,
148
- "richContent": { "nodes": [{ "type": "PARAGRAPH", "id": "krhc065", "nodes": [{ "type": "TEXT", "id": "", "nodes": [], "textData": { "text": "Thanks, we received your submission.", "decorations": [] } }], "paragraphData": { "textStyle": { "textAlignment": "CENTER" } } }] }
149
- }
150
- }
151
- }
152
- }
153
- ```
154
- 4. **Always PATCH `postSubmissionTriggers` after creation** — The creation API silently drops this field. Treat form creation as a two-step atomic operation:
155
- - Step A: `POST /forms` to create the form
156
- - Step B: `PATCH /forms/<formId>` to add `postSubmissionTriggers`
157
- Never skip Step B, even if you included triggers in the creation payload. The cost of a redundant PATCH is zero; the cost of missing triggers is silent data loss (submissions recorded but no CRM contact created).
158
- - GET the form: `GET https://www.wixapis.com/form-schema-service/v4/forms?namespace=wix.form_app.form`
159
- - PATCH using the procedure in step 5 below
160
- 5. **If forms already exist** → verify the form has `postSubmissionTriggers.upsertContact`. This field is **critical** — without it, submissions are recorded but no Contact is created in the CRM. If missing, patch the form to add it:
161
- ```
162
- REST: PATCH https://www.wixapis.com/form-schema-service/v4/forms/<formId>
163
- body: {
164
- "form": {
165
- "revision": "<current revision from GET>",
166
- "postSubmissionTriggers": {
167
- "upsertContact": {
168
- "fieldsMapping": {
169
- <map each contact field target in the form, e.g.:>
170
- "email": { "contactField": "EMAIL", "emailInfo": { "tag": "UNTAGGED" } },
171
- "first_name": { "contactField": "FIRST_NAME" },
172
- "last_name": { "contactField": "LAST_NAME" },
173
- "phone": { "contactField": "PHONE", "phoneInfo": { "tag": "UNTAGGED" } }
174
- },
175
- "labels": []
176
- }
177
- }
178
- }
179
- }
180
- ```
181
- Only include mappings for fields that exist on the form. The `fieldsMapping` keys must match the `inputOptions.target` values of the form's fields.
182
-
183
- ## Files to Modify / Create
184
-
185
- | File | Action |
186
- |------|--------|
187
- | Existing designed page (e.g., `src/pages/contact.astro`) | **Modify in place** — add SDK imports and replace placeholder form with React island |
188
- | `src/components/ContactForm.tsx` | **Create** — React island for client-side submission |
189
-
190
- ## Implementation
191
-
192
- ### 1. Modify the Existing Designed Page
193
-
194
- **Do NOT create a new page from scratch.** The merged `contact-page` scope writes this page once — branded styling, layout, and `<style>` block alongside the form wiring (per `references/astro/designer/INSTRUCTIONS.md` → `contact-page`). When wiring an existing designed page, modify it in place:
195
-
196
- 1. **Add SDK imports** to the frontmatter:
197
- ```astro
198
- import { forms } from "@wix/forms";
199
- import { auth } from "@wix/essentials";
200
- import ContactForm from "../components/ContactForm.tsx";
201
- ```
202
-
203
- 2. **Add the form discovery query** to the frontmatter:
204
- ```astro
205
- const elevatedListForms = auth.elevate(forms.listForms);
206
- const listResult = await elevatedListForms("wix.form_app.form");
207
- const wixForm = listResult.forms?.[0];
208
- const formId = wixForm?._id ?? "";
209
-
210
- const formFields = wixForm?.formFields
211
- ?.filter((field) => field.fieldType === "INPUT" && !field.hidden)
212
- .map((field) => {
213
- const opts = field.inputOptions;
214
- const str = opts?.stringOptions;
215
- const label =
216
- str?.textInputOptions?.label ??
217
- str?.dropdownOptions?.label ??
218
- str?.phoneInputOptions?.label ??
219
- "";
220
- return {
221
- label,
222
- target: opts?.target ?? "",
223
- required: opts?.required ?? false,
224
- componentType: str?.componentType ?? "TEXT_INPUT",
225
- identifier: field.identifier ?? "",
226
- options: str?.dropdownOptions?.options?.map((o) => ({
227
- value: o.value ?? o.label ?? "",
228
- label: o.label ?? o.value ?? "",
229
- })),
230
- };
231
- }) ?? [];
232
- ```
233
-
234
- 3. **Replace the placeholder form HTML** with the React island:
235
- ```astro
236
- {formId ? (
237
- <ContactForm client:load formId={formId} fields={formFields} />
238
- ) : (
239
- <p>No form found. Create one in the Wix dashboard.</p>
240
- )}
241
- ```
242
-
243
- 4. **Migrate the form's `<style is:global>` block into the page.**
244
-
245
- The designed Astro placeholder component (e.g., `ContactForm.astro`) contains a `<style is:global>` block with all form CSS. Once you replace the Astro import with the React island, that component is no longer rendered and its styles vanish.
246
-
247
- - Open the designed Astro placeholder component and copy its entire `<style is:global>...</style>` block
248
- - Paste it into the page file, below any existing `<style>` block
249
- - Keep both `<style>` blocks — the page's scoped styles handle layout, the `is:global` block handles form elements inside the React island
250
- - Do NOT remove or modify the page's existing `<style>` block
251
-
252
- **Why `is:global` is required:** Astro scoped styles use `data-astro-cid-*` attributes that don't transfer to React-rendered DOM. The form styles must be global to reach elements inside the React island.
253
-
254
- ### 2. Contact Form Component (`src/components/ContactForm.tsx`)
255
-
256
- The React island must match the designed component's class names and use CSS variables for all visual properties. Two approaches:
257
-
258
- **Approach A (preferred): Page provides styles via `<style>` block.** The component reuses the class names from the designed placeholder. The page's existing `<style>` block handles all visual styling. The component only needs minimal inline styles for dynamic states.
259
-
260
- **Approach B: Component owns its styles using CSS variables.** If the page doesn't have a `<style>` block for the form, the component includes a `<style>` JSX element using only CSS custom properties.
261
-
262
- > **Styling note:** The React island uses the styling contract class names (`.form-container`, `.form-field`, `.form-label`, `.form-input`, `.form-textarea`, `.form-button`, `.form-success`, `.form-error`, `.form-field-error`, `.form-input-error`) from the designed ContactForm component's `<style is:global>` block. See `references/shared/STYLING.md` (Contact Form).
263
-
264
- ```tsx
265
- import { useState } from "react";
266
- import { submissions } from "@wix/forms";
267
-
268
- interface FormField {
269
- label: string;
270
- target: string;
271
- required: boolean;
272
- componentType: string;
273
- identifier?: string;
274
- options?: { value: string; label: string }[];
275
- }
276
-
277
- interface ContactFormProps {
278
- formId: string;
279
- fields: FormField[];
280
- }
281
-
282
- export default function ContactForm({ formId, fields }: ContactFormProps) {
283
- const [formData, setFormData] = useState<Record<string, string>>({});
284
- const [status, setStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
285
- const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});
286
-
287
- const handleSubmit = async (e: React.FormEvent) => {
288
- e.preventDefault();
289
- setStatus("submitting");
290
- setFieldErrors({});
291
-
292
- try {
293
- const result = await submissions.createSubmission({
294
- formId,
295
- submissions: formData,
296
- });
297
-
298
- if (result.status === "PENDING" || result.status === "CONFIRMED") {
299
- setStatus("success");
300
- setFormData({});
301
- } else {
302
- setStatus("error");
303
- }
304
- } catch (err: unknown) {
305
- const violations =
306
- (err as any)?.details?.validationError?.fieldViolations ?? [];
307
- const errorMap: Record<string, string> = {};
308
-
309
- for (const v of violations) {
310
- const fieldErrs: { errorPath?: string; errorMessage?: string }[] =
311
- v?.data?.errors ?? [];
312
- for (const fe of fieldErrs) {
313
- if (fe.errorPath && !errorMap[fe.errorPath]) {
314
- errorMap[fe.errorPath] = fe.errorMessage ?? "Invalid value";
315
- }
316
- }
317
- }
318
-
319
- if (Object.keys(errorMap).length > 0) {
320
- setFieldErrors(errorMap);
321
- setStatus("idle");
322
- } else {
323
- setStatus("error");
324
- }
325
- }
326
- };
327
-
328
- if (status === "success") {
329
- return (
330
- <div className="form-success">
331
- Thank you! We'll be in touch soon.
332
- </div>
333
- );
334
- }
335
-
336
- return (
337
- <form onSubmit={handleSubmit} className="form-container">
338
- {/* Styles come from the designed component's <style is:global> block.
339
- Uses styling contract classes: .form-container, .form-field, .form-label,
340
- .form-input, .form-select, .form-textarea, .form-button, .form-error,
341
- .form-field-error, .form-input-error.
342
- See references/shared/STYLING.md (Contact Form). */}
343
-
344
- {fields.map((field) => (
345
- <div key={field.target} className="form-field">
346
- <label className="form-label">
347
- {field.label}
348
- {field.required && <span className="required">*</span>}
349
- </label>
350
- {field.componentType === "DROPDOWN" && field.options ? (
351
- <select
352
- required={field.required}
353
- value={formData[field.target] ?? ""}
354
- onChange={(e) =>
355
- setFormData((prev) => ({ ...prev, [field.target]: e.target.value }))
356
- }
357
- className={`form-select${fieldErrors[field.target] ? " form-input-error" : ""}`}
358
- >
359
- <option value="">Select an option</option>
360
- {field.options.map((opt) => (
361
- <option key={opt.value} value={opt.value}>{opt.label}</option>
362
- ))}
363
- </select>
364
- ) : field.identifier === "TEXT_AREA" || field.target === "message" ? (
365
- <textarea
366
- required={field.required}
367
- value={formData[field.target] ?? ""}
368
- onChange={(e) =>
369
- setFormData((prev) => ({ ...prev, [field.target]: e.target.value }))
370
- }
371
- rows={4}
372
- className={`form-textarea${fieldErrors[field.target] ? " form-input-error" : ""}`}
373
- />
374
- ) : (
375
- <input
376
- type={
377
- field.target === "email" ? "email" :
378
- field.componentType === "PHONE_INPUT" ? "tel" : "text"
379
- }
380
- required={field.required}
381
- value={formData[field.target] ?? ""}
382
- onChange={(e) =>
383
- setFormData((prev) => ({ ...prev, [field.target]: e.target.value }))
384
- }
385
- className={`form-input${fieldErrors[field.target] ? " form-input-error" : ""}`}
386
- {...(field.componentType === "PHONE_INPUT" ? { placeholder: "+1234567890" } : {})}
387
- />
388
- )}
389
- {fieldErrors[field.target] && (
390
- <p className="form-field-error">{fieldErrors[field.target]}</p>
391
- )}
392
- </div>
393
- ))}
394
-
395
- <button
396
- type="submit"
397
- disabled={status === "submitting"}
398
- className="form-button"
399
- >
400
- {status === "submitting" ? "Sending..." : "Send Message"}
401
- </button>
402
-
403
- {status === "error" && (
404
- <p className="form-error">Something went wrong. Please try again.</p>
405
- )}
406
- </form>
407
- );
408
- }
409
- ```
410
-
411
- > **Adapting class names:** The class names above (`form-container`, `form-field`, `form-label`, `form-input`, `form-button`, `form-success`, `form-error`, `form-field-error`, `form-input-error`) are defaults. If the designed component uses different class names, use those instead — the styling contract from the page's own design takes precedence.
412
-
413
- ## Discovering Forms
414
-
415
- Forms are auto-created when scaffolding with a forms template. Use `auth.elevate(forms.listForms)` with the `"wix.form_app.form"` namespace to discover them — no hardcoded ID needed:
416
-
417
- ```typescript
418
- import { forms } from "@wix/forms";
419
- import { auth } from "@wix/essentials";
420
-
421
- const elevatedListForms = auth.elevate(forms.listForms);
422
- const listResult = await elevatedListForms("wix.form_app.form");
423
- const wixForm = listResult.forms?.[0];
424
- const formId = wixForm?._id;
425
- ```
426
-
427
- If no forms exist, use the REST API Form Setup section above to create one via `curl`. If curl auth is not available, create one in the Wix dashboard (Forms section → Add New Form).
428
-
429
- ## Form Field Schema (SDK Types)
430
-
431
- Each field in `formFields` has this structure when `fieldType === "INPUT"`:
432
-
433
- ```typescript
434
- field.identifier // "CONTACTS_EMAIL", "TEXT_AREA", "SUBMIT_BUTTON", etc.
435
- field.inputOptions.target // "email", "first_name", "message", custom UUIDs
436
- field.inputOptions.required // boolean
437
- field.inputOptions.stringOptions.componentType // "TEXT_INPUT" | "DROPDOWN" | "PHONE_INPUT"
438
- field.inputOptions.stringOptions.textInputOptions?.label // label for text inputs
439
- field.inputOptions.stringOptions.dropdownOptions?.label // label for dropdowns
440
- field.inputOptions.stringOptions.dropdownOptions?.options // [{value, label}] for dropdowns
441
- field.inputOptions.stringOptions.phoneInputOptions?.label // label for phone inputs
442
- ```
443
-
444
- > **⚠️ Textarea detection:** The message field's `componentType` is always `"TEXT_INPUT"` (the API rejects `"TEXT_AREA"` as a componentType value). To render a `<textarea>`, check `field.identifier === "TEXT_AREA"` or `field.target === "message"` — NOT `field.componentType`.
445
-
446
- ## Built-In Field Targets
447
-
448
- | Target | Type | HTML Input |
449
- |--------|------|-----------|
450
- | `email` | Email | `type="email"` |
451
- | `first_name` | Text | `type="text"` |
452
- | `last_name` | Text | `type="text"` |
453
- | `phone` | Phone | `type="tel"` |
454
- | `company` | Text | `type="text"` |
455
-
456
- Custom fields use UUID-based targets from the form schema.
457
-
458
- ## Testing
459
-
460
- 1. Run `npx @wix/cli@latest dev`
461
- 2. Navigate to `/contact`
462
- 3. Fill in the form and submit
463
- 4. Check the Wix dashboard → Forms → Submissions to verify the data arrived