@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
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: "How to Code CMS"
3
+ description: The frontend read/write contract for Wix CMS (Wix Data) — the `@wix/data` `items.query` builder, the `_id`-and-fields-on-the-item shape (not `item.data.field`), why public-read collections need no `auth.elevate`, how to resolve images and render Ricos rich text, and the visitor-write path for collaborative collections (`items.insert`/`update`/`remove`, the update-replaces-whole-item footgun, shared/unscoped data). Specifies the *how* (module + exact calls + the failure modes the docs omit); which collections to render/write come from the request.
4
+ ---
5
+ **RECIPE**: How to Code a Wix CMS Frontend (`@wix/data`, Wix Data v2)
6
+
7
+ A concise contract for writing the **frontend code** that reads Wix CMS collections: listing items, filtering, following references, and rendering images and rich text. **This recipe is the *how* (which module, which calls, which fields), not the *what*** — which collections to show, how the page looks, and the framework are decided by the request you're fulfilling.
8
+
9
+ > **This recipe is for CODING the frontend, not for seeding it.** It assumes the collections and items already exist and are **public-read** (created by `setup-cms.md`). It says nothing about creating collections or inserting data — only how to read them from frontend code.
10
+
11
+ > **⚠️ Reading rule — always append `.md?apiView=SDK` to every doc link below.** The Wix docs render two views of the same page. The **bare / REST view** describes the REST shape — items nested under `item.data.<field>` and queried via a `POST /items/query` body. The **`?apiView=SDK` view** describes the SDK shape — items with **fields on the item itself** and a chainable `items.query(...)` builder. The SDK is what your frontend calls; reading the REST view by mistake is the source of the `item.data.title`-returns-`undefined` bug below. Fetch the `.md?apiView=SDK` form directly.
12
+
13
+ ---
14
+
15
+ ## The module and the client (read this first)
16
+
17
+ **⚠️ CRITICAL: the Wix Data items API is the `items` named export of `@wix/data`** — `import { items } from "@wix/data"`, then `items.query` / `items.get` / `items.insert` / `items.update` / `items.remove` (plus `items.bulkInsert` / `items.queryReferenced`). Do **not** import from the internal `@wix/wix-data-items-sdk` — `@wix/data` is the single documented package.
18
+
19
+ | Need | Package | Module / export |
20
+ |---|---|---|
21
+ | Read collection items (query, get, filter, references) | `@wix/data` | `items` |
22
+ | Resolve `wix:image://` URIs to URLs | `@wix/sdk` | `media` |
23
+
24
+ **Collection id has NO namespace.** A native collection's id is just the name the seed created (`"team-members"`, `"faq"`, `"Projects"`) — pass it straight to `items.query("team-members")`. The `<namespace>/<name>` form is only for Wix App collections. Stay consistent with the `collectionId` the seed recipe kept.
25
+
26
+ **Auth / client — framework split:**
27
+ - **Astro (Wix-managed):** authentication is ambient. Call `items.query(...)` directly from server components and backend routes (`src/pages/api/*.ts`) — **no `createClient`, no `OAuthStrategy`, no `clientId`.**
28
+ - **Non-Astro (Vite/React/Vue/static):** build one manual visitor client and reuse it:
29
+ ```js
30
+ import { createClient, OAuthStrategy } from '@wix/sdk';
31
+ import { items } from '@wix/data';
32
+
33
+ const client = createClient({
34
+ modules: { items },
35
+ auth: OAuthStrategy({ clientId: /* the project's PUBLIC OAuth client id */ }),
36
+ });
37
+ // then: client.items.query('team-members').find()
38
+ ```
39
+ The `clientId` is public, not a secret.
40
+
41
+ **⚠️ CRITICAL: do NOT call `auth.elevate` — public collections are public-read, and member-scoped ones use the member token.** `setup-cms.md` creates a public collection with `read: "ANYONE"`, so the visitor token reads it directly. A pure SPA/static frontend has **no server and cannot elevate** at all; even on Astro the read is visitor-scoped and needs no elevation. (Elevation is only for collections that genuinely can't be public — not the case here.) **If a query on a PUBLIC collection comes back empty, it wasn't seeded public-read — that's a permissions bug in the seed, not a query bug** (re-check the collection's `read` permission); don't reach for `elevate` to paper over it.
42
+
43
+ **Member-scoped collections (only when the run includes members login).** A collection seeded member-scoped (`setup-cms.md` → `SITE_MEMBER_AUTHOR` for per-user-private, or `SITE_MEMBER` for member-only) is read/written with the **logged-in member's token** — the same client, just after the member has logged in (see `how-to-code-members-astro.md` / `how-to-code-members-non-astro.md`). Key rules:
44
+ - **Still NO `auth.elevate`.** The member token carries the identity; the platform scopes the rows server-side. Reaching for elevate here is the wrong axis (it's for admin/site-wide reads, not a member's own data).
45
+ - **`SITE_MEMBER_AUTHOR` returns only the caller's OWN rows automatically** (matched on the item's `_owner`) — you don't filter by owner in the query, and you **must not** set `_owner` on insert (the platform stamps it from the member identity). `items.query('my-notes').find()` as member A returns A's notes; as member B, B's.
46
+ - **An anonymous / not-yet-logged-in read returns ZERO items — that's the gate, not a bug.** Don't render a member-scoped surface to anonymous visitors: gate the route/page behind login first (bounce to the login flow), *then* query. An empty result after a confirmed login on a `SITE_MEMBER_AUTHOR` collection just means that member has no rows yet (show an empty state), not a permissions error.
47
+
48
+ ---
49
+
50
+ ## The shape you read (field cheat-sheet)
51
+
52
+ ```jsonc
53
+ // items.query("CollectionId").find() → result.items[]
54
+ item = {
55
+ _id, // the item id (SDK normalizes to _id, NOT id)
56
+ _createdDate, _updatedDate, _owner, // system fields
57
+ name, role, bio, order, // YOUR fields — directly on the item (NOT item.data.name)
58
+ }
59
+ // result also has: result.length, result.hasNext(), result.pageSize
60
+ ```
61
+
62
+ `result.items[]` is the array; paging via `result.hasNext()` / a follow-up `.find()`. A `wix:image://` value in an IMAGE field and a Ricos object in a RICH_TEXT/RICH_CONTENT field both need resolving before render (see below).
63
+
64
+ ---
65
+
66
+ ## The features (build the ones the site needs)
67
+
68
+ Each section is a **self-contained feature** — implement only what the site uses, in any order.
69
+
70
+ ### Listing / reading (and the field-access rule)
71
+
72
+ Query a collection with the chainable builder; `.find()` resolves to `{ items, ... }`.
73
+ Doc: <https://dev.wix.com/docs/sdk/business-solutions/data/items/query.md?apiView=SDK>
74
+
75
+ ```js
76
+ const { items: rows } = await items.query('team-members')
77
+ .ascending('order')
78
+ .limit(50)
79
+ .find();
80
+ // rows[0] === { _id, name, role, bio, order, _createdDate, ... }
81
+ ```
82
+
83
+ **⚠️ CRITICAL: fields are on the item itself — `item.name`, NOT `item.data.name`.** The SDK returns each field as a top-level property of the item (the API was revised to match the Velo `wix-data` shape). `item.data.name` is the **REST** response shape and reads `undefined` in SDK code — the silent "every field is blank" bug. If you're reaching through `.data`, you're reading the REST doc view; re-open it with `?apiView=SDK`.
84
+
85
+ **⚠️ CRITICAL: the id is `_id`, never `id`.** `item.id` is `undefined`; use `item._id` for keys, links, and reference lookups.
86
+
87
+ **⚠️ `items.queryDataItems(...)` does NOT exist in the SDK.** The chainable entry point is `items.query("collectionId")` — `queryDataItems` is a REST/method name. Don't mix the two.
88
+
89
+ ### Filtering and single-item lookup
90
+
91
+ Chain filter/sort/page methods on the query builder, then `.find()`:
92
+
93
+ ```js
94
+ // by slug (detail page)
95
+ const { items: [post] } = await items.query('articles').eq('slug', slug).limit(1).find();
96
+ // compound filter + sort
97
+ const { items: rows } = await items.query('products')
98
+ .eq('inStock', true).gt('price', 25).ascending('title').limit(50).find();
99
+ ```
100
+
101
+ Builder methods: `.eq` / `.ne` / `.gt` / `.ge` / `.lt` / `.le` / `.contains` / `.startsWith` / `.hasSome` / `.ascending` / `.descending` / `.limit` / `.skip`. (No `$`-operator JSON body — that's the REST `/items/query` shape; in the SDK the operators are builder methods.)
102
+
103
+ ### Following references
104
+
105
+ A `REFERENCE` / `MULTI_REFERENCE` field stores only ids by default. To inline the referenced items, add `.include("<fieldKey>")`:
106
+
107
+ ```js
108
+ const { items: rows } = await items.query('projects').include('teamMembers').find();
109
+ // rows[0].teamMembers is now an array of full team-member items, not ids
110
+ ```
111
+ Doc: <https://dev.wix.com/docs/sdk/business-solutions/data/items/query-referenced.md?apiView=SDK> (for `items.queryReferenced`, the alternative when a multi-reference set is large). Without `.include(...)`, the field is just ids — resolve them yourself or use `include`.
112
+
113
+ ### Rendering images (IMAGE fields)
114
+
115
+ An `IMAGE` field comes back as a **`wix:image://v1/<hash>/<file>#…` identifier, not a ready URL** — putting it straight into `<img src>` shows nothing (`ERR_UNKNOWN_URL_SCHEME`). Resolve it with the SDK media module, and reuse one helper on every render path:
116
+
117
+ ```js
118
+ import { media } from '@wix/sdk';
119
+ function imgSrc(v, w = 800, h = 600) {
120
+ if (!v) return '';
121
+ if (typeof v === 'string' && v.startsWith('wix:image://')) return media.getScaledToFillImageUrl(v, w, h, {});
122
+ return typeof v === 'string' ? v : (v?.url ?? ''); // an already-absolute https URL passes through
123
+ }
124
+ ```
125
+
126
+ **Never hand-build a `static.wixstatic.com/.../v1/fit/...` URL** — the format is easy to get wrong and the image then **403s**. Only `wix:image://` values need resolving; an already-absolute `https://` URL (e.g. an Unsplash placeholder seeded when imagery was off) goes straight into `<img src>`. Doc: <https://dev.wix.com/docs/sdk/core-modules/sdk/media>
127
+
128
+ **⚠️ When imagery is OFF (the seed default), IMAGE fields are EMPTY — fall back, don't render a broken `<img>`.** The seed is text-only unless imagery is on, so a `photo`/`coverImage`/`headshot` field is often **absent or empty** on every item. Guard the render: only emit `<img>` when the field resolves to a real URL, otherwise show a graceful fallback (an initials avatar, a colored placeholder, or simply omit the image) — never an empty/broken `<img src="">`. A missing image is expected content state here, not an error.
129
+
130
+ ### Rendering rich text (RICH_TEXT / RICH_CONTENT fields)
131
+
132
+ Wix CMS stores `RICH_TEXT` / `RICH_CONTENT` as **Ricos JSON** — a structured node tree (PARAGRAPH, HEADING, BULLETED_LIST…), not HTML and not a string.
133
+
134
+ **⚠️ Do NOT `set:html={item.bio}` or `String(item.bio)` directly.** That dumps `[object Object]` or `{"nodes":...}` into the page. Render the Ricos node tree — either with a small SSR Ricos→HTML walker (covers PARAGRAPH, HEADING, lists, BLOCKQUOTE, BOLD/ITALIC/LINK; renders anything else defensively as a `<p>`), or with `@wix/ricos`'s React `RicosViewer` as a client island when the content carries the full feature set (galleries, embeds). For short bound fields a plain-text variant is fine; for a body field, render it **formatted**.
135
+
136
+ ### Writing from the frontend (only to a visitor-writable collection)
137
+
138
+ Most collections are **read-only** from the visitor client — admin-owned content (catalog, team, articles) the site only displays. **Fire-and-forget visitor input** (contact, signup, lead capture) goes through **Wix Forms**, not CMS — don't `items.insert` for those.
139
+
140
+ But when the site is built around **shared, visitor-editable data** — a guestbook, a community board, a collaborative list anyone can add to and edit — that collection is seeded **visitor-writable** (`insert`/`update`/`remove: ANYONE`, see `setup-cms.md`), and the client does full CRUD with the same `items` module:
141
+
142
+ ```js
143
+ const created = await items.insert('community-board', { title, note, status: 'open' }); // → item with _id
144
+ await items.update('community-board', { ...item, status: 'claimed' }); // see footgun below
145
+ await items.remove('community-board', item._id);
146
+ ```
147
+
148
+ **⚠️ CRITICAL: `items.update()` REPLACES the whole item — it does NOT patch.** Per the docs: *"If the existing item had fields with values and those fields aren't included in the updated item, the values in those properties are lost."* So `update('c', { _id, status })` **wipes `title`, `note`, and every other field** — the classic "toggling status erases the row" bug. **Always pass the FULL item** on update (spread the record you already hold in state: `{ ...item, status }`). If you only have the id + one changed field and not the whole record, use **`items.bulkPatch('c', [id]).setField('status', v).run()`** instead — `bulkPatch` modifies only the named fields. Doc: <https://dev.wix.com/docs/sdk/business-solutions/data/items/update.md?apiView=SDK>
149
+
150
+ **⚠️ A write needs the collection seeded with the matching open permission — else it 403s.** `items.insert`/`update`/`remove` only succeed if the collection was created with that verb at `ANYONE` (`setup-cms.md`). A write to an `ADMIN`-write collection 403s from the visitor client (there's no `auth.elevate` on this path to get around it). If writes 403, fix the seed permission, not the call.
151
+
152
+ **⚠️ On the ANONYMOUS path the data is SHARED and unscoped — no per-user identity.** The visitor token has no per-user identity, so an `ANYONE`-writable collection is **global/shared across all visitors** (not per-user, not cross-device) and **any visitor can edit or delete any row**. That's the intended model for a collaborative board; surface it as such. **For per-user-private data, that's the member-scoped path** (`SITE_MEMBER_AUTHOR`, see the member-scoped note above): the same `items.insert`/`update`/`remove` calls, but run under a **logged-in member's token**, and each member touches only their own `_owner`-matched rows. On Astro you may route writes through a backend `src/pages/api/*` endpoint, but the permission facts are identical — no `_owner` set by hand, no elevate.
153
+
154
+ ---
155
+
156
+ ## Conclusion
157
+ A correct Wix CMS frontend:
158
+ - imports the **`items`** export of **`@wix/data`** (never `@wix/wix-data-items-sdk`), and `media` from `@wix/sdk` for images;
159
+ - queries with **`items.query("collectionId")` + builder methods + `.find()`** (no namespace on the id; `queryDataItems` doesn't exist);
160
+ - reads fields **on the item** (`item.name`) and the id as **`item._id`** — never `item.data.name`, never `item.id`;
161
+ - does **no `auth.elevate`** — a public collection is read on the visitor token (an empty result there is a seed permissions bug, not a query bug), and a **member-scoped** collection (opt-in, `SITE_MEMBER_AUTHOR`/`SITE_MEMBER`) is read on the **logged-in member's token** with the same no-elevate rule (an anonymous read returning empty is the gate, not a bug);
162
+ - resolves `wix:image://` via `media.getScaledToFillImageUrl` and renders Ricos rich text formatted (never raw `set:html`/`String`);
163
+ - treats CMS as **read-only by default** (fire-and-forget input → Forms); writes to a **visitor-writable** collection use `items.insert`/`update`/`remove` — always passing the **full item** on `update` (it replaces, not patches), expecting the data to be **shared/unscoped**, and relying on the collection's seeded `ANYONE` write permission (no `auth.elevate`). For **per-user-private** data (opt-in, members login in the run) the same calls run under the **member token** against a `SITE_MEMBER_AUTHOR` collection — each member sees/edits only their own `_owner`-matched rows, `_owner` is never set by hand, and the surface is gated behind login.
@@ -0,0 +1,203 @@
1
+ ---
2
+ name: "How to Code Events"
3
+ description: The frontend read/registration contract for a Wix Events (Events V3) site — which SDK modules to import, how to list upcoming events, read one by slug, list ticket tiers, and run the two registration paths (ticketed = reserve → redirect to Wix's hosted checkout; free = createRsvp). Specifies the *how* (modules + exact calls + the failure modes the docs omit); which events to render and how the page looks come from the request.
4
+ ---
5
+ **RECIPE**: How to Code a Wix Events Frontend (Events V3 + hosted-checkout redirect)
6
+
7
+ A concise contract for writing the **frontend code** of an events site: a listing, per-event detail pages, ticketed checkout (reserve the tickets, then redirect to Wix's hosted checkout), and free RSVP registration. **This recipe is the *how* (which modules, which calls, which fields), not the *what*** — which events to show, how the page looks, and the framework are decided by the request you're fulfilling.
8
+
9
+ > **This recipe is for CODING the registration flow, not for seeding it.** It assumes an Events V3 backend already exists (published events with future dates, ticket definitions for ticketed events). It says nothing about creating events — only how to read and register for them from frontend code.
10
+
11
+ > **The whole flow is a site-visitor operation — no server route, no elevation.** Reserving tickets, minting the checkout redirect, and creating an RSVP all run under the **anonymous visitor** identity (the Events Checkout scope is granted to visitors), the same client-side model as the bookings pack. If you reach for a `src/pages/api/*` route or `auth.elevate()` to make a reservation work, **stop** — that masks the real gate (the payment-method precondition below) and the redirect call actively **fails** when elevated.
12
+
13
+ > **⚠️ Reading rule — always append `.md?apiView=SDK` to every doc link below.** The Wix docs render two views of the same page. The **bare / REST view shows `id`**; the **`?apiView=SDK` view shows `_id`** — and the SDK is what your frontend calls. Reading the REST view by mistake is the most common source of the `event.id`-is-`undefined` bug. If a field name surprises you, you're probably reading the REST view — re-open it with `?apiView=SDK`. Discover any shape not pinned here with `SearchWixSDKDocumentation`, not by guessing a URL.
14
+
15
+ ---
16
+
17
+ ## The modules and the client (read this first)
18
+
19
+ No app-id constant is needed in frontend code — the only id the client needs is the public **`clientId`** (non-Astro only; see below). Ticketed checkout hands off to Wix's hosted checkout via the Redirects API, so there is **no on-site cart and no `catalogReference`**.
20
+
21
+ | Need | Package | Module |
22
+ |---|---|---|
23
+ | List events / get one by slug | `@wix/events` | `wixEventsV2` (`queryEvents`, `getEventBySlug`) |
24
+ | Ticket tiers (ticketed) | `@wix/events` | `orders` (`queryAvailableTickets`) — the visitor-public storefront read |
25
+ | Reserve tickets (ticketed) | `@wix/events` | `ticketReservations` (`createTicketReservation`) |
26
+ | Create an RSVP (free) | `@wix/events` | **`rsvpV2`** (`createRsvp`) — NOT the legacy `rsvp` module (v1 → 400) |
27
+ | Redirect to hosted checkout (ticketed) | `@wix/redirects` | `redirects` (`createRedirectSession`) |
28
+
29
+ - **The events query/get namespace is `wixEventsV2`** (despite the name, this is the current Events V3 module from `@wix/events`). Import `wixEventsV2`, `orders`, `ticketReservations`, `rsvpV2` from `@wix/events`.
30
+ - **⚠️ CRITICAL: read ticket tiers with `orders.queryAvailableTickets`, NOT `ticketDefinitions(V2).queryTicketDefinitions`.** The `ticketDefinitions*` namespaces are the **management** API (`TicketDefinitionManagement`, a manage scope) — the **anonymous visitor is `403`-denied** on every one of them (`queryTicketDefinitions`, `queryTicketDefinitionsV2`, `listTicketDefinitions`), so a storefront that reads tiers that way gets an empty picker. **Do NOT work around it with `auth.elevate()`** — that's the wrong axis (an app/admin permission elevation), it's SSR-only (useless on a non-Astro SPA), and it's unnecessary: the **visitor-public storefront read** is `orders.queryAvailableTickets({ filter: { eventId }, limit })` → `{ definitions }` (visitor-public — works for the anonymous visitor on Astro *and* SPA). The event read (`queryEvents`/`getEventBySlug`) is visitor-public too — **no elevation anywhere in this recipe.**
31
+ - **Never use the deprecated `orders.createReservation`** — reserve with `ticketReservations.createTicketReservation`.
32
+ - **Never complete a paid purchase with `orders.checkout` (inline payment)** — that path leaves orders unpaid without a payment integration. The supported headless completion is the **hosted redirect** (below).
33
+
34
+ **Auth / client — framework split:**
35
+ - **Astro (Wix-managed):** authentication is ambient. Call the modules directly — from server components for the SSR reads (listing/detail) and from browser islands for the visitor-session writes (reserve / redirect / rsvp) via the `@wix/astro` visitor client — **no `createClient`, no `OAuthStrategy`, no `clientId`.** Nothing here needs elevation (every read and write runs as the visitor — "no elevation anywhere"); a public-env `clientId` read in `.astro` SSR is `undefined` at server render → 500, so don't build an `OAuthStrategy` client there.
36
+ - **Non-Astro (Vite/React/Vue/static):** build one manual visitor client and reuse it:
37
+ ```js
38
+ import { createClient, OAuthStrategy } from '@wix/sdk';
39
+ import { wixEventsV2, orders, ticketReservations, rsvpV2 } from '@wix/events';
40
+ import { redirects } from '@wix/redirects';
41
+
42
+ const client = createClient({
43
+ modules: { wixEventsV2, orders, ticketReservations, rsvpV2, redirects },
44
+ auth: OAuthStrategy({ clientId: /* the project's PUBLIC OAuth client id */ }),
45
+ });
46
+ ```
47
+ The `clientId` is public, not a secret. A mis-wired public env var inlines as `undefined` and 400s every call.
48
+
49
+ ---
50
+
51
+ ## The shapes you read (field cheat-sheet)
52
+
53
+ ```jsonc
54
+ // wixEventsV2.getEventBySlug(slug, { fields: [...] }) → { event }
55
+ // wixEventsV2.queryEvents(...) → result.events[]
56
+ event = {
57
+ _id, // routes · reserve/rsvp bind to it (NOT .id → undefined)
58
+ slug, // the URL slug — checkout redirect needs it
59
+ title, shortDescription,
60
+ mainImage, // image ref (render via the media helper)
61
+ dateAndTimeSettings: { formatted: { dateAndTime } }, // human-formatted date string
62
+ location: { name, type }, // "VENUE" | "ONLINE" | TBD
63
+ registration: { initialType }, // "TICKETING" | "RSVP" — BRANCH on this
64
+ // categories?: { categories: [{ _id, name }] } // runtime shape when fields:['CATEGORIES'] is requested — but NOT on the typed Event (SDK gap): read via a cast, see below
65
+ }
66
+
67
+ // orders.queryAvailableTickets({ filter: { eventId }, limit }) → { definitions } (VISITOR-public)
68
+ tier = {
69
+ _id, // reserve by this (NOT .id)
70
+ name, description,
71
+ price: { value, currency }, // value is a STRING (e.g. "45.00"); also at pricing.fixedPrice.value
72
+ free, // boolean
73
+ saleStatus, // "SALE_STARTED" | "SALE_ENDED" | "SALE_SCHEDULED" — gate the picker on this
74
+ limitPerCheckout, // max qty per order for this tier
75
+ }
76
+ ```
77
+
78
+ **⚠️ CRITICAL: entity ids are `_id`, NOT `id`.** `event._id`, `tier._id`. `event.id` is `undefined` in SDK code — a surprise `id`/`undefined` means you're reading the REST doc view; re-open it with `?apiView=SDK`.
79
+
80
+ **Filtering by event format/track (talk/workshop/social)** — if the site groups events by a format, the seed models it as **Event Categories** (`setup-events.md` STEP 4). Read the assigned category off the event and filter **client-side** — two gotchas:
81
+ - **Request `CATEGORIES` as the 2nd positional arg**, not inside the flat query: `queryEvents({ filter, sort, paging }, { fields: ['CATEGORIES'] })` and `getEventBySlug(slug, { fields: ['CATEGORIES'] })`. (`fields` lives on the options arg, not on `EventQuery`.)
82
+ - **`categories` is NOT on the typed `Event` (an SDK type gap** — the `CATEGORIES` enum and `EventCategory`/`EventCategories` types ship, but `Event` omits the property, so a direct `event.categories` read fails `tsc`/`astro check`). **Read it through a cast:** `const cats = (event as any).categories?.categories ?? []` — each entry is `{ _id, name }`; map `cats[].name` → your format enum.
83
+ - **Do NOT call the management categories endpoints** (`/events/v1/categories*`, `listEventsByCategory`) from the frontend — they're admin-scope; the visitor read is just the cast `CATEGORIES` field on the event.
84
+
85
+ ---
86
+
87
+ ## The registration features (build the ones the site needs)
88
+
89
+ Each section is a **self-contained feature** — implement only what the site uses. **Branch on the event's `registration.initialType`:** `TICKETING` → ticket picker (tiers + quantities → reserve → redirect); `RSVP` → the built-in name+email form → `createRsvp`. Never render an RSVP event with a ticket picker (or a ticketed event with an RSVP form).
90
+
91
+ ### Listing events (upcoming only, and the `_id` rule)
92
+
93
+ ```js
94
+ const { events } = await wixEventsV2.queryEvents({
95
+ filter: { status: { $in: ['UPCOMING', 'STARTED'] } }, // exclude DRAFT / ENDED / CANCELED
96
+ sort: [{ fieldName: 'dateAndTimeSettings.startDate', order: 'ASC' }],
97
+ paging: { limit: 100 }, // ⚠️ MUST be > 0
98
+ }); // → result.events[]
99
+ ```
100
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/query-events.md?apiView=SDK>
101
+
102
+ - **⚠️ CRITICAL: `queryEvents` takes the query object FLAT as its first arg — `queryEvents({ filter, sort, paging })`, NOT `queryEvents({ query: { … } })`.** The signature is `queryEvents(query, options)` where `query` *is* `{ filter, sort, paging }`. Wrapping it in an extra `{ query: … }` (the REST body shape, and the `.queryServices({ query })` builder shape from other verticals) is **not** rejected — the SDK silently ignores the unrecognized `query` key, so `paging` never applies, `limit` defaults to **0**, and you get **`events: []` with no error**. This is the #1 "my listing is empty even though events are published" trap. (The flat form returns the events; the nested form returns zero.)
103
+ - **⚠️ `paging.limit` MUST be > 0.** Even with the flat shape, `queryEvents` defaults `paging.limit` to **`0`, which returns zero events**. Always set a positive limit.
104
+ - The result array is **`result.events`** (not `.items`).
105
+ - **Filter to upcoming/published and never list or link a past event** — a past event isn't purchasable/registerable (the seed uses future dates). Filter by `status` (above) or by a future `startDate`.
106
+ - Read `event._id` / `event.slug` / `event.title`. A **single-event** site collapses the listing — lead the home page straight into the one event's detail. **Still drive that homepage from the listing query** (take the first/only result), never a hardcoded lone slug — so a second event the owner adds later automatically brings the listing back instead of staying invisible.
107
+
108
+ ### One event by slug + its ticket tiers
109
+
110
+ ```js
111
+ const { event } = await wixEventsV2.getEventBySlug(slug, {
112
+ fields: ['DETAILS', 'TEXTS', 'REGISTRATION', 'URLS'], // REGISTRATION carries initialType — you branch on it
113
+ });
114
+
115
+ // ticketed only — list the tiers (VISITOR-public; NOT ticketDefinitions* — those 403 the visitor):
116
+ const { definitions: tiers } = await orders.queryAvailableTickets({
117
+ filter: { eventId: event._id }, limit: 20,
118
+ });
119
+ ```
120
+ Docs: <https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/get-event-by-slug.md?apiView=SDK> · <https://dev.wix.com/docs/api-reference/business-solutions/events/registration/ticketing/orders/query-available-tickets.md?apiView=SDK>
121
+
122
+ - **Request `REGISTRATION` in `fields`** so `event.registration.initialType` is populated — that's the value you branch on.
123
+ - Per tier read `tier._id`, `tier.name`, `tier.price.value` (a **string**) + `tier.price.currency`, `tier.free`, and `tier.saleStatus` (gate the picker on `SALE_STARTED`).
124
+ - **⚠️ The confirmation page (post-checkout) reads the event by ID, and the return envelope DIFFERS from `getEventBySlug`.** After the hosted checkout redirects back to your `postFlowUrl` (carrying `?eventId=…`), look the event up with **`wixEventsV2.getEvent(eventId, { fields: ['TEXTS', 'URLS'] })`** — this returns the **`Event` object DIRECTLY (unwrapped)**: read `event.title` / `event.slug`, **not** `{ event }`. This is the one read that isn't wrapped (`getEventBySlug` *is* `{ event }`); assume the wrapper and the page crashes. Use this exact call — don't inspect the installed `.d.ts` to rediscover it.
125
+
126
+ ### Ticketed checkout — reserve → redirect (the exact sequence)
127
+
128
+ Two steps, both as the visitor. **Use as-is — the payload shapes are easy to get subtly wrong.**
129
+
130
+ ```js
131
+ // 1 · Reserve the selected tiers (PENDING; auto-expires after the event's reservation window).
132
+ const reservation = await ticketReservations.createTicketReservation({
133
+ tickets: selections // one entry per chosen tier, quantity ≥ 1
134
+ .filter((s) => s.quantity > 0)
135
+ .map((s) => ({ ticketDefinitionId: s.ticketDefinitionId, quantity: s.quantity })),
136
+ });
137
+ const reservationId = reservation._id; // ⚠️ _id, not id
138
+
139
+ // 2 · Mint the hosted-checkout redirect and hand off.
140
+ const origin = window.location.origin; // ⚠️ the published https:// host — see below
141
+ const { redirectSession } = await redirects.createRedirectSession({
142
+ eventsCheckout: { reservationId, eventSlug: event.slug },
143
+ callbacks: {
144
+ thankYouPageUrl: `${origin}/event-confirmation`, // Wix appends ?orderNumber=&eventId=
145
+ postFlowUrl: `${origin}/events/${event.slug}`, // back to the event on abandon
146
+ },
147
+ });
148
+ window.location.href = redirectSession.fullUrl; // Wix collects guest details + payment, emails the PDF/QR ticket
149
+ ```
150
+ Docs: <https://dev.wix.com/docs/api-reference/business-solutions/events/registration/ticketing/ticket-reservations/create-ticket-reservation.md?apiView=SDK> · <https://dev.wix.com/docs/api-reference/business-management/headless/redirects/create-redirect-session.md?apiView=SDK>
151
+
152
+ - **⚠️ CRITICAL: don't hand-build the checkout URL.** `{base}/event-details/{slug}/ticket-form?reservationId=…` **404s on a headless site** (there's no Wix-hosted event page). The Redirects API mints a checkout URL on Wix's own domain — `eventsCheckout: { reservationId, eventSlug }` → `redirectSession.fullUrl` is the **only** path that works headless.
153
+ - **⚠️ CRITICAL: the redirect call must run in the VISITOR (headless-OAuth) context — never elevated/admin.** `createRedirectSession` embeds the headless app's `clientId`; an admin/elevated token fails with *"client Id does not correspond to a headless oauth app."* On Astro the **browser island** calls it (ambient visitor client), never a server endpoint; on non-Astro it's the `OAuthStrategy` client. Don't elevate it.
154
+ - **⚠️ CRITICAL: `origin` MUST be the published `https://` host — from `window.location.origin`, never a server-derived `new URL(request.url).origin`.** The Headless redirect allowlist registers the `https://` host and treats `http://<same host>` as a different, unlisted origin; an `http://` `postFlowUrl` makes the return ("Continue Browsing") **403** with *"… isn't listed as an allowed redirect domain."* Pass `window.location.origin` from the client. Doc: <https://dev.wix.com/docs/go-headless/getting-started/setup/manage-urls/add-allowed-redirect-domains>.
155
+ - **⚠️ Handle the paid-ticket precondition softly.** Reserving a **paid** ticket as a visitor fails with **`403 "No payment method configured"`** until the site has a premium plan **and** a configured payment method (a dashboard step the seed already flagged). This is the **real gate** — not a permissions bug, and **not** something elevation should paper over (elevating just creates an unpayable `INITIATED` order). Catch the error; if its message matches `/payment method|not configured|premium/i`, show *"Ticket sales aren't switched on yet — the organizer needs to connect a payment method."* Free / RSVP events are unaffected.
156
+ - Wrap both calls in try/catch (sold out, sale ended, no payment method) and surface a friendly message; don't crash the page.
157
+
158
+ ### Free RSVP — the built-in form
159
+
160
+ ```js
161
+ await rsvpV2.createRsvp({
162
+ eventId: event._id,
163
+ firstName, lastName, email, // the built-in form fields — collect EXACTLY these
164
+ status: 'YES', // 'NO' only for YES_AND_NO events
165
+ });
166
+ // then show an inline confirmation — no reservation, no redirect, no payment
167
+ ```
168
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/events/registration/rsvp-v2/create-rsvp.md?apiView=SDK>
169
+
170
+ - **⚠️ CRITICAL: use the `rsvpV2` module, NOT `rsvp`.** The legacy `rsvp.createRsvp` posts to `/events/v1/rsvp` and **400s** with `"rsvp.firstName/lastName/email must not be empty"` even when you pass those fields — that v1 surface expects a different form-response body. Import **`rsvpV2`** from `@wix/events` and call `rsvpV2.createRsvp(rsvp)` with the rsvp object **directly as the first arg** (not wrapped in `{ rsvp: … }`, which is the elevated/`@wix/essentials` style). The flat `{ eventId, firstName, lastName, email, status }` object is correct for `rsvpV2` and **works for the anonymous visitor**.
171
+ - **The RSVP registration form is built-in** (firstName, lastName, email) — add exactly those fields; **don't fetch a form schema** or hand-build extra fields.
172
+ - Wrap in try/catch — a duplicate email or closed registration rejects; surface a friendly message.
173
+
174
+ ### Rendering & mounting
175
+
176
+ - **Date**: `event.dateAndTimeSettings.formatted.dateAndTime` (already human-formatted) — request the `DETAILS` field to populate it.
177
+ - **Image**: `event.mainImage` is a Wix media ref — render it via the media helper (`@wix/sdk` `media.getScaledToFillImageUrl` / `getImageUrl`); **never** hand-build a `static.wixstatic.com` URL (→ 403).
178
+ - **Price**: `tier.price.value` (string) + `tier.price.currency` (the event's stored currency — format from it, don't assume USD).
179
+ - **Mount the ticket picker / RSVP form in a `client:only="react"` island** (Astro) — they run visitor-session SDK calls and redirect. **SSR only the read pages** (listing/detail) for SEO.
180
+
181
+ ### SEO on item pages (Astro, Wix-managed)
182
+
183
+ An **event detail** page is a Wix **item page**: its `<title>`/description/OG/canonical come from what the owner sets in the dashboard. On the Astro (Wix-managed) frontend, wire it per the canonical guide — **[Add SEO Support to Item Pages](https://dev.wix.com/docs/go-headless/wix-managed-headless/seo/add-seo-support-to-item-pages.md)** — which covers the three steps: export `wixMetadata` (registers the route → sitemap + dashboard SEO editor), call `loadSEOTagsServiceConfig(...)`, and render `<SEO.Tags>` (from `@wix/seo`; deps + `@wix/essentials ≥ 1.0.10` are in the guide's "Before you begin").
184
+
185
+ For an event page use:
186
+ - **`wixMetadata`** from `WIX_APPS.events.eventPageMetadata` — referenced **directly** in the export (module scope). Route param `slug` → `identifiers.slug`.
187
+ - **`itemType`**: `seoTags.ItemType.EVENTS_PAGE`.
188
+
189
+ Fold `loadSEOTagsServiceConfig` into the same `Promise.all` as the ambient `getEventBySlug` read, with `.catch(() => null)` (it needs only the slug — still a visitor-safe ambient call), so a SEO hiccup falls back to the layout's default title. Optional: render an `Event` schema.org JSON-LD `<script>` from the fetched event (see the guide's structured-data step).
190
+
191
+ ### Out of scope
192
+ Assigned seating / seat maps (display + reserve flat ticket definitions only); coupons & gift cards at checkout (Wix's hosted checkout handles those — don't build a discount UI); on-site order management / cancel / refund (handled by the hosted flow + the buyer's email); manual `orders.checkout` inline payment (use the hosted redirect).
193
+
194
+ ---
195
+
196
+ ## Conclusion
197
+ A correct Events V3 registration frontend:
198
+ - imports **`wixEventsV2` / `orders` / `ticketReservations` / `rsvpV2`** from `@wix/events` plus **`redirects`** from `@wix/redirects` — and never inline `orders.checkout` or the legacy `rsvp` (v1 → 400) module;
199
+ - uses **`event._id` / `tier._id`** (never `.id`) and reads the flat fields (`event.slug`, `registration.initialType`, `tier.price.value`);
200
+ - lists with **`queryEvents({ filter, sort, paging })` FLAT** (never `{ query: { … } }` — that silently returns `events: []`) and **`paging.limit > 0`**, filtered to **upcoming/published** events, never past ones;
201
+ - reads ticket tiers with the **visitor-public `orders.queryAvailableTickets({ filter: { eventId }, limit })`** (→ `definitions`) — **never** the management `ticketDefinitions*` query (visitor 403s) and **never** `auth.elevate()` (wrong axis, SSR-only); no elevation anywhere;
202
+ - **branches on `registration.initialType`**: `TICKETING` → reserve (`createTicketReservation` → `reservation._id`) → **`createRedirectSession({ eventsCheckout })`** → `redirectSession.fullUrl`; `RSVP` → **`rsvpV2.createRsvp`** with the built-in firstName/lastName/email and an inline confirmation;
203
+ - runs the reserve/redirect/rsvp **client-side as the visitor** (no server route, no elevation), uses `window.location.origin` (the `https://` host) for the callbacks, and **fails soft** on the `403 "No payment method configured"` paid-ticket precondition.