@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,173 @@
1
+ ---
2
+ name: "How to Code Restaurant Reservations"
3
+ description: The frontend contract for a Wix Table Reservations site — which SDK modules to import, how to read the reservation location, get available time slots, and make a reservation via the hold→reserve flow (or single create). Specifies the *how* (modules + exact calls + failure modes); the restaurant/party details come from the visitor.
4
+ ---
5
+ **RECIPE**: How to Code a Wix Table-Reservations Frontend (Table Reservations)
6
+
7
+ A contract for the **frontend code** that lets a visitor **book a table**: reading the reservation location, fetching available time slots for a date + party size, and creating a reservation. **This recipe is the *how* (which modules, which calls, which fields), not the *what*** — the restaurant, the party size, and the page design come from the request / the visitor's input.
8
+
9
+ > **This recipe is for CODING reservations, not seeding them.** It assumes the backend already exists — the Table Reservations app installed and a reservation location configured with **online reservations enabled** (see `setup-restaurant-reservations.md`). It says nothing about creating or configuring the location — only how visitors read availability and book from frontend code.
10
+
11
+ > **⚠️ Reading rule — always append `.md?apiView=SDK` to every doc link below.** The bare / REST view shows `id`; the `?apiView=SDK` view shows `_id` — and the SDK is what your frontend calls. Reading the REST view is the most common source of the `entity.id`-is-`undefined` bug. Fetch the `.md?apiView=SDK` form directly.
12
+
13
+ > **⚠️ ONLINE RESERVATIONS MUST BE ENABLED (premium) for this flow to work.** The visitor flow reads/creates against a location whose `onlineReservationsEnabled` is `true` — and (per `setup-restaurant-reservations.md`) that toggle is **premium-only** (`428 PREMIUM_ONLY` on a free site). On a non-premium site the location exists and you can *read* it, but time-slot availability / booking won't function. If bookings fail on a site you know is configured, check the site is premium and the toggle is on — it's a provisioning precondition, not a code bug.
14
+
15
+ ---
16
+
17
+ ## The modules and the client (read this first)
18
+
19
+ **One package: `@wix/table-reservations`** — a **distinct** package from `@wix/restaurants` (menus) and from the Orders app. It exposes three namespaces you use:
20
+
21
+ | Need | Package | Module (namespace) |
22
+ |---|---|---|
23
+ | The reservation location (id, party-size bounds) | `@wix/table-reservations` | `reservationLocations` |
24
+ | Available time slots for a date + party size | `@wix/table-reservations` | `timeSlots` |
25
+ | Create / hold / reserve a reservation | `@wix/table-reservations` | `reservations` |
26
+
27
+ **No cart, no `@wix/ecom`, no `@wix/redirects`.** A basic table reservation is a **hold**, not a purchase — there's no checkout in this flow. (Deposit/prepayment reservations exist — status `PAYMENT_INFORMATION_PENDING` — but they're out of scope for the standard book-a-table flow.)
28
+
29
+ **Auth / client — framework split:**
30
+ - **Astro (Wix-managed):** authentication is ambient. Call `reservationLocations` / `timeSlots` / `reservations` directly from server components and backend routes (`src/pages/api/*.ts`) — **no `createClient`, no `OAuthStrategy`, no `clientId`.**
31
+ ```js
32
+ import { reservationLocations, timeSlots, reservations } from '@wix/table-reservations';
33
+ const { reservationLocations: locs = [] } = await reservationLocations.listReservationLocations();
34
+ ```
35
+ - **Non-Astro (Vite/React/Vue/static):** build one manual visitor client and reuse it:
36
+ ```js
37
+ import { createClient, OAuthStrategy } from '@wix/sdk';
38
+ import { reservationLocations, timeSlots, reservations } from '@wix/table-reservations';
39
+
40
+ const client = createClient({
41
+ modules: { reservationLocations, timeSlots, reservations },
42
+ auth: OAuthStrategy({ clientId: /* the project's PUBLIC OAuth client id */ }),
43
+ });
44
+ // then: await client.timeSlots.getTimeSlots(locationId, new Date(date), partySize)
45
+ ```
46
+ The `clientId` is public, not a secret. A mis-wired public env var inlines as `undefined` and 400s every call.
47
+
48
+ ---
49
+
50
+ ## The shapes you read (field cheat-sheet)
51
+
52
+ SDK read shapes (`?apiView=SDK`), so entity ids are **`_id`**.
53
+
54
+ ```jsonc
55
+ // reservationLocations.listReservationLocations() → { reservationLocations: [...] } (no arguments)
56
+ reservationLocation = {
57
+ _id, // → the reservationLocationId every call below needs (NOT .id)
58
+ default, // the auto-provisioned location has default: true
59
+ configuration: { onlineReservations: {
60
+ partySize: { min, max }, // bound the party-size input to this range
61
+ onlineReservationsEnabled, // must be true for the flow to work (premium)
62
+ approval: { mode }, // "AUTOMATIC" → reserve confirms immediately; manual → status REQUESTED
63
+ } },
64
+ }
65
+
66
+ // timeSlots.getTimeSlots(reservationLocationId, date, partySize, options?) → { timeSlots: [...] }
67
+ // NOTE: the SDK types `date` as a Date (NOT the ISO string the REST doc shows) — pass new Date(...)
68
+ timeSlot = {
69
+ startDate, // a Date — pass THIS into createHeldReservation
70
+ duration, // minutes
71
+ status, // "AVAILABLE" | "UNAVAILABLE" | "NON_WORKING_HOURS" — book only AVAILABLE
72
+ manualApproval, // whether this slot needs staff approval
73
+ }
74
+
75
+ // reservations.createHeldReservation({ reservationLocationId, startDate, partySize }) → { reservation: {...} }
76
+ // reservations.reserveReservation(reservationId, reservee, revision) → { reservation: {...} }
77
+ reservation = {
78
+ _id, revision, // keep BOTH from the held reservation — reserve needs the revision
79
+ status, // "HELD" after create → "RESERVED" (auto) or "REQUESTED" (manual approval) after reserve
80
+ }
81
+ ```
82
+
83
+ ---
84
+
85
+ ## The features (build the ones the site needs)
86
+
87
+ Each subsection is a **self-contained feature**. The only ordering is the booking chain itself (location → slots → hold → reserve).
88
+
89
+ ### Reading the reservation location (and the `_id` rule)
90
+
91
+ Get the location so you have its **`_id`** and the party-size bounds for your form. `listReservationLocations()` takes **no arguments**.
92
+
93
+ ```js
94
+ const { reservationLocations: locs = [] } = await reservationLocations.listReservationLocations();
95
+ const loc = locs.find((l) => l.default) ?? locs[0];
96
+ const reservationLocationId = loc._id;
97
+ const { min, max } = loc.configuration?.onlineReservations?.partySize ?? { min: 1, max: 20 };
98
+ ```
99
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/reservation-locations/list-reservation-locations.md?apiView=SDK>
100
+
101
+ **⚠️ CRITICAL: the entity id is `_id`, NOT `id`.** `location.id` / `reservation.id` are `undefined` in SDK code — use `_id`. (A surprising `id` field means you're on the REST doc view — re-open with `?apiView=SDK`.)
102
+
103
+ **⚠️ Default the array (`= []`).** `listReservationLocations()` types the returned array as optional, so destructuring `{ reservationLocations: locs }` and calling `locs.find(...)` directly errors under `strict` / `astro check` (`'locs' is possibly 'undefined'`). Default it, exactly as with the restaurants `list*` methods.
104
+
105
+ ### Getting available time slots
106
+
107
+ Call `getTimeSlots` with **positional** args: the location id, a **`Date` object** (`new Date(selectedDate)` — NOT the ISO string the doc shows; see the CRITICAL note below), the party size, and optional `{ slotsBefore, slotsAfter, duration }`. Then keep the `AVAILABLE` slots.
108
+
109
+ ```js
110
+ const { timeSlots: slots = [] } = await timeSlots.getTimeSlots(
111
+ reservationLocationId,
112
+ new Date(selectedDate), // a Date — the SDK types this param as Date (see callout)
113
+ partySize,
114
+ { slotsBefore: 4, slotsAfter: 4 },
115
+ );
116
+ const available = slots.filter((s) => s.status === 'AVAILABLE');
117
+ ```
118
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/time-slots/get-time-slots.md?apiView=SDK>
119
+
120
+ **⚠️ CRITICAL: `getTimeSlots` takes POSITIONAL args, not a single options object.** The signature is `getTimeSlots(reservationLocationId, date, partySize, options?)` — passing one object (`getTimeSlots({ reservationLocationId, date, partySize })`) does not type-check. Only `slotsBefore`/`slotsAfter`/`duration` go in the 4th `options` arg.
121
+
122
+ **⚠️ CRITICAL: the `date` param is a `Date`, NOT the ISO-8601 string the doc shows (doc/SDK drift).** The REST/SDK doc describes `date` as an ISO-8601 string, but the shipped `@wix/table-reservations` type is **`Date`** — passing `new Date(...).toISOString()` fails to compile (`TS2345: 'string' is not assignable to 'Date'`). Pass a **`Date` object** (`new Date(selectedDate)`). Both the `date` arg you send and each `slot.startDate` you read back are `Date`s — so pass the chosen slot's `startDate` straight into `createHeldReservation`, no conversion.
123
+
124
+ **⚠️ Book only `status === 'AVAILABLE'`.** `UNAVAILABLE` (can't seat that party then) and `NON_WORKING_HOURS` (closed) are also returned — filter them out before presenting slots, or the hold will fail.
125
+
126
+ ### Making a reservation (hold → reserve)
127
+
128
+ The two-step flow from the sample: **hold** the slot (10-minute temporary reservation) while the visitor enters details, then **reserve** it with their name + phone.
129
+
130
+ ```js
131
+ // 1 · hold the slot — startDate is the Date from the chosen AVAILABLE time slot
132
+ const held = await reservations.createHeldReservation({
133
+ reservationLocationId,
134
+ startDate: chosenSlot.startDate,
135
+ partySize,
136
+ });
137
+ // ⚠️ `held.reservation` is OPTIONAL and its `_id`/`revision` are `string | null` in the SDK type —
138
+ // narrow before use or the strict/`astro check` build fails (TS18048 / TS2345).
139
+ if (!held.reservation?._id || !held.reservation.revision) throw new Error('hold failed');
140
+ const reservationId = held.reservation._id;
141
+ const revision = held.reservation.revision; // reserve needs this
142
+
143
+ // 2 · reserve it — reservee needs firstName + phone at minimum
144
+ const done = await reservations.reserveReservation(
145
+ reservationId,
146
+ { firstName, lastName, email, phone },
147
+ revision,
148
+ );
149
+ // done.reservation.status === 'RESERVED' (auto-approval) | 'REQUESTED' (manual approval on)
150
+ ```
151
+ Docs: <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/reservations/create-held-reservation.md?apiView=SDK> · <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/reservations/reserve-reservation.md?apiView=SDK>
152
+
153
+ **⚠️ CRITICAL: `reserveReservation(reservationId, reservee, revision)` takes THREE positional args** — the reservation id, the `reservee` object, and the **`revision`** from the held reservation. Omitting the revision (or wrapping the three in one object) does not type-check. Keep `held.reservation.revision` from step 1.
154
+
155
+ **⚠️ CRITICAL: `reservee.firstName` and `reservee.phone` are required.** A reservation from any `source` other than `WALK_IN` (i.e. every online booking) requires at least `firstName` and `phone` — omitting them returns an error. Collect them in the details form before calling reserve.
156
+
157
+ **⚠️ A `HELD` reservation expires in 10 MINUTES.** If the visitor takes longer than 10 min to confirm, `reserveReservation` returns an error — start a fresh hold. And **do not** call `updateReservation` to move a reservation off `HELD` (it errors); the only way forward from `HELD` is `reserveReservation`.
158
+
159
+ **Result status:** with the seeded default (`approval.mode: "AUTOMATIC"`, manual approval off) the reservation becomes **`RESERVED`** immediately — confirm to the visitor. If the location requires manual approval it becomes **`REQUESTED`** (staff must approve) — tell the visitor it's pending.
160
+
161
+ **Single-shot alternative:** if you collect all details up front (no "hold while they type" step), call `reservations.createReservation({ details: { reservationLocationId, startDate, partySize }, reservee })` instead — same `firstName`/`phone` requirement; it returns `RESERVED`/`REQUESTED` directly, skipping the `HELD` phase. **⚠️ The location/time/party go under a nested `details` object (NOT top-level), and this method returns the `Reservation` DIRECTLY — not wrapped in `{ reservation }`** (unlike `createHeldReservation`/`reserveReservation`). Top-level fields or reading `.reservation` off the result fails to type-check.
162
+ Doc: <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/reservations/create-reservation.md?apiView=SDK>
163
+
164
+ ---
165
+
166
+ ## Conclusion
167
+ A correct Table-Reservations frontend:
168
+ - imports **`reservationLocations` / `timeSlots` / `reservations` from `@wix/table-reservations`** — one package, three namespaces; **no cart / ecom / redirects** (a reservation is a hold, not a purchase);
169
+ - uses **`_id`** (never `id`) for the location and reservation, and **defaults the `list*` array** (`= []`) so strict/`astro check` passes;
170
+ - calls **`getTimeSlots(locationId, new Date(date), partySize, options?)`** with **positional** args — the `date` param is a **`Date`** (not the ISO string the doc shows) — and books only **`status === 'AVAILABLE'`** slots (passing the slot's `Date` `startDate` onward);
171
+ - books via **`createHeldReservation({...})` → `reserveReservation(id, reservee, revision)`** (three positional args; `firstName` + `phone` required; 10-minute hold; `reserveReservation` is the only exit from `HELD`);
172
+ - treats **`onlineReservationsEnabled` (premium)** as a precondition — the read/book flow only works once it's on.
173
+ </content>
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: "How to Code Restaurants"
3
+ description: The frontend read contract for a Wix Restaurants Menus site — which SDK modules to import, how to list menus/sections/items, how to re-order them by the parent's id arrays, how to read prices from priceInfo, and the _id / image gotchas the docs omit. Specifies the *how* (modules + exact calls + failure modes); which menu to render comes from the request.
4
+ ---
5
+ **RECIPE**: How to Code a Wix Restaurants Frontend (Menus V1 — display-only)
6
+
7
+ A concise contract for writing the **frontend code** that renders a Wix Restaurants **menu**: listing the menu, its sections, and their items, assembling the hierarchy in display order, and reading each item's price. **This recipe is the *how* (which modules, which calls, which fields), not the *what*** — which menu to show and how the page looks are decided by the request you're fulfilling.
8
+
9
+ > **This recipe is for CODING the menu display, not for seeding it.** It assumes a Restaurants Menus backend already exists (a menu, its sections, its items). It says nothing about creating them — only how to read and render them from frontend code.
10
+
11
+ > **Menus are DISPLAY-ONLY here.** The Wix Restaurants **Menus** app is a catalog for *showing* a menu — there is no cart, no checkout, no `variantId`, no `@wix/ecom` in this recipe. **Online ordering** (add-to-cart / checkout) and **table reservations** are **separate apps** (`@wix/restaurants` Orders / the distinct `@wix/table-reservations` package, installed only if the request calls for them) and are out of scope. If the site only shows a menu, you import one package and make read calls — nothing else.
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 `entity.id`-is-`undefined` bug. Fetch the `.md?apiView=SDK` form directly; don't re-discover these with search.
14
+
15
+ ---
16
+
17
+ ## The modules and the client (read this first)
18
+
19
+ **One package for menu display: `@wix/restaurants`.** It exposes three namespaces you read from — one per level of the hierarchy:
20
+
21
+ | Need | Package | Module (namespace) |
22
+ |---|---|---|
23
+ | Menus (list / get) | `@wix/restaurants` | `menus` |
24
+ | Sections (list / get) | `@wix/restaurants` | `sections` |
25
+ | Items (list / get) | `@wix/restaurants` | `items` |
26
+
27
+ The hierarchy is **Menu → Sections → Items**, wired by **id arrays**: a `menu.sectionIds[]` points at its sections, a `section.itemIds[]` points at its items. You read each level separately and stitch them together (see *Assembling the menu*).
28
+
29
+ **Auth / client — framework split:**
30
+ - **Astro (Wix-managed):** authentication is ambient. Call `menus` / `sections` / `items` directly from server components and backend routes (`src/pages/api/*.ts`) — **no `createClient`, no `OAuthStrategy`, no `clientId`.**
31
+ ```js
32
+ import { menus, sections, items } from '@wix/restaurants';
33
+ const { menus: menuList } = await menus.listMenus({ onlyVisible: true });
34
+ ```
35
+ - **Non-Astro (Vite/React/Vue/static):** build one manual visitor client and reuse it:
36
+ ```js
37
+ import { createClient, OAuthStrategy } from '@wix/sdk';
38
+ import { menus, sections, items } from '@wix/restaurants';
39
+
40
+ const client = createClient({
41
+ modules: { menus, sections, items },
42
+ auth: OAuthStrategy({ clientId: /* the project's PUBLIC OAuth client id */ }),
43
+ });
44
+ // then: await client.menus.listMenus({ onlyVisible: true })
45
+ ```
46
+ The `clientId` is public, not a secret. A mis-wired public env var inlines as `undefined` and 400s every call.
47
+
48
+ ---
49
+
50
+ ## The shapes you read (field cheat-sheet)
51
+
52
+ The exact field paths the frontend reads. These are **SDK read shapes** (`?apiView=SDK`), so ids are **`_id`**. Price is a decimal **string**.
53
+
54
+ ```jsonc
55
+ // menus.listMenus({ onlyVisible: true }) → { menus: [...] }
56
+ menu = {
57
+ _id, // entity id (NOT .id → undefined in SDK code)
58
+ name, description, visible,
59
+ sectionIds, // ORDERED array of section _ids — the section display order lives HERE
60
+ urlQueryParam, // slug fragment for the menu URL
61
+ }
62
+
63
+ // sections.listSections({ onlyVisible: true }) → { sections: [...] }
64
+ section = {
65
+ _id, name, description, visible,
66
+ itemIds, // ORDERED array of item _ids — the item display order lives HERE
67
+ image, // OPTIONAL media id STRING (wix:image://…) or absent — see Rendering images
68
+ }
69
+
70
+ // items.listItems({ onlyVisible: true }) → { items: [...] }
71
+ item = {
72
+ _id, name, description, visible,
73
+ priceInfo: { price }, // PRICE. price is a decimal STRING ("9.50"), NO currency symbol. The SDK `PriceInfo` type carries ONLY `price` — there is no `formattedPrice`
74
+ image, // OPTIONAL — a media id STRING (wix:image://…) or absent (text-only seed). NOT an object: resolve it, never read image.url
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## The features (build the ones the site needs)
81
+
82
+ Each section below is a **self-contained feature** — implement only what the site uses. The only ordering is *within* the assembly (fetch levels before you stitch them).
83
+
84
+ ### Listing menus / sections / items (and the `_id` rule)
85
+
86
+ Use the `list*` methods — they take a simple options object and return a plain array, with no query-builder ceremony:
87
+
88
+ ```js
89
+ const { menus: menuList } = await menus.listMenus({ onlyVisible: true });
90
+ const { sections: allSecs } = await sections.listSections({ onlyVisible: true });
91
+ const { items: allItems } = await items.listItems({ onlyVisible: true });
92
+ ```
93
+ Docs: <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/menus/menus/list-menus.md?apiView=SDK> · <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/menus/sections/list-sections.md?apiView=SDK> · <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/menus/items/items/list-items.md?apiView=SDK>
94
+
95
+ **✅ PREFER `list*` over `query*` for reads.** `listMenus` / `listSections` / `listItems` take an options object (`{ onlyVisible, paging, menuIds/sectionIds/itemIds }`) and are unambiguous. The `queryMenus` / `queryItems` methods exist but their argument shape (object-param vs. fluent builder) is a known SDK-doc drift hotspot across Wix packages — avoid them for simple reads. To fetch a specific subset by id, pass the id array to the list method: `items.listItems({ itemIds: section.itemIds })`.
96
+
97
+ **⚠️ CRITICAL: the entity id is `_id`, NOT `id`.** The SDK normalizes every entity's id to **`_id`**. `menu.id` / `section.id` / `item.id` are `undefined` in SDK code. Use `_id` everywhere — when following `sectionIds` / `itemIds`, when building links, and as React keys. (If a field name surprises you, you are probably reading the REST doc view — re-open it with `?apiView=SDK`.)
98
+
99
+ **Visibility:** pass `onlyVisible: true`, and note only entities seeded `visible: true` are returned to a visitor token anyway — a missing section/item usually means it wasn't seeded visible, not a query bug (ties back to the seed recipe).
100
+
101
+ ### Assembling the menu (follow the id arrays — and preserve their order)
102
+
103
+ The three `list*` calls return **flat, unordered** arrays. The display structure and order live in the parent's id arrays (`menu.sectionIds`, `section.itemIds`), so stitch by looking entities up by `_id` **in id-array order** — do **not** render the raw `list*` order.
104
+
105
+ ```js
106
+ const byId = (arr) => new Map(arr.map((e) => [e._id, e]));
107
+ const secById = byId(allSecs);
108
+ const itemById = byId(allItems);
109
+
110
+ const menu = menuList[0]; // or match by urlQueryParam / name per the request
111
+ const structured = {
112
+ ...menu,
113
+ sections: (menu.sectionIds ?? [])
114
+ .map((sid) => secById.get(sid))
115
+ .filter(Boolean) // a stale id (deleted section) → skip, don't crash
116
+ .map((sec) => ({
117
+ ...sec,
118
+ items: (sec.itemIds ?? [])
119
+ .map((iid) => itemById.get(iid))
120
+ .filter(Boolean),
121
+ })),
122
+ };
123
+ ```
124
+
125
+ **⚠️ CRITICAL: order comes from `sectionIds` / `itemIds`, NOT from the `list*` response order.** `listSections` / `listItems` return entities in arbitrary (creation/internal) order. If you render `allSecs` / `allItems` directly, the menu shows "Desserts" before "Starters" and items in a scrambled order. Always map over the parent's ordered id array and look each child up by `_id`. **`.filter(Boolean)`** after each lookup so a dangling id (a child deleted out from under the menu) is skipped rather than rendering `undefined`.
126
+
127
+ ### Reading the price
128
+
129
+ Read **`item.priceInfo.price`** — a decimal **string** (`"9.50"`) with **no currency symbol**. Render it directly, or `Number(item.priceInfo.price)` if you need arithmetic, and prefix your site's currency in the UI.
130
+
131
+ **⚠️ CRITICAL: price is under `priceInfo.price`, not a top-level `price` field — and there is NO `formattedPrice` on the SDK type.** Two traps here:
132
+ - The old top-level `item.price` is **deprecated** and reads `undefined` against seeded data → `$NaN` on the page. Always read `item.priceInfo.price`.
133
+ - The SDK's `PriceInfo` type is **`{ price?: string }`** only. `item.priceInfo.formattedPrice` **does not type-check** (`TS2339`) — even though the REST response happens to include a `formattedPrice`, the SDK type omits it, and the frontend calls the SDK. Do **not** read `formattedPrice`; format the currency yourself from `price` (the amount carries no symbol).
134
+
135
+ ### Rendering images (only when imagery is on)
136
+
137
+ Menus are seeded **text-only by default**, so `section.image` / `item.image` are usually **absent** — guard for that and render a text-only card when missing. **`image` is a bare STRING** (the SDK types both `Section.image` and `Item.image` as `image?: string`) — a media identifier, usually a `wix:image://…`, occasionally an already-absolute URL. It is **not** an object, so **never read `image.url`** (`TS2339` — the recipe's earlier draft got this wrong). Resolve a `wix:image://` string through the helper (never put it straight into `<img src>` — it fails with `ERR_UNKNOWN_URL_SCHEME`):
138
+
139
+ ```js
140
+ import { media } from '@wix/sdk';
141
+ function imgSrc(image, w = 600, h = 600) {
142
+ if (!image) return ''; // absent (text-only) → caller renders a text card
143
+ if (image.startsWith('wix:image://')) return media.getScaledToFillImageUrl(image, w, h, {}); // 4th arg REQUIRED
144
+ return image; // already an absolute https URL
145
+ }
146
+ ```
147
+
148
+ **⚠️ `media.getScaledToFillImageUrl` takes FOUR arguments** in `@wix/sdk` — `(wixMediaIdentifier, width, height, options)`. The `options` object is **required** (unlike `getCroppedImageUrl`, whose `options?` is optional); a 3-arg call fails with `TS2554: Expected 4 arguments, but got 3`. Pass `{}` when you have no transform options.
149
+
150
+ Never hand-build a `static.wixstatic.com/.../v1/fit/...` URL — the format is easy to get wrong and the image then 403s. Doc: <https://dev.wix.com/docs/sdk/core-modules/sdk/media>
151
+
152
+ ---
153
+
154
+ ## Conclusion
155
+ A correct Restaurants Menus frontend:
156
+ - imports **`menus` / `sections` / `items` from `@wix/restaurants`** — one package, three read namespaces; **no cart / checkout / ecom** (menus are display-only; ordering & reservations are separate apps);
157
+ - uses **`_id`** (never `id`) as every entity's id and when following `sectionIds` / `itemIds`;
158
+ - prefers the **`list*`** methods (option-object) over the drift-prone `query*` builders for reads;
159
+ - **assembles menu → sections → items in the order of the parent's `sectionIds` / `itemIds` arrays** (not the `list*` response order), `.filter(Boolean)` to drop dangling ids;
160
+ - reads price from **`item.priceInfo.price`** (a decimal string, no currency; **no `formattedPrice` on the SDK type**) — never the deprecated top-level `price`;
161
+ - treats `image` as an **optional string** (never `image.url`) and resolves `wix:image://` values through **`media.getScaledToFillImageUrl(id, w, h, {})`** (4 args), never raw.
@@ -0,0 +1,175 @@
1
+ ---
2
+ name: "Setup Blog"
3
+ description: Initializes a Wix Blog with Blog V3 — fetches an author memberId, then bulk-creates published posts with Ricos rich content (text-only), and optionally creates + assigns categories/tags. Specifies the *how* (calls + format); how many posts, their topics, and which categories come from the request being fulfilled.
4
+ ---
5
+ **RECIPE**: Business Recipe – Initial Setup for a Wix Blog (Blog V3)
6
+
7
+ > **Standard call shape (every curl below).** The `<AUTH>` placeholder is shorthand for `Authorization: Bearer <TOKEN>` only. Body-bearing requests also need `Content-Type: application/json`.
8
+
9
+ A concise checklist for populating any new Wix site that has the Blog app installed with Blog V3.
10
+ **Notice** that this recipe is **NOT** meant for coding purposes and is **ONLY** meant for initial blog content setup.
11
+
12
+ > **This recipe is the *how*, not the *what*.** What to seed — how many posts, which topics, whether to group them into categories/tags — is determined by the request you're fulfilling. This recipe only specifies the calls and the request format; it does not decide quantities or topics.
13
+
14
+ > **API surfaces:** posts use Blog V3 (`https://www.wixapis.com/blog/v3/...`). The author lookup is the exception — it lives on the Members API (`https://www.wixapis.com/members/v1/members`). Don't mix in any pre-V3 blog endpoints.
15
+
16
+ ---
17
+
18
+ ## Article: Steps for Setting Up a Wix Blog
19
+ **YOU MUST** complete all the following steps **in the given order** (1-3), then **Attach images** when `imagery` is on, without skipping any and **without requiring additional user input**.
20
+
21
+ **⚠️ CRITICAL ORDER REQUIREMENT: Fetch the author `memberId` FIRST — every post create needs it. Create the posts. Categories/tags are optional and only created if the request names them. Covers are added in the **Attach images** step, only when `imagery` is on.**
22
+
23
+ ### STEP 1: Get an author `memberId` (required for 3rd-party callers)
24
+
25
+ When calling the Blog API as a 3rd-party app (headless, not the site owner in the dashboard), every post create needs `memberId` — the post's author. Omitting it fails with `"Missing post owner information"`.
26
+
27
+ **⚠️ `memberId` is *author attribution*, not the caller.** Two identities are in play and they are NOT the same: the **caller** is the **APP** (your admin/CLI token — `CreateDraftPost` is an admin-only method, `applicableIdentities: [APP]`), while `memberId` is a **body field** meaning *"the draft post owner's member ID"* — whom to credit as author. The dashboard supplies the author implicitly (the logged-in human); a headless APP token isn't a person, so it must **name** one — that's the whole reason for this lookup. Consequence: this does **not** mean a logged-in member can author posts from their own session — every draft-post write/query method is APP-only. (Member-native blog features are **likes** and **comments**; see `how-to-code-a-blog.md`.)
28
+
29
+ List the first site member and keep its id:
30
+
31
+ ```bash
32
+ curl -sS -X GET "https://www.wixapis.com/members/v1/members?fieldsets=PUBLIC&paging.limit=1" \
33
+ -H "Authorization: <AUTH>"
34
+ ```
35
+
36
+ Read `members[0].id` (a.k.a. `_id`) from the response — that's the `memberId` you pass to every post in Step 2.
37
+
38
+ **⚠️ CRITICAL: the `memberId` must belong to a real site member/collaborator** — never fabricate one (a made-up id fails the create with `"memberIds ... do not exist"`). A provisioned site normally has the owner as a member, so this GET returns at least one id. **If the list comes back empty**, the documented fallback is to **create a member first** (find the Members API create method via `DOC_DISCOVERY.md` — don't guess its URL/body) and use that id, or use the site owner's member id. Only if neither is possible, **fail loudly** with the empty-members response.
39
+
40
+ ### STEP 2: Bulk-create the posts (published, with Ricos content)
41
+
42
+ Create the posts in a **single bulk request** to `POST https://www.wixapis.com/blog/v3/bulk/draft-posts/create` with `"publish": true` so they go live immediately. **How many posts and their topics are set by the request you're fulfilling — this step only gives the call and the required format.** Each post is **text-only** (no cover image — imagery is attached later in the dedicated images step only when `imagery` is on; `SEED.md` § "Entity images").
43
+
44
+ > **Use the bulk endpoint whenever `postCount ≥ 2`** — one call replaces N single-post calls, each of which costs ~25–30 s of latency. For exactly one post, use the single-post endpoint shown at the end of this step.
45
+
46
+ **⚠️ CRITICAL: the correct URL is `/blog/v3/bulk/draft-posts/create`** — `bulk` is a path segment **between** `v3` and `draft-posts`, not a suffix. Both `/blog/v3/draft-posts/bulk` and `/blog/v3/draft-posts/bulk-create` return **404**.
47
+
48
+ **⚠️ CRITICAL: each item in `draftPosts` is a FLAT post object — do NOT wrap it in a `draftPost` field.** The single-post endpoint uses the `{ "draftPost": {…} }` envelope because the request *is* one post; the bulk endpoint flattens that envelope away because the array itself is the envelope. Wrapping each item in `draftPost` returns `400 "draftPosts[i].title must not be empty"` (the API looks for `draftPosts[i].title` directly and finds it nested). Put `title` / `memberId` / `richContent` **directly** inside each array element.
49
+
50
+ **Request body shape** (one representative post shown — repeat post objects inside the `draftPosts` array):
51
+
52
+ ```json
53
+ {
54
+ "draftPosts": [
55
+ {
56
+ "title": "How We Roast Our Single-Origin Beans",
57
+ "memberId": "<memberId-from-step-1>",
58
+ "richContent": {
59
+ "nodes": [
60
+ {
61
+ "type": "HEADING",
62
+ "id": "n1",
63
+ "nodes": [
64
+ { "type": "TEXT", "id": "", "nodes": [], "textData": { "text": "From farm to cup", "decorations": [] } }
65
+ ],
66
+ "headingData": { "level": 2 }
67
+ },
68
+ {
69
+ "type": "PARAGRAPH",
70
+ "id": "n2",
71
+ "nodes": [
72
+ { "type": "TEXT", "id": "", "nodes": [], "textData": { "text": "Every batch starts with beans sourced from a single estate.", "decorations": [] } }
73
+ ],
74
+ "paragraphData": {}
75
+ },
76
+ {
77
+ "type": "BLOCKQUOTE",
78
+ "id": "n3",
79
+ "nodes": [
80
+ {
81
+ "type": "PARAGRAPH",
82
+ "id": "n4",
83
+ "nodes": [
84
+ { "type": "TEXT", "id": "", "nodes": [], "textData": { "text": "Great coffee is grown, not made.", "decorations": [] } }
85
+ ],
86
+ "paragraphData": {}
87
+ }
88
+ ],
89
+ "blockquoteData": { "indentation": 1 }
90
+ }
91
+ ]
92
+ }
93
+ }
94
+ ],
95
+ "publish": true
96
+ }
97
+ ```
98
+
99
+ **⚠️ CRITICAL RICOS NESTING — `richContent` is Ricos JSON, not a string or HTML.** A plain string or an HTML blob is rejected. Build a `{ "nodes": [...] }` tree following these rules, or you get `"Expected a paragraph node but found TEXT"`:
100
+ - **`TEXT` is always a leaf** inside a container — never a direct child of `BLOCKQUOTE`, `LIST_ITEM`, `CODE_BLOCK`, or the root.
101
+ - **`BLOCKQUOTE` and `LIST_ITEM` contain `PARAGRAPH` nodes**, which then contain the `TEXT`.
102
+ - **`BULLETED_LIST` / `ORDERED_LIST` contain `LIST_ITEM` nodes**, which contain `PARAGRAPH` → `TEXT`.
103
+ - **Container nodes (`PARAGRAPH`, `HEADING`, `BLOCKQUOTE`, …) need a unique `id`** (any string, e.g. `"n1"`, `"n2"`); `TEXT` leaves may use `"id": ""`.
104
+ - Common node types: `PARAGRAPH` (body), `HEADING` (`headingData.level` 2–4), `CODE_BLOCK` (`codeBlockData.language`), `BULLETED_LIST`/`ORDERED_LIST` + `LIST_ITEM`, `BLOCKQUOTE`. Mix at least a few per post for visual variety.
105
+
106
+ **⚠️ CRITICAL: omit `media` — seed text-only.** Cover/inline images are attached in the dedicated **Attach images** step **only when `imagery` is on** (`SEED.md` § "Entity images"). Do not pass external image URLs into `media` or `richContent` `IMAGE` nodes here — external URLs don't work directly (they must first be imported to Wix Media), and imagery is opt-in.
107
+
108
+ **⚠️ Reading the response — bulk results carry only ids, not slugs.** A successful bulk create returns `200` with:
109
+
110
+ ```json
111
+ { "results": [
112
+ { "itemMetadata": { "id": "<postId>", "originalIndex": 0, "success": true } }
113
+ ] }
114
+ ```
115
+
116
+ The bulk call returns `200` **even if some items fail** — check each `results[i].itemMetadata.success` individually; it does **not** throw on partial failure. If part of the batch fails, retry **only the failed items** **once** with the exact same format; do not loop. (You need only confirm each post was created — the frontend links posts by **slug read from a live `queryPosts` result / the URL**, so there's no need to collect slugs at seed time.)
117
+
118
+ **⚠️ CRITICAL: a transient `401 "No identity found"` on draft-post creation is a known server-side async-identity defect, NOT a body error.** It is not caused by your token or payload (categories/members/CMS calls succeed with the same token). If you hit it, **retry the create once**; do not rewrite the body and do not retry-spiral — a spiralling retry is a wasted headless run.
119
+
120
+ #### Single-post endpoint (only when `postCount = 1`)
121
+
122
+ `POST https://www.wixapis.com/blog/v3/draft-posts` with the **nested** envelope and `publish: true`:
123
+
124
+ ```json
125
+ {
126
+ "draftPost": {
127
+ "title": "How We Roast Our Single-Origin Beans",
128
+ "memberId": "<memberId-from-step-1>",
129
+ "richContent": { "nodes": [ /* same Ricos tree as above */ ] }
130
+ },
131
+ "publish": true
132
+ }
133
+ ```
134
+
135
+ ### STEP 3: Group posts into categories / tags (optional — only if the request names them)
136
+
137
+ Only create categories or tags **if the request explicitly groups the posts** (e.g. "a blog with Recipes and Brewing-Tips sections"). If it doesn't, **create none** — skip this step entirely (skill policy; overrides any docs default).
138
+
139
+ - **Categories:** `POST https://www.wixapis.com/blog/v3/categories` per category; keep each returned category `id`.
140
+ - **Tags:** `POST https://www.wixapis.com/blog/v3/tags` per tag; keep each returned tag `id`.
141
+ - **Assign:** include the resolved ids in each post's `categoryIds` / `tagIds` array — set them **in the Step-2 create body** when you already know the grouping, or PATCH the post afterward via **`PATCH https://www.wixapis.com/blog/v3/draft-posts/{draftPostId}`** (body wrapped in `draftPost`). **⚠️ NOT `POST …/draft-posts/{id}/update`** — that path 404s for a single post; `/update` exists only as the bulk method.
142
+
143
+ **⚠️ CRITICAL: re-publish after any PATCH.** Updating an already-published post sets `hasUnpublishedChanges: true` — the live site keeps showing the old version until you call `POST https://www.wixapis.com/blog/v3/draft-posts/{draftPostId}/publish` again. (Seeding categoryIds/tagIds directly in the Step-2 create body avoids this round-trip.)
144
+
145
+ > **Comments (a Required site feature, conditional).** If the request's blog needs reader comments, comments are typically available once the Blog app is installed — record it as **available** so the Handoff tells the host to surface the comment UI (the coding recipe wires read-public / write-authenticated). Only if comments are off by default for this site, enable the feature — find the check/enable method via `DOC_DISCOVERY.md` — before relying on it. Don't seed comment *content*.
146
+
147
+ ### Attach images (imagery ON only)
148
+
149
+ **Runs only when `imagery` is on** (`SEED.md` § "Entity images"). If imagery is off, **skip this step entirely** — the posts were seeded text-only in the bulk-create step and stay that way. This is the pass-2 "attach the image" step for blog posts (the create is pass-1, text-first).
150
+
151
+ For each post that should get a cover:
152
+
153
+ 1. **Generate + import** per `references/IMAGE_GENERATION.md` (§1 Generate, §2 Import). From the imported `file` object keep **`file.id`** — the WixMedia file id (e.g. `<hash>~mv2.jpg`). Blog binds the cover **by this id** (not by `file.url`).
154
+ 2. **Attach the cover** via **`PATCH https://www.wixapis.com/blog/v3/draft-posts/{draftPostId}`** (body wrapped in a `draftPost` object), writing the cover under `media`:
155
+
156
+ ```json
157
+ { "draftPost": { "media": { "displayed": true, "custom": true, "wixMedia": { "image": { "id": "<file.id>" } } } } }
158
+ ```
159
+
160
+ **⚠️ CRITICAL: the endpoint is `PATCH …/draft-posts/{draftPostId}` — NOT `POST …/draft-posts/{draftPostId}/update`.** The `/update` path **404s** for a single post (it exists only as the *bulk* update method); use the bare `PATCH` on the id.
161
+ **⚠️ CRITICAL: `media.wixMedia.image.id` ALONE is a silent no-op.** The PATCH returns `200` but the response comes back `media: { "displayed": false, "custom": false }` with no `wixMedia`, and **no cover attaches**. You MUST also set **`media.displayed: true`** and **`media.custom: true`** for the cover to persist. A `200` is therefore **not** proof — re-query the post's `media` and confirm `wixMedia.image` populated.
162
+ 3. **⚠️ Re-publish after the PATCH.** Updating an already-published post sets `hasUnpublishedChanges: true` / unpublishes it, so the live site keeps showing the old cover-less version until you call `POST https://www.wixapis.com/blog/v3/draft-posts/{draftPostId}/publish` again. (Same re-publish rule as the categories/tags step — don't let the two drift.)
163
+
164
+ **Never block the run on image failure** — on a generation/import/attach failure, skip that cover and leave the post text-only (`IMAGE_GENERATION.md` § "Never block the run on image failure").
165
+
166
+ ---
167
+
168
+ ## Conclusion
169
+ Following these steps **in order** populates a new Blog V3 site:
170
+ - Every post is authored by a **real `memberId`** (fetched first) and created **`publish: true`**, so it appears live immediately.
171
+ - Posts carry valid **Ricos `richContent`** (correct `TEXT`-in-`PARAGRAPH` nesting), in the count and on the topics called for by the request.
172
+ - The **bulk** endpoint is used for `postCount ≥ 2` (flat per-item shape), the single endpoint for one post.
173
+ - Posts are seeded **text-only**; covers are attached by the **Attach images** step, only when `imagery` is on (`PATCH …/draft-posts/{id}` with `media.wixMedia.image.id = file.id` **plus `media.displayed:true` + `media.custom:true`**, then re-publish), otherwise they stay text-only.
174
+ - Categories/tags exist **only if** the request named them, with posts assigned and re-published after any PATCH.
175
+ - Posts are then discovered **live** by the frontend (`queryPosts`, `[...slug]` routes) — no per-post ids/slugs need to be carried into the coding handoff.