@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,32 +0,0 @@
1
- // React binding of the collection-projects store (wix/portfolio/collection-projects-store.ts) —
2
- // slug → collection header + its projects lives there, framework-free; this hook subscribes to
3
- // one instance per (slug, mount) and recreates it when the slug changes. SSR-friendly: pass both
4
- // `initial*` and no client fetch happens. `notFound` is the real not-found signal (collection
5
- // stays null while loading too) — route a 404 off it, never off a transient null.
6
- import { useEffect, useRef, useSyncExternalStore } from "react";
7
- import {
8
- createCollectionProjectsStore,
9
- type CollectionProjectsState,
10
- type CollectionProjectsStore,
11
- type CollectionProjectsStoreOptions,
12
- } from "../../wix/portfolio/collection-projects-store";
13
-
14
- export type UseCollectionProjectsOptions = CollectionProjectsStoreOptions;
15
-
16
- export type UseCollectionProjects = CollectionProjectsState;
17
-
18
- export function useCollectionProjects(
19
- slug: string,
20
- { initialCollection, initialProjects }: UseCollectionProjectsOptions = {},
21
- ): UseCollectionProjects {
22
- const ref = useRef<{ slug: string; store: CollectionProjectsStore } | null>(null);
23
- if (!ref.current || ref.current.slug !== slug) {
24
- ref.current = { slug, store: createCollectionProjectsStore(slug, { initialCollection, initialProjects }) };
25
- }
26
- const store = ref.current.store;
27
- useEffect(() => {
28
- store.start();
29
- return () => store.stop();
30
- }, [store]);
31
- return useSyncExternalStore(store.subscribe, store.getState, store.getState);
32
- }
@@ -1,21 +0,0 @@
1
- // React binding of the collections store (wix/portfolio/collections-store.ts) — the gallery's
2
- // load state lives there, framework-free; this hook subscribes to one instance per mounted
3
- // gallery. SSR-friendly: pass server-fetched data as `initialCollections` and no client fetch
4
- // happens; a SPA passes nothing. A static page, Vue, or Svelte uses the store directly.
5
- import { useEffect, useRef, useSyncExternalStore } from "react";
6
- import { createCollectionsStore, type CollectionsState, type CollectionsStore, type CollectionsStoreOptions } from "../../wix/portfolio/collections-store";
7
-
8
- export type UseCollectionsOptions = CollectionsStoreOptions;
9
-
10
- export type UseCollections = CollectionsState;
11
-
12
- export function useCollections(options: UseCollectionsOptions = {}): UseCollections {
13
- const ref = useRef<CollectionsStore | null>(null);
14
- if (!ref.current) ref.current = createCollectionsStore(options);
15
- const store = ref.current;
16
- useEffect(() => {
17
- store.start();
18
- return () => store.stop();
19
- }, [store]);
20
- return useSyncExternalStore(store.subscribe, store.getState, store.getState);
21
- }
@@ -1,31 +0,0 @@
1
- // React binding of the project-detail store (wix/portfolio/project-detail-store.ts) — slug →
2
- // project + media gallery lives there, framework-free; this hook subscribes to one instance per
3
- // (slug, mount) and recreates it when the slug changes. SSR-friendly: pass both `initial*` and no
4
- // client fetch happens. `notFound` is the real not-found signal (project stays null while loading).
5
- import { useEffect, useRef, useSyncExternalStore } from "react";
6
- import {
7
- createProjectDetailStore,
8
- type ProjectDetailState,
9
- type ProjectDetailStore,
10
- type ProjectDetailStoreOptions,
11
- } from "../../wix/portfolio/project-detail-store";
12
-
13
- export type UseProjectDetailOptions = ProjectDetailStoreOptions;
14
-
15
- export type UseProjectDetail = ProjectDetailState;
16
-
17
- export function useProjectDetail(
18
- slug: string,
19
- { initialProject, initialItems }: UseProjectDetailOptions = {},
20
- ): UseProjectDetail {
21
- const ref = useRef<{ slug: string; store: ProjectDetailStore } | null>(null);
22
- if (!ref.current || ref.current.slug !== slug) {
23
- ref.current = { slug, store: createProjectDetailStore(slug, { initialProject, initialItems }) };
24
- }
25
- const store = ref.current.store;
26
- useEffect(() => {
27
- store.start();
28
- return () => store.stop();
29
- }, [store]);
30
- return useSyncExternalStore(store.subscribe, store.getState, store.getState);
31
- }
@@ -1,82 +0,0 @@
1
- // One collection's header + its projects, by slug, as a framework-free store — the logic behind
2
- // useCollectionProjects, usable from React (the hook wraps it), from a static page's collection
3
- // view, from Vue/Svelte, or as the specification for a port.
4
- //
5
- // SSR-friendly: pass BOTH `initialCollection` and `initialProjects` and nothing is fetched. With
6
- // only the collection seeded, `start()` fetches its projects; with nothing seeded it resolves the
7
- // slug first. `notFound` is the real not-found signal (collection stays null while loading too) —
8
- // route a 404 off it, never off a transient null. One store per (slug, mount):
9
- // createCollectionProjectsStore(slug, options), not a singleton.
10
- import { fetchCollectionBySlug, fetchProjects } from "./portfolio";
11
- import type { CollectionSummary, ProjectSummary } from "./types";
12
-
13
- export interface CollectionProjectsStoreOptions {
14
- initialCollection?: CollectionSummary;
15
- initialProjects?: ProjectSummary[];
16
- }
17
-
18
- export interface CollectionProjectsState {
19
- /** null while loading AND when not found — check `notFound` to tell them apart. */
20
- collection: CollectionSummary | null;
21
- notFound: boolean;
22
- /** null while the first load is in flight — render skeletons, not an empty state. */
23
- projects: ProjectSummary[] | null;
24
- error: string | null;
25
- }
26
-
27
- export interface CollectionProjectsStore {
28
- getState(): CollectionProjectsState;
29
- subscribe(listener: () => void): () => void;
30
- /** Resolve the slug and load its projects unless both were seeded. Call once when mounted. */
31
- start(): void;
32
- /** Stop reacting; drop late responses. */
33
- stop(): void;
34
- }
35
-
36
- export function createCollectionProjectsStore(
37
- slug: string,
38
- { initialCollection, initialProjects }: CollectionProjectsStoreOptions = {},
39
- ): CollectionProjectsStore {
40
- let collection: CollectionSummary | null = initialCollection ?? null;
41
- let notFound = false;
42
- let projects: ProjectSummary[] | null = initialProjects ?? null;
43
- let error: string | null = null;
44
- let started = false;
45
- const listeners = new Set<() => void>();
46
- let snapshot: CollectionProjectsState | null = null;
47
- const emit = () => { snapshot = null; for (const fn of listeners) fn(); };
48
-
49
- return {
50
- getState() {
51
- return (snapshot ??= { collection, notFound, projects, error });
52
- },
53
- subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); },
54
- start() {
55
- if (started) return;
56
- started = true;
57
- if (initialCollection && initialProjects) return;
58
- (async () => {
59
- try {
60
- const col = initialCollection ?? (await fetchCollectionBySlug(slug));
61
- if (!started) return;
62
- if (!col) {
63
- notFound = true;
64
- projects = [];
65
- emit();
66
- return;
67
- }
68
- collection = col;
69
- emit();
70
- const list = await fetchProjects({ collectionId: col.id });
71
- if (started) { projects = list; emit(); }
72
- } catch (e) {
73
- if (!started) return;
74
- projects = [];
75
- error = e instanceof Error ? e.message : String(e);
76
- emit();
77
- }
78
- })();
79
- },
80
- stop() { started = false; },
81
- };
82
- }
@@ -1,58 +0,0 @@
1
- // The collections gallery as a framework-free store — the logic behind useCollections, usable
2
- // from React (useCollections wraps it with useSyncExternalStore), from a static page or
3
- // Vue/Svelte (subscribe and render), or as the specification for a port. State, subscribe/getState,
4
- // start()/stop(), emit after every change.
5
- //
6
- // SSR-friendly: seed with `initialCollections` and nothing is fetched; without a seed `start()`
7
- // fetches once. One store per mounted gallery: createCollectionsStore(), not a singleton.
8
- import { fetchCollections } from "./portfolio";
9
- import type { CollectionSummary } from "./types";
10
-
11
- export interface CollectionsStoreOptions {
12
- initialCollections?: CollectionSummary[];
13
- }
14
-
15
- export interface CollectionsState {
16
- /** null while the first load is in flight — render skeletons, not an empty state. */
17
- collections: CollectionSummary[] | null;
18
- error: string | null;
19
- }
20
-
21
- export interface CollectionsStore {
22
- getState(): CollectionsState;
23
- subscribe(listener: () => void): () => void;
24
- /** Fetch when no seed was given. Call once when mounted (a browser). */
25
- start(): void;
26
- /** Stop reacting; drop a late response. */
27
- stop(): void;
28
- }
29
-
30
- export function createCollectionsStore({ initialCollections }: CollectionsStoreOptions = {}): CollectionsStore {
31
- let collections: CollectionSummary[] | null = initialCollections ?? null;
32
- let error: string | null = null;
33
- let started = false;
34
- const listeners = new Set<() => void>();
35
- let snapshot: CollectionsState | null = null;
36
- const emit = () => { snapshot = null; for (const fn of listeners) fn(); };
37
-
38
- return {
39
- getState() {
40
- return (snapshot ??= { collections, error });
41
- },
42
- subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); },
43
- start() {
44
- if (started) return;
45
- started = true;
46
- if (initialCollections) return;
47
- fetchCollections()
48
- .then((c) => { if (started) { collections = c; emit(); } })
49
- .catch((e) => {
50
- if (!started) return;
51
- collections = [];
52
- error = e instanceof Error ? e.message : String(e);
53
- emit();
54
- });
55
- },
56
- stop() { started = false; },
57
- };
58
- }
@@ -1,177 +0,0 @@
1
- // Portfolio rules and DTO mapping — transport-agnostic, imported by BOTH transports: ./portfolio.ts
2
- // (the SDK, managed Astro and React) and the REST twin in references/portfolio/rest/portfolio.ts
3
- // (fetch, a static site or a port to another language). Every rule about hidden entities, order,
4
- // covers, media kinds lives HERE, once. A raw entity may come from the SDK (`_id`) or from REST
5
- // (`id`); the mappers accept both. Imports are type-only so a strip to JS emits no imports.
6
- import type { CollectionSummary, GalleryItem, ProjectDetail, ProjectDetailRow, ProjectSummary } from "./types";
7
-
8
- /** A raw Portfolio v1 entity as either transport returns it. */
9
- export type Raw = Record<string, any>;
10
- /** Media value + size → https URL. Injected: the SDK transport scales through @wix/sdk, REST through the URL form. */
11
- export type ImgSrc = (value: any, width: number, height: number) => string;
12
- /**
13
- * A `wix:video://` reference → its mp4 rendition and poster, or null when it can't be resolved.
14
- * Injected: only the SDK can resolve the string form (media.getVideoUrl); REST never receives it
15
- * (its videoInfo is already an object with resolutions + posters, handled here).
16
- */
17
- export type VideoSrc = (wixVideoRef: string) => { url: string; thumbnail: string } | null;
18
-
19
- const id = (raw: Raw | undefined | null): string => raw?._id ?? raw?.id ?? "";
20
-
21
- /**
22
- * An image reference as either transport carries it — the SDK's bare `wix:image://` string, or
23
- * REST's `imageInfo` object `{ id, url, filename }` — normalized to the `wix:image://` form so
24
- * imgSrc scales both to the SAME URL (REST's `url` is a fixed 1024×1024 rendition; the id is the
25
- * media file). "" when there is no image.
26
- */
27
- export function imageRef(value: unknown): string {
28
- if (!value) return "";
29
- if (typeof value === "string") return value;
30
- const o = value as Raw;
31
- if (typeof o.id === "string" && o.id) return `wix:image://v1/${o.id}/${o.filename ?? o.id}`;
32
- return typeof o.url === "string" ? o.url : "";
33
- }
34
-
35
- /**
36
- * A video as either transport carries it: the SDK's bare `wix:video://` string (resolved by the
37
- * injected videoSrc — 720p is the standard transcode), or REST's videoInfo object
38
- * `{ resolutions: [{ url }], posters: [{ id, url }] }` (optimal resolution first).
39
- */
40
- export function toVideo(value: unknown, imgSrc: ImgSrc, videoSrc: VideoSrc): { videoUrl: string | null; posterUrl: string } {
41
- if (typeof value === "string") {
42
- const v = value.startsWith("wix:video://") ? videoSrc(value) : null;
43
- return v ? { videoUrl: v.url, posterUrl: imgSrc(imageRef(v.thumbnail), 1200, 675) } : { videoUrl: null, posterUrl: "" };
44
- }
45
- const raw = value as Raw | null | undefined;
46
- const url = raw?.resolutions?.[0]?.url;
47
- return {
48
- videoUrl: typeof url === "string" ? url : null,
49
- posterUrl: imgSrc(imageRef(raw?.posters?.[0]), 1200, 675),
50
- };
51
- }
52
-
53
- // ---- DTO mappers -----------------------------------------------------------------------------------
54
-
55
- export function toCollection(raw: Raw, imgSrc: ImgSrc): CollectionSummary {
56
- return {
57
- id: id(raw),
58
- slug: raw.slug ?? "",
59
- title: raw.title ?? "",
60
- description: raw.description ?? "",
61
- imageUrl: imgSrc(imageRef(raw.coverImage?.imageInfo), 1200, 900),
62
- };
63
- }
64
-
65
- /** coverImage is ONE-OF with coverVideo — a video-covered project falls back to its poster. */
66
- export function projectCover(raw: Raw, imgSrc: ImgSrc, videoSrc: VideoSrc): string {
67
- return imgSrc(imageRef(raw.coverImage?.imageInfo), 1200, 900) || toVideo(raw.coverVideo?.videoInfo, imgSrc, videoSrc).posterUrl;
68
- }
69
-
70
- export function toProject(raw: Raw, imgSrc: ImgSrc, videoSrc: VideoSrc): ProjectSummary {
71
- return {
72
- id: id(raw),
73
- slug: raw.slug ?? "",
74
- title: raw.title ?? "",
75
- description: raw.description ?? "",
76
- imageUrl: projectCover(raw, imgSrc, videoSrc),
77
- collectionIds: raw.collectionIds ?? [],
78
- };
79
- }
80
-
81
- /** A details row is a one-of: { label, text } or { label, link: { text, url, target } }. */
82
- export function toDetailRow(raw: Raw): ProjectDetailRow {
83
- return {
84
- label: raw.label ?? "",
85
- text: raw.link?.text ?? raw.text ?? "",
86
- url: raw.link?.url ?? null,
87
- target: raw.link?.target ?? null,
88
- };
89
- }
90
-
91
- export function toDetail(raw: Raw, imgSrc: ImgSrc, videoSrc: VideoSrc): ProjectDetail {
92
- return { ...toProject(raw, imgSrc, videoSrc), details: ((raw.details ?? []) as Raw[]).map(toDetailRow) };
93
- }
94
-
95
- /** IMAGE → image item, VIDEO → video item; UNDEFINED or unresolvable media → null (nothing renderable). */
96
- export function toGalleryItem(raw: Raw, imgSrc: ImgSrc, videoSrc: VideoSrc): GalleryItem | null {
97
- const base = {
98
- id: id(raw),
99
- title: raw.title ?? "",
100
- description: raw.description ?? "",
101
- linkUrl: raw.link?.url ?? null,
102
- linkTarget: raw.link?.target ?? null,
103
- };
104
- if (raw.type === "IMAGE") {
105
- const imageUrl = imgSrc(imageRef(raw.image?.imageInfo), 1600, 1200);
106
- return imageUrl ? { ...base, kind: "image", imageUrl, videoUrl: null } : null;
107
- }
108
- if (raw.type === "VIDEO") {
109
- const { videoUrl, posterUrl } = toVideo(raw.video?.videoInfo, imgSrc, videoSrc);
110
- return videoUrl ? { ...base, kind: "video", imageUrl: posterUrl, videoUrl } : null;
111
- }
112
- return null;
113
- }
114
-
115
- // ---- list rules -----------------------------------------------------------------------------------
116
-
117
- /**
118
- * Visible collections in the owner's dashboard order (sortOrder — collections have one, projects
119
- * don't). An omitted `hidden` comes back ABSENT (proto3): test falsy, never === false.
120
- */
121
- export function visibleCollections(raws: Raw[], imgSrc: ImgSrc): CollectionSummary[] {
122
- return raws
123
- .filter((c) => !c.hidden)
124
- .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
125
- .map((c) => toCollection(c, imgSrc));
126
- }
127
-
128
- /** One visible collection, or null when missing or hidden (a real 404, never a fallback). */
129
- export function visibleCollection(raw: Raw | undefined | null, imgSrc: ImgSrc): CollectionSummary | null {
130
- return raw && !raw.hidden ? toCollection(raw, imgSrc) : null;
131
- }
132
-
133
- /**
134
- * Visible projects in list order (Project exposes no sortOrder), optionally only one collection's.
135
- * The collection filter is client-side over the one list (portfolios are small; a project links
136
- * to collections via collectionIds).
137
- */
138
- export function visibleProjects(raws: Raw[], collectionId: string | undefined, imgSrc: ImgSrc, videoSrc: VideoSrc): ProjectSummary[] {
139
- return raws
140
- .filter((p) => !p.hidden)
141
- .filter((p) => !collectionId || ((p.collectionIds ?? []) as string[]).includes(collectionId))
142
- .map((p) => toProject(p, imgSrc, videoSrc));
143
- }
144
-
145
- /** One visible project with its details rows, or null when missing or hidden. */
146
- export function visibleProject(raw: Raw | undefined | null, imgSrc: ImgSrc, videoSrc: VideoSrc): ProjectDetail | null {
147
- return raw && !raw.hidden ? toDetail(raw, imgSrc, videoSrc) : null;
148
- }
149
-
150
- /** A project's gallery in dashboard order (item sortOrder); UNDEFINED and unresolvable items dropped. */
151
- export function galleryItems(raws: Raw[], imgSrc: ImgSrc, videoSrc: VideoSrc): GalleryItem[] {
152
- return raws
153
- .slice()
154
- .sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
155
- .map((it) => toGalleryItem(it, imgSrc, videoSrc))
156
- .filter((g): g is GalleryItem => g !== null);
157
- }
158
-
159
- // ---- render rule ----------------------------------------------------------------------------------
160
-
161
- /** The one element a gallery item renders as, attribute names as HTML spells them. */
162
- export type MediaElement =
163
- | { tag: "img"; attrs: { src: string; alt: string; loading: "lazy"; decoding: "async" } }
164
- | { tag: "video"; attrs: { src: string; poster?: string; controls: ""; playsinline: "" } };
165
-
166
- /**
167
- * Branch on `kind` once, here: a video item is a <video> with its poster, an image item an <img>,
168
- * anything else null — never a broken tag, never an <img> for a video. The shipped GalleryMedia.tsx
169
- * renders this; a static page or a port creates the element from it.
170
- */
171
- export function mediaElement(item: GalleryItem): MediaElement | null {
172
- if (item.kind === "video" && item.videoUrl) {
173
- return { tag: "video", attrs: { src: item.videoUrl, ...(item.imageUrl ? { poster: item.imageUrl } : {}), controls: "", playsinline: "" } };
174
- }
175
- if (item.imageUrl) return { tag: "img", attrs: { src: item.imageUrl, alt: item.title, loading: "lazy", decoding: "async" } };
176
- return null;
177
- }
@@ -1,78 +0,0 @@
1
- // Portfolio reads (Wix Portfolio v1) over the SDK — the only file that touches raw portfolio
2
- // entities on this transport. Read-only vertical: no cart, no checkout, no @wix/ecom. Everything
3
- // it returns is a plain DTO from ./types. The rules and mappers live in ./portfolio-core (shared
4
- // with the REST twin in references/portfolio/rest/); this file is the transport only. Copy as-is;
5
- // extend by adding functions, not by editing these.
6
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/list-collections.md
7
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/list-projects.md
8
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/project-items/list-project-items.md
9
- // docs: https://dev.wix.com/docs/sdk/core-modules/sdk/media.md
10
- import {
11
- collections as collectionsModule,
12
- projects as projectsModule,
13
- projectItems as projectItemsModule,
14
- } from "@wix/portfolio";
15
- import { media, VideoResolution } from "@wix/sdk";
16
- import { wixModule } from "../sdk";
17
- import { imgSrc } from "../media";
18
- import {
19
- galleryItems,
20
- visibleCollection,
21
- visibleCollections,
22
- visibleProject,
23
- visibleProjects,
24
- type Raw,
25
- type VideoSrc,
26
- } from "./portfolio-core";
27
- import type { CollectionSummary, GalleryItem, ProjectDetail, ProjectSummary } from "./types";
28
-
29
- const collections = wixModule(collectionsModule);
30
- const projects = wixModule(projectsModule);
31
- const projectItems = wixModule(projectItemsModule);
32
-
33
- // The SDK types coverImage.imageInfo / item.image.imageInfo as a bare wix:image:// STRING and
34
- // videoInfo as a bare wix:video:// string; getVideoUrl derives the mp4 rendition + poster.
35
- const videoSrc: VideoSrc = (ref) => {
36
- try {
37
- const v = media.getVideoUrl(ref, VideoResolution.MID);
38
- return { url: v.url, thumbnail: v.thumbnail };
39
- } catch {
40
- return null;
41
- }
42
- };
43
-
44
- /** List visible collections in the owner's dashboard order (sortOrder). */
45
- export async function fetchCollections({ limit = 100 } = {}): Promise<CollectionSummary[]> {
46
- const res = await collections.listCollections({ paging: { limit } });
47
- return visibleCollections((res.collections ?? []) as Raw[], imgSrc);
48
- }
49
-
50
- /** Fetch one visible collection by its URL slug. Null when not found or hidden. */
51
- export async function fetchCollectionBySlug(slug: string): Promise<CollectionSummary | null> {
52
- const res = await collections.queryCollections().eq("slug", slug).limit(1).find();
53
- return visibleCollection(res.items?.[0] as Raw | undefined, imgSrc);
54
- }
55
-
56
- /** List visible projects (list order), optionally only one collection's. */
57
- export async function fetchProjects({
58
- collectionId,
59
- limit = 100,
60
- }: { collectionId?: string; limit?: number } = {}): Promise<ProjectSummary[]> {
61
- const res = await projects.listProjects({ paging: { limit } });
62
- return visibleProjects((res.projects ?? []) as Raw[], collectionId, imgSrc, videoSrc);
63
- }
64
-
65
- /** Fetch one visible project by its URL slug. Null when not found or hidden. */
66
- export async function fetchProjectBySlug(slug: string): Promise<ProjectDetail | null> {
67
- const res = await projects.queryProjects().eq("slug", slug).limit(1).find();
68
- return visibleProject(res.items?.[0] as Raw | undefined, imgSrc, videoSrc);
69
- }
70
-
71
- /**
72
- * A project's media gallery in dashboard order (item sortOrder). IMAGE and VIDEO items only —
73
- * UNDEFINED and unresolvable media are dropped. First arg is the project _id (positional).
74
- */
75
- export async function fetchProjectGallery(projectId: string): Promise<GalleryItem[]> {
76
- const res = await projectItems.listProjectItems(projectId, { paging: { limit: 100 } });
77
- return galleryItems((res.items ?? []) as Raw[], imgSrc, videoSrc);
78
- }
@@ -1,81 +0,0 @@
1
- // Project detail + media gallery, by slug, as a framework-free store — the logic behind
2
- // useProjectDetail, usable from React (the hook wraps it), from a static page's project view,
3
- // from Vue/Svelte, or as the specification for a port.
4
- //
5
- // SSR-friendly: pass BOTH `initialProject` and `initialItems` and nothing is fetched. With only
6
- // the project seeded, `start()` fetches its gallery; with nothing seeded it resolves the slug
7
- // first. `notFound` is the real not-found signal (project stays null while loading). One store
8
- // per (slug, mount): createProjectDetailStore(slug, options), not a singleton.
9
- import { fetchProjectBySlug, fetchProjectGallery } from "./portfolio";
10
- import type { GalleryItem, ProjectDetail } from "./types";
11
-
12
- export interface ProjectDetailStoreOptions {
13
- initialProject?: ProjectDetail;
14
- initialItems?: GalleryItem[];
15
- }
16
-
17
- export interface ProjectDetailState {
18
- /** null while loading AND when not found — check `notFound` to tell them apart. */
19
- project: ProjectDetail | null;
20
- notFound: boolean;
21
- /** null while the gallery load is in flight — render skeletons, not an empty state. */
22
- items: GalleryItem[] | null;
23
- error: string | null;
24
- }
25
-
26
- export interface ProjectDetailStore {
27
- getState(): ProjectDetailState;
28
- subscribe(listener: () => void): () => void;
29
- /** Resolve the slug and load its gallery unless both were seeded. Call once when mounted. */
30
- start(): void;
31
- /** Stop reacting; drop late responses. */
32
- stop(): void;
33
- }
34
-
35
- export function createProjectDetailStore(
36
- slug: string,
37
- { initialProject, initialItems }: ProjectDetailStoreOptions = {},
38
- ): ProjectDetailStore {
39
- let project: ProjectDetail | null = initialProject ?? null;
40
- let notFound = false;
41
- let items: GalleryItem[] | null = initialItems ?? null;
42
- let error: string | null = null;
43
- let started = false;
44
- const listeners = new Set<() => void>();
45
- let snapshot: ProjectDetailState | null = null;
46
- const emit = () => { snapshot = null; for (const fn of listeners) fn(); };
47
-
48
- return {
49
- getState() {
50
- return (snapshot ??= { project, notFound, items, error });
51
- },
52
- subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); },
53
- start() {
54
- if (started) return;
55
- started = true;
56
- if (initialProject && initialItems) return;
57
- (async () => {
58
- try {
59
- const proj = initialProject ?? (await fetchProjectBySlug(slug));
60
- if (!started) return;
61
- if (!proj) {
62
- notFound = true;
63
- items = [];
64
- emit();
65
- return;
66
- }
67
- project = proj;
68
- emit();
69
- const gallery = await fetchProjectGallery(proj.id);
70
- if (started) { items = gallery; emit(); }
71
- } catch (e) {
72
- if (!started) return;
73
- items = [];
74
- error = e instanceof Error ? e.message : String(e);
75
- emit();
76
- }
77
- })();
78
- },
79
- stop() { started = false; },
80
- };
81
- }
@@ -1,55 +0,0 @@
1
- // Portfolio DTOs — the serializable shapes every hook, component, and page consumes.
2
- // Plain JSON: safe as Astro island props or across server/client boundaries. Images are
3
- // resolved https URLs; videos are playable mp4 URLs with a poster frame.
4
-
5
- /** A collection as the gallery grid needs it. */
6
- export interface CollectionSummary {
7
- id: string;
8
- slug: string;
9
- title: string;
10
- description: string;
11
- /** Resolved https URL ("" when the collection has no cover). */
12
- imageUrl: string;
13
- }
14
-
15
- /** A project as a grid tile needs it. */
16
- export interface ProjectSummary {
17
- id: string;
18
- slug: string;
19
- title: string;
20
- description: string;
21
- /** Cover image; a video-covered project falls back to its poster frame ("" when neither). */
22
- imageUrl: string;
23
- /** The collections this project belongs to (a project can be in several). */
24
- collectionIds: string[];
25
- }
26
-
27
- /** One row of a project's metadata (Role, Year, Client…): plain text or an outbound link. */
28
- export interface ProjectDetailRow {
29
- label: string;
30
- text: string;
31
- /** Non-null → render the row's text as a link. */
32
- url: string | null;
33
- /** Link rows only: "_blank" | "_self". */
34
- target: string | null;
35
- }
36
-
37
- /** A project as the detail page needs it. */
38
- export interface ProjectDetail extends ProjectSummary {
39
- details: ProjectDetailRow[];
40
- }
41
-
42
- /** One media item of a project's gallery (dashboard order). */
43
- export interface GalleryItem {
44
- id: string;
45
- kind: "image" | "video";
46
- title: string;
47
- description: string;
48
- /** image: the resolved image. video: the poster frame ("" when the video has none). */
49
- imageUrl: string;
50
- /** video only: playable mp4 URL. */
51
- videoUrl: string | null;
52
- /** Optional owner-attached outbound link for this item. */
53
- linkUrl: string | null;
54
- linkTarget: string | null;
55
- }
@@ -1,40 +0,0 @@
1
- ---
2
- // The site chrome for every portfolio page — THIS file (header/footer/nav) plus the @theme
3
- // token block in src/styles/global.css are what you brand. Keep the <slot name="seo-tags" />
4
- // in <head> and the global.css import. (Deploy is fill-only: if another vertical is already
5
- // deployed, its SiteLayout won — merge a Portfolio nav link there instead.)
6
- import "../styles/global.css";
7
-
8
- interface Props {
9
- title: string;
10
- description?: string;
11
- }
12
- const { title, description } = Astro.props;
13
- ---
14
-
15
- <!doctype html>
16
- <html lang="en">
17
- <head>
18
- <meta charset="UTF-8" />
19
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
20
- <title>{title}</title>
21
- {description && <meta name="description" content={description} />}
22
- <slot name="seo-tags" />
23
- </head>
24
- <body>
25
- <header class="sticky top-0 z-40 border-b border-border bg-background/80 backdrop-blur">
26
- <div class="mx-auto flex h-16 max-w-6xl items-center justify-between px-6">
27
- <a href="/" class="text-base font-bold tracking-tight text-foreground no-underline">Brand Name</a>
28
- <nav class="flex items-center gap-6 text-sm">
29
- <a href="/portfolio" class="text-foreground no-underline transition-colors hover:text-muted-foreground">Portfolio</a>
30
- </nav>
31
- </div>
32
- </header>
33
- <main class="mx-auto max-w-6xl px-6 pb-24 pt-10">
34
- <slot />
35
- </main>
36
- <footer class="border-t border-border px-6 py-10 text-center text-sm text-muted-foreground">
37
- © Brand Name
38
- </footer>
39
- </body>
40
- </html>