@wix/agent-skills 1.21.0 → 1.23.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 (269) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +71 -7
  3. package/skills/wix-app/references/APP_VALIDATION.md +16 -10
  4. package/skills/wix-app/references/DASHBOARD_PAGE.md +11 -25
  5. package/skills/wix-app/references/DATA_COLLECTION.md +16 -219
  6. package/skills/wix-app/references/SDK_MODULE_MAP.md +2 -0
  7. package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +182 -0
  8. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +97 -0
  9. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md +184 -0
  10. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +203 -0
  11. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_SETTINGS.md +44 -0
  12. package/skills/wix-app/references/dashboard-page/QUERY_AND_PAGING.md +182 -0
  13. package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +133 -0
  14. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +10 -5
  15. package/skills/wix-app/references/data-collection/LIFECYCLE.md +68 -0
  16. package/skills/wix-app/references/data-collection/PERMISSIONS.md +47 -0
  17. package/skills/wix-app/references/data-collection/SCHEMA.md +181 -0
  18. package/skills/wix-app/references/data-collection/WIX_DATA.md +38 -66
  19. package/skills/wix-headless-fast/SKILL.md +95 -230
  20. package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
  21. package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +17 -14
  22. package/skills/wix-headless-fast/guides/existing-site.md +78 -0
  23. package/skills/wix-headless-fast/guides/migration.md +43 -0
  24. package/skills/wix-headless-fast/guides/reference-mode.md +100 -0
  25. package/skills/wix-headless-fast/install/AGENTS.md +9 -4
  26. package/skills/wix-headless-fast/install/agents-md.mjs +5 -1
  27. package/skills/wix-headless-fast/install/attach.mjs +25 -47
  28. package/skills/wix-headless-fast/install/check.mjs +87 -0
  29. package/skills/wix-headless-fast/install/context.mjs +126 -0
  30. package/skills/wix-headless-fast/install/deploy.mjs +106 -80
  31. package/skills/wix-headless-fast/install/lock.mjs +55 -0
  32. package/skills/wix-headless-fast/install/setup.mjs +83 -23
  33. package/skills/wix-headless-fast/install/templates.mjs +168 -0
  34. package/skills/wix-manage/SKILL.md +3 -3
  35. package/skills/wix-manage/references/app-installation/install-wix-apps.md +68 -2
  36. package/skills/wix-manage/references/contacts/bulk-label-and-unlabel-contacts.md +37 -4
  37. package/skills/wix-manage/references/ecommerce/ecom-pricing.md +29 -3
  38. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +27 -0
  39. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +83 -37
  40. package/skills/wix-manage/references/sites/site-import.md +101 -37
  41. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -303
  42. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +0 -136
  43. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +0 -112
  44. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +0 -42
  45. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +0 -31
  46. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +0 -22
  47. package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +0 -137
  48. package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +0 -78
  49. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +0 -117
  50. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +0 -52
  51. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +0 -47
  52. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +0 -58
  53. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +0 -62
  54. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +0 -40
  55. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +0 -97
  56. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +0 -24
  57. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +0 -16156
  58. package/skills/wix-headless-fast/references/blog/rest/posts.ts +0 -42
  59. package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +0 -62
  60. package/skills/wix-headless-fast/references/blog/seed/SEED.md +0 -81
  61. package/skills/wix-headless-fast/references/blog/seed/read-site.mjs +0 -22
  62. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +0 -287
  63. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -277
  64. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +0 -144
  65. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +0 -119
  66. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +0 -32
  67. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +0 -23
  68. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +0 -218
  69. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +0 -169
  70. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +0 -121
  71. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +0 -92
  72. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +0 -90
  73. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +0 -57
  74. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +0 -72
  75. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +0 -40
  76. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +0 -76
  77. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +0 -22
  78. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +0 -11962
  79. package/skills/wix-headless-fast/references/bookings/rest/booking.ts +0 -113
  80. package/skills/wix-headless-fast/references/bookings/rest/services.ts +0 -55
  81. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +0 -71
  82. package/skills/wix-headless-fast/references/bookings/seed/read-site.mjs +0 -28
  83. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +0 -302
  84. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -355
  85. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +0 -50
  86. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +0 -37
  87. package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +0 -158
  88. package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +0 -93
  89. package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +0 -177
  90. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +0 -123
  91. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +0 -75
  92. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +0 -41
  93. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +0 -11262
  94. package/skills/wix-headless-fast/references/cms/rest/items.ts +0 -125
  95. package/skills/wix-headless-fast/references/cms/seed/SEED.md +0 -112
  96. package/skills/wix-headless-fast/references/cms/seed/read-site.mjs +0 -20
  97. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +0 -324
  98. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -307
  99. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +0 -66
  100. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +0 -178
  101. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +0 -118
  102. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +0 -35
  103. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +0 -24
  104. package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +0 -130
  105. package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +0 -97
  106. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +0 -55
  107. package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +0 -113
  108. package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +0 -156
  109. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +0 -97
  110. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +0 -61
  111. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +0 -40
  112. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +0 -12
  113. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +0 -80
  114. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +0 -21
  115. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +0 -11884
  116. package/skills/wix-headless-fast/references/events/rest/events.ts +0 -57
  117. package/skills/wix-headless-fast/references/events/rest/registration.ts +0 -83
  118. package/skills/wix-headless-fast/references/events/seed/SEED.md +0 -95
  119. package/skills/wix-headless-fast/references/events/seed/read-site.mjs +0 -26
  120. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +0 -276
  121. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +0 -340
  122. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +0 -85
  123. package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +0 -332
  124. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +0 -238
  125. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +0 -54
  126. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +0 -216
  127. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +0 -59
  128. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +0 -135
  129. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +0 -10593
  130. package/skills/wix-headless-fast/references/forms/rest/forms.ts +0 -34
  131. package/skills/wix-headless-fast/references/forms/rest/submissions.ts +0 -56
  132. package/skills/wix-headless-fast/references/forms/seed/SEED.md +0 -116
  133. package/skills/wix-headless-fast/references/forms/seed/read-site.mjs +0 -20
  134. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +0 -327
  135. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -316
  136. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +0 -60
  137. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +0 -155
  138. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +0 -78
  139. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +0 -47
  140. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +0 -66
  141. package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +0 -105
  142. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +0 -59
  143. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +0 -53
  144. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +0 -122
  145. package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +0 -43
  146. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +0 -29
  147. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +0 -21
  148. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +0 -42
  149. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +0 -10
  150. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +0 -11
  151. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +0 -10329
  152. package/skills/wix-headless-fast/references/members/rest/auth.ts +0 -215
  153. package/skills/wix-headless-fast/references/members/rest/members.ts +0 -26
  154. package/skills/wix-headless-fast/references/members/seed/SEED.md +0 -39
  155. package/skills/wix-headless-fast/references/members/seed/read-site.mjs +0 -15
  156. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +0 -94
  157. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -315
  158. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +0 -110
  159. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +0 -90
  160. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +0 -35
  161. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +0 -85
  162. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +0 -32
  163. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +0 -21
  164. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +0 -31
  165. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +0 -82
  166. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +0 -58
  167. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +0 -177
  168. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +0 -78
  169. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +0 -81
  170. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +0 -55
  171. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +0 -40
  172. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +0 -30
  173. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +0 -21
  174. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +0 -29
  175. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +0 -10197
  176. package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +0 -75
  177. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +0 -86
  178. package/skills/wix-headless-fast/references/portfolio/seed/read-site.mjs +0 -20
  179. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +0 -256
  180. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -296
  181. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +0 -47
  182. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +0 -101
  183. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +0 -41
  184. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +0 -16
  185. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +0 -22
  186. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +0 -54
  187. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +0 -106
  188. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +0 -64
  189. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +0 -27
  190. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +0 -43
  191. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +0 -22
  192. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +0 -30
  193. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +0 -41
  194. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +0 -40
  195. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +0 -21
  196. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +0 -11226
  197. package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +0 -31
  198. package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +0 -20
  199. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +0 -79
  200. package/skills/wix-headless-fast/references/pricing-plans/seed/read-site.mjs +0 -21
  201. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +0 -279
  202. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -360
  203. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +0 -142
  204. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +0 -26
  205. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +0 -121
  206. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +0 -155
  207. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +0 -34
  208. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +0 -43
  209. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +0 -34
  210. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +0 -155
  211. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +0 -89
  212. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +0 -71
  213. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +0 -103
  214. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +0 -124
  215. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +0 -185
  216. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +0 -193
  217. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +0 -94
  218. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +0 -74
  219. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +0 -168
  220. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +0 -47
  221. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +0 -22
  222. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +0 -12
  223. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +0 -12560
  224. package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +0 -60
  225. package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +0 -169
  226. package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +0 -68
  227. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +0 -89
  228. package/skills/wix-headless-fast/references/restaurants/seed/read-site.mjs +0 -25
  229. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +0 -499
  230. package/skills/wix-headless-fast/references/shared/CONTENT.md +0 -22
  231. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +0 -73
  232. package/skills/wix-headless-fast/references/shared/DESIGN.md +0 -26
  233. package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +0 -23
  234. package/skills/wix-headless-fast/references/shared/app/styles/global.css +0 -52
  235. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +0 -15
  236. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +0 -81
  237. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +0 -24
  238. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +0 -89
  239. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +0 -46
  240. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +0 -46
  241. package/skills/wix-headless-fast/references/shared/rest/client.ts +0 -155
  242. package/skills/wix-headless-fast/references/shared/rest/config.ts +0 -3
  243. package/skills/wix-headless-fast/references/shared/rest/media.ts +0 -65
  244. package/skills/wix-headless-fast/references/shared/seed/images.mjs +0 -145
  245. package/skills/wix-headless-fast/references/shared/seed/read-site.mjs +0 -99
  246. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +0 -612
  247. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +0 -26
  248. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +0 -155
  249. package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +0 -266
  250. package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +0 -95
  251. package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +0 -136
  252. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +0 -48
  253. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +0 -39
  254. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +0 -34
  255. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +0 -121
  256. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +0 -107
  257. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +0 -138
  258. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +0 -314
  259. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +0 -133
  260. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +0 -147
  261. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +0 -289
  262. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +0 -169
  263. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +0 -65
  264. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +0 -12247
  265. package/skills/wix-headless-fast/references/storefront/rest/cart.ts +0 -132
  266. package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +0 -123
  267. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +0 -130
  268. package/skills/wix-headless-fast/references/storefront/seed/read-site.mjs +0 -38
  269. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -561
@@ -1,42 +0,0 @@
1
- // Post reads over REST — the twin of app/wix/blog/posts.ts. Same exports, same DTOs; the rules and
2
- // mappers come from posts-core (the SAME file the SDK transport uses, deployed flat next to this one
3
- // by deploy.mjs --stack static), so this file is only the transport: one fetch with a literal body
4
- // per function. Every call here is safe from a browser with a visitor token — only PUBLISHED posts
5
- // come back to it. Porting: keep the paths, keep the bodies, port the core once.
6
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/posts-stats/query-posts.md
7
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/posts-stats/get-post-by-slug.md
8
- import { wixRequest } from "./client.js";
9
- import { imgSrc } from "./media.js";
10
- import { BLOG_APP_ID, DETAIL_FIELDSETS, feedQuery, postMetaLine, slugQuery, toDetail, toSummary, type FetchPostsOptions, type Raw } from "./posts-core.js";
11
- import type { PostDetail, PostPage } from "./types.js";
12
-
13
- export { BLOG_APP_ID, postMetaLine, type FetchPostsOptions };
14
-
15
- const POSTS_QUERY = "/blog/v3/posts/query";
16
-
17
- /**
18
- * One page of published posts, newest first (pinned posts lead); `nextCursor` continues the same
19
- * query — send it alone, the filters ride inside it.
20
- * POST /blog/v3/posts/query { query: { filter?, sort, cursorPaging: { limit } } } — first page
21
- * POST /blog/v3/posts/query { query: { cursorPaging: { limit, cursor } } } — later pages
22
- */
23
- export async function fetchPosts(o: FetchPostsOptions = {}): Promise<PostPage> {
24
- const res = await wixRequest<Raw>(POSTS_QUERY, { body: { query: feedQuery(o) } });
25
- const paging: Raw = res?.pagingMetadata ?? {};
26
- return {
27
- posts: ((res?.posts ?? []) as Raw[]).map((p) => toSummary(p, imgSrc)),
28
- nextCursor: paging.hasNext ? (paging.cursors?.next ?? null) : null,
29
- };
30
- }
31
-
32
- /**
33
- * One post by URL slug with the full body (the RICH_CONTENT + CONTENT_TEXT fieldsets — without
34
- * them richContent and contentText are absent). Null when the slug resolves to nothing — a real
35
- * 404 for the page, never a fallback to another post.
36
- * POST /blog/v3/posts/query { fieldsets: ["RICH_CONTENT", "CONTENT_TEXT"], query: { filter: { slug: { $eq } }, cursorPaging: { limit: 1 } } }
37
- */
38
- export async function fetchPostBySlug(slug: string): Promise<PostDetail | null> {
39
- const res = await wixRequest<Raw>(POSTS_QUERY, { body: { fieldsets: DETAIL_FIELDSETS, query: slugQuery(slug) } });
40
- const raw: Raw | undefined = res?.posts?.[0];
41
- return raw ? toDetail(raw, imgSrc) : null;
42
- }
@@ -1,62 +0,0 @@
1
- // Category + tag reads over REST — the twin of app/wix/blog/taxonomy.ts. Same exports, same DTOs;
2
- // the mappers come from taxonomy-core (the SAME file the SDK transport uses, deployed flat next to
3
- // this one). Taxonomy queries page by OFFSET (`paging`), unlike posts (`cursorPaging`); a blog's
4
- // taxonomy fits in one read of 100. All four calls are visitor-safe.
5
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/query-categories.md
6
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/get-category-by-slug.md
7
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/query-tags.md
8
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/get-tag-by-slug.md
9
- import { wixRequest } from "./client.js";
10
- import { imgSrc } from "./media.js";
11
- import { CATEGORY_SORT, TAG_SORT, TAXONOMY_LIMIT, toCategory, toTag } from "./taxonomy-core.js";
12
- import type { Raw } from "./posts-core.js";
13
- import type { BlogCategory, BlogTag } from "./types.js";
14
-
15
- /**
16
- * Categories in menu order. Non-fatal: [] on failure (the feed renders without its filter row).
17
- * POST /blog/v3/categories/query { query: { sort: [{ fieldName: "displayPosition", order: "ASC" }], paging: { limit: 100 } } }
18
- */
19
- export async function fetchBlogCategories(): Promise<BlogCategory[]> {
20
- try {
21
- const res = await wixRequest<Raw>("/blog/v3/categories/query", { body: { query: { sort: CATEGORY_SORT, paging: { limit: TAXONOMY_LIMIT } } } });
22
- return ((res?.categories ?? []) as Raw[]).map((c) => toCategory(c, imgSrc)).filter((c) => c.id);
23
- } catch {
24
- return [];
25
- }
26
- }
27
-
28
- /**
29
- * Tags, most-published-posts first. Non-fatal: [] on failure.
30
- * POST /blog/v3/tags/query { query: { sort: [{ fieldName: "publishedPostCount", order: "DESC" }], paging: { limit: 100 } } }
31
- */
32
- export async function fetchBlogTags(): Promise<BlogTag[]> {
33
- try {
34
- const res = await wixRequest<Raw>("/blog/v3/tags/query", { body: { query: { sort: TAG_SORT, paging: { limit: TAXONOMY_LIMIT } } } });
35
- return ((res?.tags ?? []) as Raw[]).map(toTag).filter((t) => t.id);
36
- } catch {
37
- return [];
38
- }
39
- }
40
-
41
- // The two by-slug getters answer in DIFFERENT envelopes ({ category } and { tag }); a missing slug
42
- // is a 404 — mapped to null here, as the SDK transport does.
43
-
44
- /** One category by its URL slug. Null when not found. GET /blog/v3/categories/slugs/{slug} */
45
- export async function fetchCategoryBySlug(slug: string): Promise<BlogCategory | null> {
46
- try {
47
- const res = await wixRequest<Raw>(`/blog/v3/categories/slugs/${encodeURIComponent(slug)}`, { method: "GET" });
48
- return res?.category ? toCategory(res.category, imgSrc) : null;
49
- } catch {
50
- return null;
51
- }
52
- }
53
-
54
- /** One tag by its URL slug. Null when not found. GET /blog/v3/tags/slugs/{slug} */
55
- export async function fetchTagBySlug(slug: string): Promise<BlogTag | null> {
56
- try {
57
- const res = await wixRequest<Raw>(`/blog/v3/tags/slugs/${encodeURIComponent(slug)}`, { method: "GET" });
58
- return res?.tag ? toTag(res.tag) : null;
59
- } catch {
60
- return null;
61
- }
62
- }
@@ -1,81 +0,0 @@
1
- # Blog — seeding
2
-
3
- Seed by **running `seed-blog.mjs` with a plan file** — don't hand-write the REST calls.
4
- The script mints its own site token via the Wix CLI (logged-in session + `wix.config.json`
5
- required), installs the Blog app if needed, resolves a real author memberId (every post
6
- create requires one), and creates everything in the right order — categories/tags first,
7
- then **published** posts, then imported cover images (PATCH + re-publish).
8
-
9
- ```bash
10
- # from the project root (where wix.config.json lives):
11
- node <SKILL_ROOT>/references/blog/seed/seed-blog.mjs plan.json
12
- ```
13
-
14
- `plan.json` is plain data — write it from the brief. **Default to 3 posts** (the seed shows
15
- the shape; the owner writes the rest in the dashboard) and make them exercise the UI: group
16
- them into 2 categories when the brief has natural sections, tag a couple, vary the content
17
- blocks (heading + paragraphs + a quote or list per post), and give every post a cover — a
18
- feed without covers looks broken.
19
-
20
- ```json
21
- {
22
- "categories": ["Brewing", "Stories"],
23
- "posts": [
24
- { "title": "How We Roast Our Single-Origin Beans", "category": "Stories", "tags": ["coffee"],
25
- "coverImageUrl": "https://…",
26
- "content": [
27
- { "type": "heading", "text": "From farm to cup", "level": 2 },
28
- { "type": "paragraph", "text": "Every batch starts with beans sourced from a single estate." },
29
- { "type": "quote", "text": "Great coffee is grown, not made." }
30
- ] },
31
- { "title": "The Pour-Over, Step by Step", "category": "Brewing", "tags": ["guides"],
32
- "coverImageUrl": "https://…",
33
- "content": [
34
- { "type": "paragraph", "text": "A repeatable ritual in five minutes." },
35
- { "type": "ordered", "items": ["Rinse the filter", "Bloom 30 seconds", "Pour in circles"] }
36
- ] },
37
- { "title": "Why Water Matters More Than You Think", "category": "Brewing",
38
- "coverImageUrl": "https://…",
39
- "content": [
40
- { "type": "paragraph", "text": "Coffee is 98% water — its minerals decide the cup." },
41
- { "type": "bulleted", "items": ["Filtered, not distilled", "Aim for ~150 ppm hardness"] }
42
- ] }
43
- ]
44
- }
45
- ```
46
-
47
- - `content` blocks: `{type:"heading",text,level?}` · `{type:"paragraph",text}` ·
48
- `{type:"quote",text}` · `{type:"bulleted"|"ordered",items:[…]}`. For node types these don't
49
- cover (code, inline images), pass a pre-built Ricos `richContent` on the post instead.
50
- - `category`/`categories`/`tags` are display **names** — created idempotently and resolved to
51
- ids internally. Optional: skip them entirely when the brief doesn't group posts.
52
- - Cover — the default is a `coverImagePrompt` (AI-generated, ~1 Wix AI credit per image,
53
- account-billed): brand-contextual — subject, aesthetic/mood, palette, lighting — always
54
- ending "no text, no watermarks". At least one image in the set shows the real subject of the business — the actual product/space/service, not abstract decoration. For an asset the user actually supplied use
55
- `coverImagePath` (a file on this machine — uploaded to Wix Media) or `coverImageUrl` (their
56
- own hosted URL; verify it with `curl -sI` → 200) — never a stock-photo or guessed URL. Covers resolve
57
- in parallel and never block the seed; a failed cover leaves that post text-only (the script
58
- re-publishes each post it covers).
59
- - Posts are created **published** — an unpublished post never reaches visitors. The bulk
60
- create returns 200 even on partial failure: check each `posts[].success` in the result.
61
-
62
- **Seeding is additive — never delete or overwrite existing content**; ask first if a cleanup
63
- seems needed.
64
-
65
- ## Supplied content
66
-
67
- The general rules are in `references/shared/SUPPLIED-CONTENT.md`. For a blog, each post the user
68
- hands over is one entry. Its title becomes `title`; its body becomes `content` blocks, one block per
69
- paragraph, heading or list, whether the body arrived as text, HTML or Markdown; a category becomes
70
- `category` (and joins the `categories` list); tags become `tags`; their cover image becomes
71
- `coverImageUrl`. A post with no body is a question for the user. Authors and publish dates are
72
- not seeded — say so.
73
-
74
- ## Escape hatch — individual functions
75
- `setupBlog` composes exported steps — `installBlogApp`, `getAuthorMemberId`, `createPosts`,
76
- `createCategories`, `createTags`, `importImage`, `attachPostCovers`, plus `makeCtx()` —
77
- import them only for a partial re-seed.
78
-
79
- ## Reference
80
- Unexpected shape or an uncovered operation → read the live Wix API reference; the
81
- authoritative source recipe is `wix-headless/references/inline-recipes/setup-blog.md`.
@@ -1,22 +0,0 @@
1
- // What the blog holds: posts, categories, tags.
2
- // node <SKILL_ROOT>/references/blog/seed/read-site.mjs [--site <siteId>] [--limit <n>]
3
- import { runReader } from "../../shared/seed/read-site.mjs";
4
-
5
- const BLOG_APP_ID = "14bcded7-0066-7c35-14d7-466cb3f09103";
6
- const D = "https://dev.wix.com/docs/api-reference/business-solutions/blog";
7
-
8
- await runReader({
9
- vertical: "blog",
10
- appId: BLOG_APP_ID,
11
- async read(api, { limit }) {
12
- const posts = await api.call({ path: "/v3/posts/query", body: { fieldsets: ["URL"], query: { paging: { limit } } }, docs: `${D}/posts-stats/query-posts` });
13
- const cats = await api.tryCall({ path: "/blog/v3/categories/query", body: { query: { paging: { limit: 100 } } }, docs: `${D}/category/query-categories` });
14
- const tags = await api.tryCall({ path: "/v3/tags/query", body: { query: { paging: { limit: 100 } } }, docs: `${D}/tags/query-tags` });
15
- return {
16
- postCount: posts.metaData?.total ?? posts.pagingMetadata?.total ?? (posts.posts ?? []).length,
17
- posts: (posts.posts ?? []).map((p) => ({ title: p.title, slug: p.slug, published: p.firstPublishedDate ?? null, cover: !!p.coverMedia?.image, categories: (p.categoryIds ?? []).length, tags: (p.tagIds ?? []).length, minutesToRead: p.minutesToRead ?? null })),
18
- categories: (cats?.categories ?? []).map((c) => ({ id: c.id, label: c.label, slug: c.slug, postCount: c.postCount ?? null })),
19
- tags: (tags?.tags ?? []).map((t) => ({ id: t.id, label: t.label, postCount: t.postCount ?? null })),
20
- };
21
- },
22
- });
@@ -1,287 +0,0 @@
1
- // Blog seed — a BUILD-TIME script, never shipped in the app. Run from the project root
2
- // (where wix.config.json lives) with a plan file:
3
- //
4
- // node <SKILL_ROOT>/references/blog/seed/seed-blog.mjs plan.json
5
- //
6
- // It mints its own site token via the Wix CLI, installs the Wix Blog app if needed, resolves
7
- // a real author memberId (every post create requires one), creates categories/tags (idempotent
8
- // by label, with a fresh-install verify-retry), bulk-creates PUBLISHED posts with Ricos
9
- // richContent, and imports+attaches cover images (PATCH + re-publish). Prints a JSON result
10
- // to stdout.
11
- //
12
- // Plan shape (see SEED.md):
13
- // { "categories"?: [name], "tags"?: [name],
14
- // "posts": [{ "title", "content": [blocks] | "richContent"?, "category"?|"categories"?,
15
- // "tags"?, "coverImageUrl"? | "coverImagePrompt"? }] }
16
- // content blocks: { type:"heading", text, level? } | { type:"paragraph", text }
17
- // | { type:"quote", text } | { type:"bulleted"|"ordered", items:[text,…] }
18
- //
19
- // Seeding is ADDITIVE — never deletes or overwrites existing content. Unexpected shapes →
20
- // read the live API reference; authoritative source recipe:
21
- // wix-headless/references/inline-recipes/setup-blog.md.
22
- import { execFileSync } from "node:child_process";
23
- import { readFileSync } from "node:fs";
24
- import { resolveItemImages } from "../../shared/seed/images.mjs";
25
-
26
- const API = "https://www.wixapis.com";
27
- const BLOG_APP_ID = "14bcded7-0066-7c35-14d7-466cb3f09103";
28
-
29
- export function makeCtx({ cwd = process.cwd() } = {}) {
30
- const config = JSON.parse(readFileSync(`${cwd}/wix.config.json`, "utf8"));
31
- const siteId = config.siteId ?? config.projectId;
32
- if (!siteId) throw new Error("wix.config.json has no siteId — is this a Wix CLI project?");
33
- const token = execFileSync("npx", ["@wix/cli@latest", "token", "--site", siteId], {
34
- encoding: "utf8",
35
- cwd,
36
- }).trim();
37
- if (!token) throw new Error("The Wix CLI returned no token — run `npx @wix/cli@latest login` first.");
38
- return { token, siteId };
39
- }
40
-
41
- async function req(ctx, path, { method = "POST", body } = {}) {
42
- const res = await fetch(API + path, {
43
- method,
44
- headers: {
45
- Authorization: `Bearer ${ctx.token}`,
46
- "wix-site-id": ctx.siteId,
47
- "Content-Type": "application/json",
48
- },
49
- body: body ? JSON.stringify(body) : undefined,
50
- });
51
- const json = await res.json().catch(() => ({}));
52
- if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
53
- return json;
54
- }
55
-
56
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
57
-
58
- // ---- Ricos richContent builder (setup-blog.md § "CRITICAL RICOS NESTING") --------------------
59
- // Rules baked in: TEXT is always a leaf inside a container; BLOCKQUOTE / LIST_ITEM wrap a
60
- // PARAGRAPH; BULLETED_LIST / ORDERED_LIST wrap LIST_ITEM -> PARAGRAPH -> TEXT; every container
61
- // node gets a unique id, TEXT leaves use id "". For node types not covered here (code, images)
62
- // pass a pre-built `richContent` on the post instead — it's used verbatim.
63
- const mkText = (text) => ({ type: "TEXT", id: "", nodes: [], textData: { text: text || "", decorations: [] } });
64
- const mkParagraph = (id, text) => ({ type: "PARAGRAPH", id, nodes: [mkText(text)], paragraphData: {} });
65
-
66
- function mkRichContent(blocks = [], postIdx = 0) {
67
- let n = 0;
68
- const id = () => `p${postIdx}-n${n++}`;
69
- const nodes = [];
70
- for (const b of blocks) {
71
- switch (b.type) {
72
- case "heading":
73
- nodes.push({ type: "HEADING", id: id(), nodes: [mkText(b.text)], headingData: { level: b.level ?? 2 } });
74
- break;
75
- case "quote":
76
- nodes.push({ type: "BLOCKQUOTE", id: id(), nodes: [mkParagraph(id(), b.text)], blockquoteData: { indentation: 1 } });
77
- break;
78
- case "bulleted":
79
- case "ordered": {
80
- const listType = b.type === "bulleted" ? "BULLETED_LIST" : "ORDERED_LIST";
81
- nodes.push({
82
- type: listType, id: id(),
83
- nodes: (b.items ?? []).map((item) => ({ type: "LIST_ITEM", id: id(), nodes: [mkParagraph(id(), item)] })),
84
- });
85
- break;
86
- }
87
- case "paragraph":
88
- default:
89
- nodes.push(mkParagraph(id(), b.text));
90
- }
91
- }
92
- return { nodes };
93
- }
94
-
95
- // One post's plain data -> a flat Blog V3 draft-post object. media is omitted — covers are a
96
- // separate pass (attachPostCovers), per the recipe.
97
- function buildPost(p, i, memberId) {
98
- return {
99
- title: p.title,
100
- memberId,
101
- richContent: p.richContent ?? mkRichContent(p.content, i),
102
- ...(p.categoryIds ? { categoryIds: p.categoryIds } : {}),
103
- ...(p.tagIds ? { tagIds: p.tagIds } : {}),
104
- };
105
- }
106
-
107
- // ---- operations ----------------------------------------------------------------------------
108
-
109
- // docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
110
- export async function installBlogApp(ctx) {
111
- try {
112
- await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
113
- tenant: { tenantType: "SITE", id: ctx.siteId },
114
- appInstance: { appDefId: BLOG_APP_ID, enabled: true },
115
- } });
116
- } catch {
117
- /* already installed is fine */
118
- }
119
- }
120
-
121
- // Every post create needs a REAL author memberId — a fabricated id fails with
122
- // "memberIds ... do not exist". A provisioned site has the owner as members[0].
123
- // docs: https://dev.wix.com/docs/api-reference/crm/members-contacts/members/members/list-members.md
124
- export async function getAuthorMemberId(ctx) {
125
- const r = await req(ctx, "/members/v1/members?fieldsets=PUBLIC&paging.limit=1", { method: "GET" });
126
- const id = r.members?.[0]?.id;
127
- if (!id) throw new Error(`No site member found for author attribution: ${JSON.stringify(r).slice(0, 400)}`);
128
- return id;
129
- }
130
-
131
- /**
132
- * Create posts, PUBLISHED (publish:true — unpublished posts never reach visitors).
133
- * Endpoint auto-selected per the recipe: single-post endpoint for exactly one (nested
134
- * `{ draftPost }` envelope), bulk for >= 2 — `bulk` sits BETWEEN v3 and draft-posts, and each
135
- * bulk item is FLAT (wrapping it in `draftPost` 400s). Returns [{ id, index, success }].
136
- * docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/create-draft-post.md
137
- * docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/bulk-create-draft-posts.md
138
- */
139
- export async function createPosts(ctx, posts, { memberId, publish = true } = {}) {
140
- if (!memberId) throw new Error("createPosts requires opts.memberId (see getAuthorMemberId)");
141
- if (posts.length === 1) {
142
- const r = await req(ctx, "/blog/v3/draft-posts", { body: { draftPost: buildPost(posts[0], 0, memberId), publish } });
143
- return [{ id: r.draftPost?.id, index: 0, success: !!r.draftPost?.id }];
144
- }
145
- const r = await req(ctx, "/blog/v3/bulk/draft-posts/create", {
146
- body: { draftPosts: posts.map((p, i) => buildPost(p, i, memberId)), publish },
147
- });
148
- // Bulk returns 200 even on partial failure — read per-item results[].itemMetadata.success.
149
- return (r.results ?? []).map((x) => ({
150
- id: x.itemMetadata?.id, index: x.itemMetadata?.originalIndex, success: !!x.itemMetadata?.success,
151
- }));
152
- }
153
-
154
- // Existing label -> id, straight from the query (the source of truth for what persisted).
155
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/query-categories.md
156
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/query-tags.md
157
- async function labelIdMap(ctx, kind) {
158
- const path = kind === "categories" ? "/blog/v3/categories/query" : "/v3/tags/query";
159
- const r = await req(ctx, path, { body: { query: { paging: { limit: 100 } } } });
160
- return new Map((r[kind] ?? []).map((x) => [x.label, x.id]));
161
- }
162
-
163
- // Create category/tag labels resiliently. TWO hazards this absorbs:
164
- // 1. Fresh-install provisioning window — for a few seconds after the Blog app installs,
165
- // per-item category/tag creates return 200 with an id but DON'T persist (the id is a lie).
166
- // So the create response is never trusted — re-query, treat the query as truth, re-create
167
- // what's still missing until it sticks.
168
- // 2. Idempotency — an already-present label (a partial-failure re-run) is skipped.
169
- // Category bodies are NESTED (`{ category: { label } }`); tag bodies are FLAT (`{ label }`) —
170
- // a `{ tag: { label } }` body sends an empty top-level label and 400s. Returns [{ id, name }].
171
- async function ensureLabels(ctx, kind, createPath, mkBody, names) {
172
- let map = await labelIdMap(ctx, kind);
173
- for (let attempt = 0; attempt < 8; attempt++) {
174
- const missing = names.filter((n) => !map.has(n));
175
- if (!missing.length) break;
176
- if (attempt) await sleep(1500); // backoff only between retries — happy path pays nothing
177
- for (const name of missing) {
178
- try { await req(ctx, createPath, { body: mkBody(name) }); }
179
- catch (e) { if (!String(e.message).includes("-> 409")) throw e; } // 409 = raced, already there
180
- }
181
- map = await labelIdMap(ctx, kind);
182
- }
183
- return names.map((name) => ({ id: map.get(name), name }));
184
- }
185
-
186
- /** Create categories idempotently by label (no bulk endpoint). Feed ids into post.categoryIds. */
187
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/create-category.md
188
- export async function createCategories(ctx, names) {
189
- return ensureLabels(ctx, "categories", "/blog/v3/categories", (name) => ({ category: { label: name } }), names);
190
- }
191
-
192
- /** Create tags idempotently by label. Feed ids into post.tagIds. */
193
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/create-tag.md
194
- export async function createTags(ctx, names) {
195
- return ensureLabels(ctx, "tags", "/blog/v3/tags", (name) => ({ label: name }), names);
196
- }
197
-
198
- // Blog binds a post cover by Wix Media file ID — an external url must be imported first; a
199
- // plan `coverImagePrompt` is generated (Wix AI, 1 credit) then imported. Both live in the
200
- // shared util (parallel, resilient, never blocks the seed).
201
- export { importImage } from "../../shared/seed/images.mjs";
202
-
203
- // covers: [{ postId, fileId }] where fileId is the Wix Media file.id from importImage. Per
204
- // post: PATCH /blog/v3/draft-posts/{id} (NOT POST …/{id}/update — that 404s), setting
205
- // media.displayed:true + media.custom:true + wixMedia.image.id (the id ALONE is a silent
206
- // no-op), then RE-PUBLISH — the PATCH sets hasUnpublishedChanges, so the live post stays
207
- // cover-less until republished. Image failures never block the run.
208
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/update-draft-post.md
209
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/publish-draft-post.md
210
- export async function attachPostCovers(ctx, covers) {
211
- let attached = 0;
212
- for (const { postId, fileId } of covers) {
213
- try {
214
- await req(ctx, `/blog/v3/draft-posts/${postId}`, {
215
- method: "PATCH",
216
- body: { draftPost: { media: { displayed: true, custom: true, wixMedia: { image: { id: fileId } } } } },
217
- });
218
- await req(ctx, `/blog/v3/draft-posts/${postId}/publish`, { method: "POST" });
219
- attached++;
220
- } catch (e) {
221
- console.error(`cover attach skipped for post ${postId}: ${e.message}`);
222
- }
223
- }
224
- return attached;
225
- }
226
-
227
- /**
228
- * ONE-CALL seed: install → author memberId → categories/tags (names resolved to ids) →
229
- * published posts → covers, ids threaded in memory. The default path.
230
- */
231
- export async function setupBlog(ctx, { posts = [], categories = [], tags = [] } = {}) {
232
- await installBlogApp(ctx);
233
- await sleep(3000); // let a fresh Blog install settle so the first category/tag writes stick
234
- // (correctness is still guaranteed by ensureLabels' verify-retry).
235
- const memberId = await getAuthorMemberId(ctx);
236
-
237
- const catNames = [...new Set([...categories, ...posts.flatMap((p) => [].concat(p.category ?? [], p.categories ?? []))])];
238
- const tagNames = [...new Set([...tags, ...posts.flatMap((p) => [].concat(p.tags ?? []))])];
239
- const cats = catNames.length ? await createCategories(ctx, catNames) : [];
240
- const tgs = tagNames.length ? await createTags(ctx, tagNames) : [];
241
- const catId = new Map(cats.map((c) => [c.name, c.id]));
242
- const tagId = new Map(tgs.map((t) => [t.name, t.id]));
243
-
244
- const created = await createPosts(ctx, posts.map((p) => {
245
- const cn = [].concat(p.category ?? [], p.categories ?? []);
246
- const tn = [].concat(p.tags ?? []);
247
- return {
248
- ...p,
249
- ...(cn.length ? { categoryIds: cn.map((n) => catId.get(n)).filter(Boolean) } : {}),
250
- ...(tn.length ? { tagIds: tn.map((n) => tagId.get(n)).filter(Boolean) } : {}),
251
- };
252
- }), { memberId });
253
-
254
- // Pass 2 — covers: resolve (import by url / generate by prompt) in one parallel wave, then
255
- // attach (PATCH + re-publish per post). Failures leave the post text-only; the seed's exit
256
- // never depends on images.
257
- const files = await resolveItemImages(ctx, created.map((c, i) => (
258
- c?.id && c?.success
259
- ? { path: posts[i]?.coverImagePath, url: posts[i]?.coverImageUrl, prompt: posts[i]?.coverImagePrompt, displayName: `post-${i}.png` }
260
- : null
261
- )));
262
- const covers = created
263
- .map((c, i) => (files[i] ? { postId: c.id, fileId: files[i].id } : null))
264
- .filter(Boolean);
265
- const coversAttached = covers.length ? await attachPostCovers(ctx, covers) : 0;
266
-
267
- return { posts: created, categories: cats, tags: tgs, coversAttached };
268
- }
269
-
270
- // ---- CLI entry ----------------------------------------------------------------------------------
271
-
272
- const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
273
- if (invokedDirectly) {
274
- const planPath = process.argv[2];
275
- if (!planPath) {
276
- console.error("usage: node seed-blog.mjs <plan.json> (run from the project root)");
277
- process.exit(1);
278
- }
279
- const plan = JSON.parse(readFileSync(planPath, "utf8"));
280
- const ctx = makeCtx();
281
- setupBlog(ctx, plan)
282
- .then((result) => console.log(JSON.stringify(result, null, 2)))
283
- .catch((e) => {
284
- console.error(e.message);
285
- process.exit(1);
286
- });
287
- }