@wix/agent-skills 1.20.1 → 1.22.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 (262) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +71 -113
  3. package/skills/wix-app/references/APP_TOOLS.md +2 -1
  4. package/skills/wix-app/references/BACKEND_EVENT.md +3 -3
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +41 -152
  6. package/skills/wix-app/references/DASHBOARD_MODAL.md +4 -4
  7. package/skills/wix-app/references/DASHBOARD_PAGE.md +11 -25
  8. package/skills/wix-app/references/DATA_COLLECTION.md +16 -219
  9. package/skills/wix-app/references/SDK_MODULE_MAP.md +44 -0
  10. package/skills/wix-app/references/SITE_PLUGIN.md +36 -190
  11. package/skills/wix-app/references/app-tools/TOOLS.md +3 -1
  12. package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +21 -0
  13. package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +182 -0
  14. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +97 -0
  15. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md +184 -0
  16. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +203 -0
  17. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_SETTINGS.md +44 -0
  18. package/skills/wix-app/references/dashboard-page/ECOM_NAVIGATION.md +17 -0
  19. package/skills/wix-app/references/dashboard-page/QUERY_AND_PAGING.md +182 -0
  20. package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +133 -0
  21. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +10 -5
  22. package/skills/wix-app/references/dashboard-plugin/SLOTS.md +4 -18
  23. package/skills/wix-app/references/data-collection/LIFECYCLE.md +68 -0
  24. package/skills/wix-app/references/data-collection/PERMISSIONS.md +47 -0
  25. package/skills/wix-app/references/data-collection/SCHEMA.md +181 -0
  26. package/skills/wix-app/references/data-collection/WIX_DATA.md +38 -66
  27. package/skills/wix-app/references/site-plugin/EXAMPLES.md +1 -1
  28. package/skills/wix-headless-fast/SKILL.md +144 -221
  29. package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
  30. package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +15 -15
  31. package/skills/wix-headless-fast/guides/existing-site.md +76 -0
  32. package/skills/wix-headless-fast/guides/reference-mode.md +97 -0
  33. package/skills/wix-headless-fast/install/AGENTS.md +35 -0
  34. package/skills/wix-headless-fast/install/agents-md.mjs +39 -0
  35. package/skills/wix-headless-fast/install/attach.mjs +161 -86
  36. package/skills/wix-headless-fast/install/deploy.mjs +21 -60
  37. package/skills/wix-headless-fast/install/lock.mjs +55 -0
  38. package/skills/wix-headless-fast/install/setup.mjs +259 -0
  39. package/skills/wix-headless-fast/install/templates.mjs +168 -0
  40. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-coupon.md +10 -19
  41. package/skills/wix-manage/references/events/create-wix-event.md +5 -1
  42. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +27 -0
  43. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +83 -37
  44. package/skills/wix-headless-fast/install/fast-path.mjs +0 -181
  45. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -301
  46. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +0 -136
  47. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +0 -112
  48. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +0 -42
  49. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +0 -31
  50. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +0 -22
  51. package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +0 -137
  52. package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +0 -78
  53. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +0 -117
  54. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +0 -52
  55. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +0 -47
  56. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +0 -58
  57. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +0 -62
  58. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +0 -40
  59. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +0 -97
  60. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +0 -24
  61. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +0 -16156
  62. package/skills/wix-headless-fast/references/blog/rest/posts.ts +0 -42
  63. package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +0 -62
  64. package/skills/wix-headless-fast/references/blog/seed/SEED.md +0 -81
  65. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +0 -287
  66. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -275
  67. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +0 -144
  68. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +0 -119
  69. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +0 -32
  70. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +0 -23
  71. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +0 -218
  72. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +0 -169
  73. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +0 -121
  74. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +0 -92
  75. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +0 -90
  76. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +0 -57
  77. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +0 -72
  78. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +0 -40
  79. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +0 -76
  80. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +0 -22
  81. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +0 -11962
  82. package/skills/wix-headless-fast/references/bookings/rest/booking.ts +0 -113
  83. package/skills/wix-headless-fast/references/bookings/rest/services.ts +0 -55
  84. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +0 -71
  85. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +0 -302
  86. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -353
  87. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +0 -50
  88. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +0 -37
  89. package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +0 -158
  90. package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +0 -93
  91. package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +0 -177
  92. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +0 -123
  93. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +0 -75
  94. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +0 -41
  95. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +0 -11262
  96. package/skills/wix-headless-fast/references/cms/rest/items.ts +0 -125
  97. package/skills/wix-headless-fast/references/cms/seed/SEED.md +0 -112
  98. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +0 -324
  99. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -305
  100. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +0 -66
  101. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +0 -178
  102. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +0 -118
  103. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +0 -35
  104. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +0 -24
  105. package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +0 -130
  106. package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +0 -97
  107. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +0 -55
  108. package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +0 -113
  109. package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +0 -156
  110. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +0 -97
  111. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +0 -61
  112. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +0 -40
  113. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +0 -12
  114. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +0 -80
  115. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +0 -21
  116. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +0 -11884
  117. package/skills/wix-headless-fast/references/events/rest/events.ts +0 -57
  118. package/skills/wix-headless-fast/references/events/rest/registration.ts +0 -83
  119. package/skills/wix-headless-fast/references/events/seed/SEED.md +0 -95
  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 -338
  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/seed-forms.mjs +0 -327
  134. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -314
  135. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +0 -60
  136. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +0 -155
  137. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +0 -78
  138. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +0 -47
  139. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +0 -66
  140. package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +0 -105
  141. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +0 -59
  142. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +0 -53
  143. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +0 -122
  144. package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +0 -43
  145. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +0 -29
  146. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +0 -21
  147. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +0 -42
  148. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +0 -10
  149. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +0 -11
  150. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +0 -10329
  151. package/skills/wix-headless-fast/references/members/rest/auth.ts +0 -215
  152. package/skills/wix-headless-fast/references/members/rest/members.ts +0 -26
  153. package/skills/wix-headless-fast/references/members/seed/SEED.md +0 -39
  154. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +0 -94
  155. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -313
  156. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +0 -110
  157. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +0 -90
  158. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +0 -35
  159. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +0 -85
  160. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +0 -32
  161. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +0 -21
  162. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +0 -31
  163. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +0 -82
  164. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +0 -58
  165. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +0 -177
  166. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +0 -78
  167. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +0 -81
  168. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +0 -55
  169. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +0 -40
  170. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +0 -30
  171. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +0 -21
  172. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +0 -29
  173. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +0 -10197
  174. package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +0 -75
  175. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +0 -86
  176. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +0 -258
  177. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -294
  178. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +0 -47
  179. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +0 -101
  180. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +0 -41
  181. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +0 -16
  182. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +0 -22
  183. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +0 -54
  184. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +0 -106
  185. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +0 -64
  186. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +0 -27
  187. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +0 -43
  188. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +0 -22
  189. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +0 -30
  190. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +0 -41
  191. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +0 -40
  192. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +0 -21
  193. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +0 -11226
  194. package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +0 -31
  195. package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +0 -20
  196. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +0 -79
  197. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +0 -279
  198. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -358
  199. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +0 -142
  200. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +0 -26
  201. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +0 -121
  202. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +0 -155
  203. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +0 -34
  204. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +0 -43
  205. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +0 -34
  206. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +0 -155
  207. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +0 -89
  208. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +0 -71
  209. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +0 -103
  210. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +0 -124
  211. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +0 -185
  212. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +0 -193
  213. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +0 -94
  214. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +0 -74
  215. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +0 -168
  216. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +0 -47
  217. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +0 -22
  218. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +0 -12
  219. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +0 -12560
  220. package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +0 -60
  221. package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +0 -169
  222. package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +0 -68
  223. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +0 -89
  224. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +0 -479
  225. package/skills/wix-headless-fast/references/shared/CONTENT.md +0 -22
  226. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +0 -73
  227. package/skills/wix-headless-fast/references/shared/DESIGN.md +0 -26
  228. package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +0 -23
  229. package/skills/wix-headless-fast/references/shared/app/styles/global.css +0 -52
  230. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +0 -15
  231. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +0 -81
  232. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +0 -24
  233. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +0 -89
  234. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +0 -46
  235. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +0 -46
  236. package/skills/wix-headless-fast/references/shared/rest/client.ts +0 -155
  237. package/skills/wix-headless-fast/references/shared/rest/config.ts +0 -3
  238. package/skills/wix-headless-fast/references/shared/rest/media.ts +0 -65
  239. package/skills/wix-headless-fast/references/shared/seed/images.mjs +0 -145
  240. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +0 -608
  241. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +0 -26
  242. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +0 -155
  243. package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +0 -266
  244. package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +0 -95
  245. package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +0 -136
  246. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +0 -48
  247. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +0 -39
  248. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +0 -34
  249. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +0 -121
  250. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +0 -107
  251. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +0 -138
  252. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +0 -309
  253. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +0 -133
  254. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +0 -147
  255. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +0 -289
  256. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +0 -167
  257. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +0 -65
  258. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +0 -12247
  259. package/skills/wix-headless-fast/references/storefront/rest/cart.ts +0 -132
  260. package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +0 -123
  261. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +0 -124
  262. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -525
@@ -1,301 +0,0 @@
1
- # Blog — playbook
2
-
3
- The blog machinery ships as files — post reads (feed paging, slug lookup with the body
4
- fieldsets), category/tag taxonomy, the feed and post state machines, and the Ricos body renderer,
5
- typed end-to-end. **The presentation doesn't ship — you build it** on the shipped hooks/DTOs: the
6
- post card, the grid, the blog index surface, the post page surface, the home page, and the brand.
7
- You never write blog data logic; you never skip designing. The vertical is **read-only** —
8
- visitors read posts; authoring stays in the dashboard.
9
-
10
- ## The file map (deployed into `src/`)
11
-
12
- **On Astro and React the shipped files are tested and work as they are** — this table and the
13
- contracts below are everything you need to use them, so don't spend the run reading their source;
14
- wire them and build your surfaces. Reading them is the right move when something is off (a runtime
15
- error, a field this playbook doesn't cover) or when the brief wants a behaviour they don't offer —
16
- then read the file that owns it and change or extend it. On `lib`, `static`, and a port the
17
- components don't deploy at all, and each wiring section below opens with the files to read before
18
- writing their equivalents. Files you edit: `SiteLayout.astro`, `styles/global.css`, and the two
19
- shipped pages' templates. Files you **create**: your feed island (skeleton below), your post
20
- surface, and your home page.
21
-
22
- | file | what it is |
23
- |---|---|
24
- | `wix/config.ts` · `wix/sdk.ts` | shared auth seam (deploy configures it — nothing to set by hand) |
25
- | `wix/media.ts` · `wix/money.ts` | `imgAttrs(url, sizes, ratio)` — every `<img>` attribute for a DTO image (`src`, `srcSet`, `sizes`, lazy): `<img {...imgAttrs(post.coverUrl, "(min-width: 1024px) 33vw, 100vw", 9 / 16)} alt={post.title} />`; `imgSrc()` / `imgSrcSet()` underneath |
26
- | `wix/blog/types.ts` | the DTOs (`PostSummary`, `PostDetail`, `BlogCategory`, `BlogTag`, `PostPage`) — contracts inlined below |
27
- | `wix/blog/posts.ts` | `fetchPosts` (cursor-paged, category/tag filtered on Wix), `fetchPostBySlug` (full body), `postMetaLine(post)` ("Aug 27, 2026 · 4 min read") — the transport; the rules and DTO mappers are in `posts-core.ts` beside it (shared with the REST layer) |
28
- | `wix/blog/taxonomy.ts` | `fetchBlogCategories`, `fetchBlogTags`, `fetchCategoryBySlug`, `fetchTagBySlug` — the transport; mappers in `taxonomy-core.ts` |
29
- | `wix/blog/blog-feed-store.ts` · `post-store.ts` | the feed and post state machines, framework-free (`createBlogFeedStore()`, `createPostStore()` — `getState`/`subscribe` + actions, one instance per surface); the hooks below bind them to React, every other stack uses them directly |
30
- | `hooks/blog/useBlogFeed.ts` | React binding of `blog-feed-store.ts`: feed + taxonomy filter + load-more — contract below |
31
- | `hooks/blog/usePost.ts` | React binding of `post-store.ts`: post by slug + resolved chips — contract below |
32
- | `components/blog/RichContent.tsx` | the post-body renderer — **wire as-is** (machinery, not a reference) |
33
- | `components/blog/BlogFeedView.tsx` (+ `PostCard`) · `PostView.tsx` | **reference implementations** — correct, plain; build your own instead of shipping them |
34
- | `styles/global.css` | **the design system**: Tailwind v4 + the `@theme` token block (shared across verticals). Everything, shipped and yours, styles from these tokens |
35
-
36
- Astro stack additionally gets:
37
-
38
- | file | what it is |
39
- |---|---|
40
- | `layouts/SiteLayout.astro` | site chrome — **yours to brand** (keep the `seo-tags` slot + global.css import). If another vertical is also deployed, its layout won — add a Blog nav link there |
41
- | `pages/blog.astro` | SSR feed — **keep the frontmatter**, swap the island import to YOUR component |
42
- | `pages/blog/[...slug].astro` | SSR post page with owner-editable SEO — **keep the frontmatter, the `[...slug]` rest param, and the SEO pieces** (`wixMetadata`, `loadSEOTagsServiceConfig`, `<SEO.Tags>`) exactly; restyle the template. The body island stays `client:only="react"` (the ricos viewer breaks under SSR). A slug that resolves to nothing returns a real 404 |
43
-
44
- ## What you build — the design job
45
-
46
- 1. **The post card + grid** — your tile (cover, title, excerpt, `postMetaLine(post)`) and rhythm,
47
- with skeletons while `posts === null` and an honest empty state for `[]`.
48
- 2. **The blog index surface** — the feed island on `useBlogFeed`: category filter (only when >1
49
- non-empty category), the grid, and a load-more control gated on `hasMore`.
50
- 3. **The post page surface** — header (categories eyebrow, title, meta line, cover), the body via
51
- the shipped `RichContent`, and the tag chips — restyle the `[...slug].astro` template around it.
52
- 4. **The home page** — hero, latest posts (fetch in frontmatter → your components), brand story.
53
-
54
- Plus the **theme** (`@theme` block, one edit) and the **chrome** (`SiteLayout`, one pass).
55
- Style everything with Tailwind utilities on the tokens. Dark theme: the ricos CSS hardcodes
56
- near-black text — add a global override scoping `.ricos-content` to the foreground token
57
- (in Astro use `<style is:global>`; React islands don't inherit scoped Astro styles).
58
-
59
- ### What a complete blog shows (recommended defaults)
60
-
61
- Defaults for a blog whose brief says nothing about them; the prompt wins where it differs. Look at
62
- the seeded content before designing (how many posts, categories, covers, body structure) and design
63
- for this blog, not for a stereotype of one.
64
-
65
- - **Home:** what the blog is about and the latest posts (real ones, under a truthful heading) in the
66
- first screen; a category link goes to the feed filtered to it, never to an anchor.
67
- - **Index:** a real card — cover, title, meta line — in the first screen at 390px too; the category
68
- row only when more than one category has posts; loading, empty, and error states that look
69
- different; load-more, never a raised page size.
70
- - **Post page:** eyebrow, title, meta line, cover as a bounded band on phones (`max-h-[45vh]`), the
71
- body, then the tags; a slug that resolves to nothing shows only the not-found state.
72
- - **Copy:** nothing the author didn't write — no invented bylines, comment counts, likes, or
73
- "trending" labels; no Wix IDs or technical words in visible text.
74
-
75
- ### The contracts your components consume
76
-
77
- Tested and working as they are; read the source when something is off or the brief wants more.
78
-
79
- ```ts
80
- // PostSummary (tiles) — display-ready:
81
- // { id, slug, title, excerpt, dateLabel /* "Aug 26, 2026" | "" */, dateISO,
82
- // minutesToRead /* 0 = unknown */, featured, pinned, coverUrl /* "" = no cover, 16:9 */,
83
- // categoryIds, tagIds }
84
- // postMetaLine(post) → "Aug 26, 2026 · 4 min read" (either half alone; "" when neither is known) —
85
- // render it inside <time dateTime={post.dateISO}>; don't hand-assemble the separator.
86
- // PostDetail adds: richContent (Ricos JSON | null — render ONLY via RichContent),
87
- // paragraphs (plain-text fallback body).
88
- // BlogCategory: { id, slug, label, description, postCount, coverUrl } // display .label
89
- // BlogTag: { id, slug, label, postCount /* published posts */ }
90
-
91
- // useBlogFeed({ initialPage?, initialCategories?, initialTags?, pageSize? /* 20 */ }) →
92
- // { posts: PostSummary[]|null /* null = loading → skeletons */,
93
- // categories, tags,
94
- // activeCategoryId, setActiveCategoryId(id|null), // server-side filter
95
- // activeTagId, setActiveTagId(id|null), // mutually exclusive with category
96
- // hasMore, loadMore(), loadingMore, error }
97
- // Filters and paging run on Wix (a changed filter restarts the list; a late response is dropped).
98
-
99
- // usePost({ slug, initialPost?, initialCategories?, initialTags? }) →
100
- // { post: PostDetail|null, notFound /* true = render a 404 state, never invent a post */,
101
- // categories, tags /* THIS post's, resolved — display .label */, error }
102
-
103
- // <RichContent content={post.richContent} fallbackParagraphs={post.paragraphs} />
104
- // — the ONLY body render path. In Astro: client:only="react".
105
- ```
106
-
107
- ### The island you create — skeleton
108
-
109
- The two Astro pages ship; their frontmatter is machinery (SSR fetch → DTO props → island; the
110
- post page's SEO block) and stays as shipped. What you create is the feed island `blog.astro` mounts
111
- (and, in a SPA, the post surface — `PostView.tsx` shows its shape). Hooks first, branches after (an
112
- early return above a hook changes hook order and React throws). Islands render on the server too,
113
- after the 200 is sent — nothing in a render path may throw.
114
-
115
- ```tsx
116
- // src/components/blog/<YourFeed>.tsx — YOU build it; blog.astro mounts it (swap the import there).
117
- import { useBlogFeed } from "../../hooks/blog/useBlogFeed";
118
- import { postMetaLine } from "../../wix/blog/posts";
119
- import { imgAttrs } from "../../wix/media";
120
- import type { BlogCategory, BlogTag, PostPage } from "../../wix/blog/types";
121
-
122
- export default function YourFeed(props: {
123
- initialPage?: PostPage; // SSR props from blog.astro — pass straight to useBlogFeed;
124
- initialCategories?: BlogCategory[]; // omitted in a SPA (client fetch)
125
- initialTags?: BlogTag[];
126
- }) {
127
- const feed = useBlogFeed(props);
128
- const { posts, categories, activeCategoryId, setActiveCategoryId, hasMore, loadMore, loadingMore, error } = feed;
129
- // …you implement the render:
130
- // • a category row when more than one category has posts (categories.filter(c => c.postCount > 0)):
131
- // "All" (null) first, the active one marked by activeCategoryId, each calling setActiveCategoryId
132
- // • error → a short inline message
133
- // • posts === null → skeleton tiles; [] → your honest empty state
134
- // • else YOUR grid of YOUR tiles: cover via
135
- // <img {...imgAttrs(p.coverUrl, "(min-width: 1024px) 33vw, 100vw", 9 / 16)} alt={p.title} /> — {} when
136
- // there is no cover, render your placeholder then; title WRAPS (no truncate); excerpt clamped;
137
- // <time dateTime={p.dateISO}>{postMetaLine(p)}</time>; the tile links to `/blog/${p.slug}`
138
- // • hasMore → your "load more" control calling loadMore() (disabled while loadingMore)
139
- }
140
- ```
141
-
142
- ### The reference files for stacks where the components don't deploy
143
-
144
- On `lib`, `static`, and a port, nothing under `components/` or `hooks/` arrives. The state
145
- machines behind the hooks do arrive — `wix/blog/blog-feed-store.ts`, `post-store.ts` — so you never
146
- rewrite them: create a store per surface, `subscribe`, render from `getState()`, call its actions.
147
- Their `*State` interfaces are the render contract; read those. What you write is the rendering —
148
- card, grid, filter row, post header — and for that read these first; they are tested code for
149
- exactly that behaviour:
150
-
151
- 1. `components/blog/BlogFeedView.tsx` — the filter row (only categories with posts, "All" first,
152
- one active pill), the skeleton grid while `posts === null`, the empty state, load-more disabled
153
- while loading; `PostCard` inside it is the tile: 16:9 cover, wrapping title, clamped excerpt,
154
- the meta line in a `<time>`.
155
- 2. `components/blog/PostView.tsx` — the states in order (not found → error → loading → article),
156
- the categories eyebrow by `.label`, the tag chips, the body slot.
157
- 3. `components/blog/RichContent.tsx` — what the body renderer is: the `@wix/ricos` viewer, a React
158
- component that needs a bundler. On these stacks it doesn't run; the body renders from
159
- `post.paragraphs` (one `<p>` per entry), and headings, lists, quotes, and inline images flatten
160
- to text — say so in the closing message. A blog whose posts carry structure stays on Astro.
161
-
162
- All under `references/blog/app/`.
163
-
164
- ### Wiring — Astro (default)
165
-
166
- 1. Set the `@theme` tokens (one edit); brand `SiteLayout.astro` (one pass — merge into the
167
- other vertical's layout instead if both are deployed).
168
- 2. Write your feed island under `src/components/blog/` (a new name — don't overwrite the
169
- references), swap the island import in `pages/blog.astro`, and restyle the
170
- `pages/blog/[...slug].astro` template (keep its frontmatter + SEO pieces + the
171
- `client:only="react"` RichContent island). **Author your surfaces in as few messages as
172
- possible** — batch multiple Writes per message.
173
- 3. Write `pages/index.astro` (home) — it exists from the scaffold; Read it before overwriting.
174
-
175
- ### Wiring — another JS framework (`--stack lib`: Vue, Svelte, Solid, plain Vite)
176
-
177
- Read the reference files listed above before writing any surface.
178
-
179
- `deploy.mjs blog --stack lib` put the data layer in `src/wix/` and nothing else: `sdk.ts` (the
180
- visitor client, configured with the public client id), `media.ts`, `money.ts`, and `wix/blog/` —
181
- `posts.ts`, `taxonomy.ts`, `types.ts`, the `*-core.ts` rules, and the two stores
182
- `blog-feed-store.ts`, `post-store.ts`. None of it is React. The hooks and components don't ship on
183
- this stack; the stores replace the hooks, and you write the components in your framework to the
184
- contracts on this page:
185
-
186
- - bind the stores with your framework's external-store primitive (Vue: `shallowRef` updated in
187
- `subscribe`; Svelte: `readable(store.getState(), (set) => store.subscribe(() => set(store.getState())))`;
188
- Solid: a signal set in `subscribe`). `createBlogFeedStore(options)` per feed (`start()` when
189
- mounted, `stop()` when unmounted), `createPostStore({ slug, initialPost? })` per post surface.
190
- State in, actions out — exactly the hooks' contracts above;
191
- - the body: `@wix/ricos` is a React component — without React it doesn't render; use
192
- `post.paragraphs` and say so in the closing message.
193
-
194
- Routes `/blog`, `/blog/:slug` (null → your 404 view); dev server on 4321; a static build goes
195
- through `npx @wix/cli@latest release` with `site.outputDirectory` pointing at the build folder,
196
- an SSR build is hosted by you. Post-page tags from `post.title` and `post.excerpt`.
197
-
198
- ### Wiring — static site (`--stack static`, no bundler)
199
-
200
- Read the reference files listed above before writing any surface.
201
-
202
- `deploy.mjs blog --stack static --out site` put the REST layer in `site/js/wix/` (browser ESM,
203
- the `.ts` beside each `.js` for reading). Everything the visitor loads lives under `site/` —
204
- pages, styles, `js/` — and `wix.config.json`'s `site.outputDirectory` is `"./site"`; the project
205
- root (config, plan, seed output) is never the upload. Same function names and DTOs as the table
206
- above, so the contracts on this page hold unchanged: `fetchPosts`, `fetchPostBySlug`,
207
- `postMetaLine` from `./js/wix/posts.js`; `fetchBlogCategories`, `fetchBlogTags`,
208
- `fetchCategoryBySlug`, `fetchTagBySlug` from `./js/wix/taxonomy.js`; `imgAttrs` from
209
- `./js/wix/media.js`. The state machines ship too: `createBlogFeedStore` from
210
- `./js/wix/blog-feed-store.js` (the feed — filters, cursor paging; `start()` once the page is up)
211
- and `createPostStore` from `./js/wix/post-store.js` (the post and its resolved chips). No
212
- components ship — you write the rendering in plain JS: one render function per surface that reads
213
- `getState()`, called from `subscribe`, with the surface's controls calling the store's actions.
214
- Pages are `blog.html` and `post.html?slug=…` (Wix static hosting serves files, not directories —
215
- name the file and link to it). The body renders from `post.paragraphs` (no Ricos viewer without a
216
- bundler — see the reference files note). Set `document.title` and the meta description from
217
- `post.title` and `post.excerpt` once the post loads, as the Astro page does. The visitor token
218
- persists in `localStorage` on its own; never mint per page. `npx @wix/cli@latest release`
219
- uploads `site/`.
220
-
221
- ### Wiring — server-rendered, another language (Flask, Laravel, Rails, …)
222
-
223
- Read the reference files listed above before writing any surface.
224
-
225
- Run `deploy.mjs blog --stack static` in the project folder anyway: `js/wix/` is both the
226
- browser-side code and the readable spec. Reads render on the server: port `js/wix/posts.ts`,
227
- `taxonomy.ts` and their `*-core.ts` to your language — the same six functions returning the same
228
- DTO shapes as dicts, one anonymous visitor token per process for these public reads (mint and
229
- refresh per `client.ts`) — and render the feed and the post page in your templates to the
230
- contracts above, so titles and excerpts are in the HTML; post-page tags from `post.title` and
231
- `post.excerpt`. The body is `paragraphs` server-side too (the Ricos viewer is React). Nothing in
232
- this vertical runs on the visitor's behalf, so the browser side is optional: the feed's category
233
- filter and load-more can run client-side on `./js/wix/blog-feed-store.js` exactly as the static
234
- wiring above, or as plain server routes (`/blog?category=<slug>` via `fetchCategoryBySlug`,
235
- paging by cursor). Routes stay `/blog`, `/blog/<slug>`.
236
-
237
- **Pre-rendered (Frozen-Flask, Pelican, any static-site generator) → Wix-hosted.** Same port for
238
- the reads, run at build time with one anonymous token; the generator must emit a page for every
239
- post — walk `fetchPosts` by `nextCursor` until it is null, never only the first page. Run
240
- `deploy.mjs blog --stack static --out <build dir>` so `js/wix/` is inside the output the pages
241
- import from, point `site.outputDirectory` at that folder, `wix release`. Pages sit at different
242
- depths (`/`, `/blog/…`): give the templates one base path to `js/wix/` (a template variable, or
243
- root-relative `/js/wix/…`), never a relative `./js/wix/`. The frozen grid is the first paint; the
244
- category filter and load-more still run client-side on it through `createBlogFeedStore()` from
245
- `./js/wix/blog-feed-store.js`. Close with the live URL, the rebuild + release command, and one
246
- line for the owner: posts published in the dashboard reach the site when that command runs.
247
-
248
- ### Wiring — React SPA (Vite etc.)
249
-
250
- Import `./styles/global.css` once at the app entry (needs `@tailwindcss/vite` in the vite
251
- plugins — deploy added the dep). Routes: `/blog` → your feed on `useBlogFeed`;
252
- `/blog/:slug` → your post surface on `usePost({ slug })` (the `PostView` reference shows the
253
- shape; `notFound` → your 404 view). Deploy wrote the public client id into `wix/config.ts`;
254
- nothing else to configure.
255
-
256
- ## Hard rules
257
-
258
- - **The body renders only through `RichContent`** where it deploys (Astro, React) — a post body
259
- is a Ricos document, not HTML and not text: never `set:html`/innerHTML it, never stringify its
260
- nodes, never write your own node walker. Where it doesn't deploy, `paragraphs` is the honest
261
- body, and the closing message says so.
262
- - **Data logic only through the shipped exports** — never rewrite their internals or re-derive a
263
- request shape; extend by adding a function in `wix/blog/` (API contracts: the `wix-docs` skill).
264
- - **Route by `slug` through the shipped functions** — never hand-build a post/category/tag URL
265
- from ids; display taxonomy by `.label` (the API has no `.name`).
266
- - **`notFound` means not found** — render your 404 state; never invent a post. Only published
267
- posts come back, so a "missing" post is usually an unseeded/unpublished one.
268
- - **Filter and page at the source** — `useBlogFeed`'s filters and `fetchPosts` run on Wix before
269
- cursor paging; never filter a loaded page client-side, never raise the page limit instead of
270
- paging (`hasMore`/`loadMore`).
271
- - **Never hand-build a wixstatic image URL** — `coverUrl` is already resolved; anything else goes
272
- through `wix/media.ts`.
273
- - Where the shipped components deploy: theme via the `@theme` tokens, your markup in Tailwind
274
- utilities on the same tokens; no parallel theme files, no hardcoded palettes. Where they don't
275
- (`lib`, `static`, a port): style with what your stack does well, on one token set of your own.
276
- - Live data or an honest empty state — never mock posts, authors, dates, or read times; no stock
277
- placeholder covers. No author bylines or comment/like UI — the DTOs don't carry them.
278
- - Keep the post page's SEO pieces and `[...slug]` rest param exactly as shipped.
279
- - **Call every hook before any conditional return.** Hooks first, branches after.
280
-
281
- ## Point the user to their dashboard
282
-
283
- Hand the owner these links — `{siteId}` is `siteId` in `wix.config.json` (the deploy JSON prints it as
284
- `dashboardUrl`).
285
-
286
- | page | `https://manage.wix.com/dashboard/{siteId}/` + |
287
- |---|---|
288
- | Posts (published and drafts) | `blog/posts` |
289
- | Categories | `blog/categories` |
290
- | Tags | `blog/tags` |
291
- | Writers | `blog/writers` |
292
- | Comments | `blog/comments` |
293
- | Blog settings | `blog/settings` |
294
-
295
- Only published posts appear on the site.
296
-
297
- ## Seeding
298
-
299
- Per `seed/SEED.md` — plain-data `plan.json` into `seed-blog.mjs` from the project root.
300
- Seed posts that exercise the UI (~3 posts, 2 categories when the brief has sections, varied
301
- content blocks, a cover image per post).
@@ -1,136 +0,0 @@
1
- // REFERENCE feed surface: taxonomy filter chips + post grid + load-more on the @theme tokens.
2
- // Correct and complete; per the skill's model you design and build your own on useBlogFeed.
3
- import type { ComponentType, ReactNode } from "react";
4
- import { useBlogFeed } from "../../hooks/blog/useBlogFeed";
5
- import { postMetaLine } from "../../wix/blog/posts";
6
- import type { BlogCategory, BlogTag, PostPage, PostSummary } from "../../wix/blog/types";
7
-
8
- export interface LinkLikeProps {
9
- href: string;
10
- className?: string;
11
- children?: ReactNode;
12
- }
13
-
14
- const PlainLink = ({ href, className, children }: LinkLikeProps) => (
15
- <a href={href} className={className}>
16
- {children}
17
- </a>
18
- );
19
-
20
- export interface PostCardProps {
21
- post: PostSummary;
22
- postHref?: (slug: string) => string;
23
- LinkComponent?: ComponentType<LinkLikeProps>;
24
- }
25
-
26
- export function PostCard({ post, postHref = (slug) => `/blog/${slug}`, LinkComponent = PlainLink }: PostCardProps) {
27
- return (
28
- <LinkComponent href={postHref(post.slug)} className="group block no-underline">
29
- {post.coverUrl && (
30
- <div className="aspect-[16/9] overflow-hidden rounded-lg bg-secondary">
31
- <img
32
- src={post.coverUrl}
33
- alt={post.title}
34
- loading="lazy"
35
- className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-[1.03]"
36
- />
37
- </div>
38
- )}
39
- <h3 className="mt-3 text-base font-semibold leading-snug text-foreground">{post.title}</h3>
40
- {post.excerpt && <p className="mt-1 line-clamp-2 text-sm text-muted-foreground">{post.excerpt}</p>}
41
- <p className="mt-2 text-xs text-muted-foreground">
42
- <time dateTime={post.dateISO}>{postMetaLine(post)}</time>
43
- </p>
44
- </LinkComponent>
45
- );
46
- }
47
-
48
- export interface BlogFeedViewProps {
49
- initialPage?: PostPage;
50
- initialCategories?: BlogCategory[];
51
- initialTags?: BlogTag[];
52
- emptyMessage?: string;
53
- postHref?: PostCardProps["postHref"];
54
- LinkComponent?: ComponentType<LinkLikeProps>;
55
- CardComponent?: ComponentType<PostCardProps>;
56
- }
57
-
58
- const pill = (active: boolean) =>
59
- `rounded-full border px-4 py-1.5 text-sm font-medium transition-colors ${
60
- active
61
- ? "border-primary bg-primary text-primary-foreground"
62
- : "border-border text-foreground hover:bg-secondary"
63
- }`;
64
-
65
- export default function BlogFeedView({
66
- initialPage,
67
- initialCategories,
68
- initialTags,
69
- emptyMessage = "No posts yet — check back soon.",
70
- postHref,
71
- LinkComponent,
72
- CardComponent = PostCard,
73
- }: BlogFeedViewProps) {
74
- const {
75
- posts,
76
- categories,
77
- activeCategoryId,
78
- setActiveCategoryId,
79
- hasMore,
80
- loadMore,
81
- loadingMore,
82
- error,
83
- } = useBlogFeed({ initialPage, initialCategories, initialTags });
84
-
85
- const visibleCategories = categories.filter((c) => c.postCount > 0);
86
-
87
- return (
88
- <div>
89
- {visibleCategories.length > 1 && (
90
- <div className="mb-8 flex flex-wrap gap-2" role="group" aria-label="Categories">
91
- <button type="button" className={pill(activeCategoryId === null)} onClick={() => setActiveCategoryId(null)}>
92
- All
93
- </button>
94
- {visibleCategories.map((c) => (
95
- <button key={c.id} type="button" className={pill(activeCategoryId === c.id)} onClick={() => setActiveCategoryId(c.id)}>
96
- {c.label}
97
- </button>
98
- ))}
99
- </div>
100
- )}
101
- {error && <p className="mb-4 text-sm text-red-600">{error}</p>}
102
- {posts === null ? (
103
- <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3" aria-busy="true">
104
- {Array.from({ length: 6 }, (_, i) => (
105
- <div key={i}>
106
- <div className="aspect-[16/9] animate-pulse rounded-lg bg-secondary" />
107
- <div className="mt-3 h-3.5 w-2/3 animate-pulse rounded bg-secondary" />
108
- </div>
109
- ))}
110
- </div>
111
- ) : posts.length === 0 ? (
112
- <p className="py-16 text-center text-muted-foreground">{emptyMessage}</p>
113
- ) : (
114
- <>
115
- <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
116
- {posts.map((p) => (
117
- <CardComponent key={p.id} post={p} postHref={postHref} LinkComponent={LinkComponent} />
118
- ))}
119
- </div>
120
- {hasMore && (
121
- <div className="mt-10 text-center">
122
- <button
123
- type="button"
124
- onClick={loadMore}
125
- disabled={loadingMore}
126
- className="rounded-lg border border-border px-6 py-2.5 text-sm font-medium text-foreground transition-colors hover:bg-secondary disabled:opacity-50"
127
- >
128
- {loadingMore ? "Loading…" : "Load more"}
129
- </button>
130
- </div>
131
- )}
132
- </>
133
- )}
134
- </div>
135
- );
136
- }
@@ -1,112 +0,0 @@
1
- // REFERENCE post surface (SPA use — Astro renders the header statically and mounts only
2
- // RichContent as an island). Correct and complete; per the skill's model you design and
3
- // build your own on usePost. Chips display .label; the body renders ONLY via RichContent.
4
- import type { ComponentType } from "react";
5
- import { usePost } from "../../hooks/blog/usePost";
6
- import { postMetaLine } from "../../wix/blog/posts";
7
- import type { BlogCategory, BlogTag, PostDetail } from "../../wix/blog/types";
8
- import RichContent from "./RichContent";
9
- import type { LinkLikeProps } from "./BlogFeedView";
10
-
11
- export interface PostViewProps {
12
- slug: string;
13
- initialPost?: PostDetail;
14
- initialCategories?: BlogCategory[];
15
- initialTags?: BlogTag[];
16
- /** Where a chip routes; omit to render chips as plain labels. */
17
- categoryHref?: (slug: string) => string;
18
- tagHref?: (slug: string) => string;
19
- LinkComponent?: ComponentType<LinkLikeProps>;
20
- }
21
-
22
- const PlainLink = ({ href, className, children }: LinkLikeProps) => (
23
- <a href={href} className={className}>
24
- {children}
25
- </a>
26
- );
27
-
28
- const chipClass =
29
- "rounded-full border border-border px-3 py-1 text-xs font-medium text-muted-foreground no-underline";
30
-
31
- export default function PostView({
32
- slug,
33
- initialPost,
34
- initialCategories,
35
- initialTags,
36
- categoryHref,
37
- tagHref,
38
- LinkComponent = PlainLink,
39
- }: PostViewProps) {
40
- const { post, notFound, categories, tags, error } = usePost({
41
- slug,
42
- initialPost,
43
- initialCategories,
44
- initialTags,
45
- });
46
-
47
- if (notFound) {
48
- return (
49
- <div className="py-24 text-center">
50
- <p className="text-lg font-medium">Post not found</p>
51
- <p className="mt-2 text-sm text-muted-foreground">It may have been unpublished or moved.</p>
52
- </div>
53
- );
54
- }
55
- if (error) return <p className="py-8 text-sm text-red-600">{error}</p>;
56
- if (post === null) {
57
- return (
58
- <div aria-busy="true">
59
- <div className="h-8 w-2/3 animate-pulse rounded bg-secondary" />
60
- <div className="mt-6 aspect-[16/9] animate-pulse rounded-lg bg-secondary" />
61
- </div>
62
- );
63
- }
64
-
65
- return (
66
- <article className="mx-auto max-w-3xl">
67
- {categories.length > 0 && (
68
- <p className="eyebrow">
69
- {categories.map((c, i) => (
70
- <span key={c.id}>
71
- {i > 0 && " · "}
72
- {categoryHref ? (
73
- <LinkComponent href={categoryHref(c.slug)} className="no-underline">
74
- {c.label}
75
- </LinkComponent>
76
- ) : (
77
- c.label
78
- )}
79
- </span>
80
- ))}
81
- </p>
82
- )}
83
- <h1 className="mt-2 text-3xl font-semibold tracking-tight">{post.title}</h1>
84
- <p className="mt-3 text-sm text-muted-foreground">
85
- <time dateTime={post.dateISO}>{postMetaLine(post)}</time>
86
- </p>
87
- {post.coverUrl && (
88
- <div className="mt-6 aspect-[16/9] overflow-hidden rounded-xl bg-secondary">
89
- <img src={post.coverUrl} alt={post.title} className="h-full w-full object-cover" />
90
- </div>
91
- )}
92
- <div className="mt-8">
93
- <RichContent content={post.richContent} fallbackParagraphs={post.paragraphs} />
94
- </div>
95
- {tags.length > 0 && (
96
- <div className="mt-10 flex flex-wrap gap-2">
97
- {tags.map((t) =>
98
- tagHref ? (
99
- <LinkComponent key={t.id} href={tagHref(t.slug)} className={chipClass}>
100
- {t.label}
101
- </LinkComponent>
102
- ) : (
103
- <span key={t.id} className={chipClass}>
104
- {t.label}
105
- </span>
106
- ),
107
- )}
108
- </div>
109
- )}
110
- </article>
111
- );
112
- }
@@ -1,42 +0,0 @@
1
- // The post-body renderer — wire AS-IS (machinery, not a reference). A post body is a Ricos
2
- // document, not HTML and not text: never innerHTML it, never String() its nodes. This is the
3
- // documented render path (@wix/ricos viewer + quick-start plugins).
4
- //
5
- // In Astro this component MUST be a `client:only="react"` island — the ricos viewer breaks
6
- // under SSR. Dark theme: the ricos CSS hardcodes near-black text; scope an override on
7
- // `.ricos-content` forcing the foreground token (in Astro use <style is:global> — React
8
- // islands don't inherit scoped Astro styles).
9
- import { quickStartViewerPlugins, RicosViewer } from "@wix/ricos";
10
- import "@wix/ricos/css/all-plugins-viewer.css";
11
-
12
- // Module-level, once — never rebuild the plugin list per render.
13
- const plugins = quickStartViewerPlugins();
14
-
15
- export interface RichContentProps {
16
- /** PostDetail.richContent — the Ricos document (plain JSON). */
17
- content: Record<string, unknown> | null;
18
- /** PostDetail.paragraphs — the honest fallback body when richContent is null. */
19
- fallbackParagraphs?: string[];
20
- }
21
-
22
- export default function RichContent({ content, fallbackParagraphs = [] }: RichContentProps) {
23
- if (content) {
24
- return (
25
- <div className="ricos-content">
26
- <RicosViewer content={content as any} plugins={plugins} />
27
- </div>
28
- );
29
- }
30
- if (fallbackParagraphs.length > 0) {
31
- return (
32
- <div className="space-y-4">
33
- {fallbackParagraphs.map((p, i) => (
34
- <p key={i} className="leading-relaxed">
35
- {p}
36
- </p>
37
- ))}
38
- </div>
39
- );
40
- }
41
- return null;
42
- }
@@ -1,31 +0,0 @@
1
- // React binding of the blog feed store (wix/blog/blog-feed-store.ts) — the feed state machine
2
- // (taxonomy filter, cursor paging) lives there, framework-free; this hook subscribes to one
3
- // instance per mounted feed and exposes its state and actions under one name. Astro islands and
4
- // React SPAs use this; a static page, Vue, or Svelte uses the store directly.
5
- //
6
- // SSR-friendly: pass server-fetched data as `initial*` (Astro frontmatter / server component) and
7
- // no client fetch happens; a SPA passes nothing. Category/tag filtering fetches live
8
- // (server-side-filtered); the two filters are mutually exclusive — setting one clears the other.
9
- import { useEffect, useRef, useSyncExternalStore } from "react";
10
- import { createBlogFeedStore, type BlogFeedState, type BlogFeedStore, type BlogFeedStoreOptions } from "../../wix/blog/blog-feed-store";
11
-
12
- export type UseBlogFeedOptions = BlogFeedStoreOptions;
13
-
14
- export type UseBlogFeed = BlogFeedState & Pick<BlogFeedStore, "setActiveCategoryId" | "setActiveTagId" | "loadMore">;
15
-
16
- export function useBlogFeed(options: UseBlogFeedOptions = {}): UseBlogFeed {
17
- const ref = useRef<BlogFeedStore | null>(null);
18
- if (!ref.current) ref.current = createBlogFeedStore(options);
19
- const store = ref.current;
20
- useEffect(() => {
21
- store.start();
22
- return () => store.stop();
23
- }, [store]);
24
- const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);
25
- return {
26
- ...state,
27
- setActiveCategoryId: store.setActiveCategoryId,
28
- setActiveTagId: store.setActiveTagId,
29
- loadMore: store.loadMore,
30
- };
31
- }
@@ -1,22 +0,0 @@
1
- // React binding of the post store (wix/blog/post-store.ts) — post-by-slug loading and the resolved
2
- // category/tag chips live there, framework-free; this hook subscribes to one instance per slug.
3
- //
4
- // SSR-friendly: pass the server-fetched post (and taxonomy) as `initial*` and no client fetch
5
- // happens; a SPA passes only the slug. A slug change creates a fresh store and refetches.
6
- import { useEffect, useRef, useSyncExternalStore } from "react";
7
- import { createPostStore, type PostState, type PostStore, type PostStoreOptions } from "../../wix/blog/post-store";
8
-
9
- export type UsePostOptions = PostStoreOptions;
10
-
11
- export type UsePost = PostState;
12
-
13
- export function usePost({ slug, initialPost, initialCategories, initialTags }: UsePostOptions): UsePost {
14
- const ref = useRef<{ slug: string; store: PostStore } | null>(null);
15
- if (!ref.current || ref.current.slug !== slug) ref.current = { slug, store: createPostStore({ slug, initialPost, initialCategories, initialTags }) };
16
- const store = ref.current.store;
17
- useEffect(() => {
18
- store.start();
19
- return () => store.stop();
20
- }, [store]);
21
- return useSyncExternalStore(store.subscribe, store.getState, store.getState);
22
- }