@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,289 +0,0 @@
1
- // The shop listing as a framework-free store — the logic behind useShop, usable from React
2
- // (useShop wraps it with useSyncExternalStore), from a static page or Vue/Svelte (subscribe and
3
- // render), or as the specification for a port. Same shape as cart-store.ts: state, actions,
4
- // subscribe/getState, emit after every change.
5
- //
6
- // Category, sort, price/stock/search filters, option facets, and cursor paging are all applied
7
- // by Wix across the whole catalog (searchCatalog), never to a page already in hand. A changed
8
- // selection starts a fresh cursor chain; a late response from a superseded query is dropped.
9
- //
10
- // SSR-friendly: seed with `initialProducts`/`initialCategories` and they render at once; `start()`
11
- // then revalidates the first page to open the cursor chain, replacing the seed without a
12
- // skeleton flash. `initialCategoryId` scopes the first query (a /category/[slug] page).
13
- //
14
- // URL state: sort, filters, facet choices (and a live category switch on /shop) are read from the
15
- // query string by `start()` and written back with replaceState after every change — a filtered
16
- // gallery is a link a shopper can share, reload, and step back to. Paging stays out of the URL.
17
- //
18
- // One store per mounted listing (a page can hold a shop and a featured rail): createShopStore(),
19
- // not a singleton. The cart store is a singleton because the cart is one per visitor.
20
- import { CATALOG_SORTS, fetchCategories, fetchFacetData, searchCatalog, type CatalogSort } from "./catalog";
21
- import type { Category, Facet, PriceRange, ProductSummary } from "./types";
22
-
23
- export const SORTS = CATALOG_SORTS;
24
-
25
- export interface ShopFilters {
26
- minPrice?: number | string;
27
- maxPrice?: number | string;
28
- inStockOnly?: boolean;
29
- /** Name search, max 100 chars. */
30
- search?: string;
31
- }
32
-
33
- export interface ShopStoreOptions {
34
- initialProducts?: ProductSummary[];
35
- initialCategories?: Category[];
36
- /** Scope the listing to one category from the first render (a /category/[slug] page). */
37
- initialCategoryId?: string | null;
38
- pageSize?: number;
39
- /** Mirror the selection into the query string (default true; off for a rail that isn't the page's subject). */
40
- syncUrl?: boolean;
41
- }
42
-
43
- /** Everything a listing surface renders from. Read it with getState() or through a subscription. */
44
- export interface ShopState {
45
- /** null while the first load is in flight — render skeletons, not an empty state. */
46
- products: ProductSummary[] | null;
47
- /** Matching products across the whole catalog for the current selection; null until known. */
48
- total: number | null;
49
- categories: Category[];
50
- /** null = "all products". */
51
- activeCategoryId: string | null;
52
- sort: CatalogSort;
53
- filters: ShopFilters;
54
- /** The filterable options of the current scope (Color, Size…), from the catalog itself. */
55
- facets: Facet[];
56
- /** Lowest and highest product price in the scope — the price slider's bounds; null until known or when equal. */
57
- priceRange: PriceRange | null;
58
- /** Selected facet choice ids — products carrying ANY of them match. */
59
- selectedChoiceIds: string[];
60
- /** True when any filter or facet is active. */
61
- hasActiveFilters: boolean;
62
- loading: boolean;
63
- error: string | null;
64
- hasMore: boolean;
65
- loadingMore: boolean;
66
- }
67
-
68
- export interface ShopStore {
69
- getState(): ShopState;
70
- subscribe(listener: () => void): () => void;
71
- /** Adopt the URL, fetch categories/facets, open the cursor chain. Call once when mounted (a browser). */
72
- start(): void;
73
- /** Stop reacting; drop late responses. */
74
- stop(): void;
75
- setActiveCategoryId(id: string | null): void;
76
- setSort(sort: CatalogSort): void;
77
- setFilters(filters: ShopFilters): void;
78
- toggleChoice(choiceId: string): void;
79
- /** Clears price/stock/search filters and facet selections (keeps category and sort). */
80
- clearFilters(): void;
81
- retry(): void;
82
- loadMore(): Promise<void>;
83
- }
84
-
85
- const URL_KEYS = { sort: "sort", min: "min", max: "max", stock: "stock", q: "q", choice: "choice", category: "category" } as const;
86
-
87
- function readUrlState(): { sort?: CatalogSort; filters: ShopFilters; choiceIds: string[]; categoryId?: string | null } | null {
88
- if (typeof window === "undefined") return null;
89
- const p = new URLSearchParams(window.location.search);
90
- const sort = p.get(URL_KEYS.sort);
91
- const filters: ShopFilters = {};
92
- if (p.get(URL_KEYS.min)) filters.minPrice = p.get(URL_KEYS.min)!;
93
- if (p.get(URL_KEYS.max)) filters.maxPrice = p.get(URL_KEYS.max)!;
94
- if (p.get(URL_KEYS.stock) === "1") filters.inStockOnly = true;
95
- if (p.get(URL_KEYS.q)) filters.search = p.get(URL_KEYS.q)!;
96
- return {
97
- sort: sort && sort in CATALOG_SORTS ? (sort as CatalogSort) : undefined,
98
- filters,
99
- choiceIds: p.getAll(URL_KEYS.choice),
100
- categoryId: p.has(URL_KEYS.category) ? p.get(URL_KEYS.category) : undefined,
101
- };
102
- }
103
-
104
- function writeUrlState(s: { sort: CatalogSort; filters: ShopFilters; selectedChoiceIds: string[]; activeCategoryId: string | null }, initialCategoryId: string | null): void {
105
- if (typeof window === "undefined") return;
106
- const p = new URLSearchParams(window.location.search);
107
- for (const k of Object.values(URL_KEYS)) p.delete(k);
108
- if (s.sort !== "featured") p.set(URL_KEYS.sort, s.sort);
109
- if (s.filters.minPrice != null && s.filters.minPrice !== "") p.set(URL_KEYS.min, String(s.filters.minPrice));
110
- if (s.filters.maxPrice != null && s.filters.maxPrice !== "") p.set(URL_KEYS.max, String(s.filters.maxPrice));
111
- if (s.filters.inStockOnly) p.set(URL_KEYS.stock, "1");
112
- if (s.filters.search?.trim()) p.set(URL_KEYS.q, s.filters.search.trim());
113
- for (const id of s.selectedChoiceIds) p.append(URL_KEYS.choice, id);
114
- if (s.activeCategoryId !== initialCategoryId) p.set(URL_KEYS.category, s.activeCategoryId ?? "");
115
- const qs = p.toString();
116
- const next = `${window.location.pathname}${qs ? `?${qs}` : ""}${window.location.hash}`;
117
- if (next !== `${window.location.pathname}${window.location.search}${window.location.hash}`) window.history.replaceState(window.history.state, "", next);
118
- }
119
-
120
- export function createShopStore({ initialProducts, initialCategories, initialCategoryId = null, pageSize = 24, syncUrl = true }: ShopStoreOptions = {}): ShopStore {
121
- // selection
122
- let activeCategoryId: string | null = initialCategoryId;
123
- let sort: CatalogSort = "featured";
124
- let filters: ShopFilters = {};
125
- let selectedChoiceIds: string[] = [];
126
- let attempt = 0;
127
- // data
128
- let categories: Category[] = initialCategories ?? [];
129
- let facets: Facet[] = [];
130
- let priceRange: PriceRange | null = null;
131
- // the current page; `key` is the selection it answers to (null = the SSR seed, no query yet)
132
- let pageKey: string | null = null;
133
- let products: ProductSummary[] | null = initialProducts ?? null;
134
- let total: number | null = null;
135
- let cursor: string | null = null;
136
- let error: string | null = null;
137
- let loadingMore = false;
138
- // control
139
- let started = false;
140
- let generation = 0;
141
- let pendingMore: object | null = null;
142
- const listeners = new Set<() => void>();
143
-
144
- const selectionKey = () =>
145
- JSON.stringify([pageSize, activeCategoryId, sort, filters.minPrice ?? null, filters.maxPrice ?? null, !!filters.inStockOnly, filters.search ?? "", [...selectedChoiceIds].sort(), attempt]);
146
-
147
- let snapshot: ShopState | null = null;
148
- const emit = () => {
149
- snapshot = null;
150
- for (const fn of listeners) fn();
151
- };
152
-
153
- function getState(): ShopState {
154
- if (snapshot) return snapshot;
155
- const key = selectionKey();
156
- const current = pageKey === key;
157
- const seeded = pageKey === null && products !== null; // SSR seed, first query in flight
158
- const hasActiveFilters =
159
- selectedChoiceIds.length > 0 ||
160
- !!filters.inStockOnly ||
161
- (filters.minPrice != null && filters.minPrice !== "") ||
162
- (filters.maxPrice != null && filters.maxPrice !== "") ||
163
- !!(filters.search && filters.search.trim());
164
- snapshot = {
165
- products: current || seeded ? products : null,
166
- total: current ? total : null,
167
- categories,
168
- activeCategoryId,
169
- sort,
170
- filters,
171
- facets,
172
- priceRange,
173
- selectedChoiceIds,
174
- hasActiveFilters,
175
- // Seeded content on screen is not "loading" — skeletons are only for a genuinely empty wait.
176
- loading: (!current && !seeded) || (current && products === null),
177
- error: current ? error : null,
178
- hasMore: current && !!cursor,
179
- loadingMore: current && loadingMore,
180
- };
181
- return snapshot;
182
- }
183
-
184
- // Facets follow the category scope (a Size facet in "Donuts" is meaningless).
185
- let facetScope: string | null | undefined;
186
- function loadFacets(): void {
187
- if (facetScope === activeCategoryId) return;
188
- facetScope = activeCategoryId;
189
- const scope = activeCategoryId;
190
- fetchFacetData({ categoryId: scope }).then((d) => {
191
- if (!started || scope !== activeCategoryId) return;
192
- facets = d.facets;
193
- priceRange = d.priceRange;
194
- emit();
195
- });
196
- }
197
-
198
- // Run the query for the current selection. Keeps the seed (or the previous page) on screen while
199
- // it runs; only a selection change with no seed shows skeletons.
200
- function query(): void {
201
- if (!started) return;
202
- const key = selectionKey();
203
- const id = ++generation;
204
- pendingMore = null;
205
- if (pageKey !== null) products = null;
206
- pageKey = key; total = null; cursor = null; error = null; loadingMore = false;
207
- emit();
208
- const [limit, categoryId, selectedSort, minPrice, maxPrice, inStockOnly, search, choiceIds] = JSON.parse(key);
209
- searchCatalog({ limit, categoryId, sort: selectedSort, minPrice, maxPrice, inStockOnly, search, choiceIds })
210
- .then((res) => {
211
- if (generation !== id || selectionKey() !== key) return; // superseded — drop it
212
- products = res.products; total = res.total; cursor = res.nextCursor; error = null;
213
- emit();
214
- })
215
- .catch((e) => {
216
- if (generation !== id || selectionKey() !== key) return;
217
- products = []; total = null; cursor = null;
218
- error = e instanceof Error ? e.message : "Couldn't load products.";
219
- emit();
220
- });
221
- }
222
-
223
- function changed(): void {
224
- if (syncUrl) writeUrlState({ sort, filters, selectedChoiceIds, activeCategoryId }, initialCategoryId);
225
- loadFacets();
226
- // A new filters object with the same values keeps the page (same selection, same query).
227
- if (selectionKey() === pageKey) emit();
228
- else query();
229
- }
230
-
231
- return {
232
- getState,
233
- subscribe(fn) {
234
- listeners.add(fn);
235
- return () => listeners.delete(fn);
236
- },
237
- start() {
238
- if (started) return;
239
- started = true;
240
- // Adopt the URL's selection once (the server rendered the defaults).
241
- const u = syncUrl ? readUrlState() : null;
242
- if (u) {
243
- if (u.sort) sort = u.sort;
244
- if (Object.keys(u.filters).length) filters = u.filters;
245
- if (u.choiceIds.length) selectedChoiceIds = u.choiceIds;
246
- if (u.categoryId !== undefined && u.categoryId !== initialCategoryId) activeCategoryId = u.categoryId || null;
247
- }
248
- if (!initialCategories) {
249
- fetchCategories().then((list) => { if (started) { categories = list; emit(); } }).catch(() => { if (started) { categories = []; emit(); } });
250
- }
251
- loadFacets();
252
- query();
253
- },
254
- stop() {
255
- started = false;
256
- generation++;
257
- },
258
- setActiveCategoryId(id) { if (id === activeCategoryId) return; activeCategoryId = id; changed(); },
259
- setSort(next) { if (next === sort) return; sort = next; changed(); },
260
- setFilters(next) { filters = next; changed(); },
261
- toggleChoice(choiceId) {
262
- selectedChoiceIds = selectedChoiceIds.includes(choiceId) ? selectedChoiceIds.filter((x) => x !== choiceId) : [...selectedChoiceIds, choiceId];
263
- changed();
264
- },
265
- clearFilters() { filters = {}; selectedChoiceIds = []; changed(); },
266
- retry() { attempt++; changed(); },
267
- async loadMore() {
268
- const key = selectionKey();
269
- if (pageKey !== key || !cursor || pendingMore) return;
270
- const request = { generation, key };
271
- pendingMore = request; // blocks repeated clicks before a re-render
272
- const isCurrent = () => generation === request.generation && selectionKey() === key;
273
- loadingMore = true; error = null; emit();
274
- try {
275
- const res = await searchCatalog({ limit: pageSize, cursor });
276
- if (isCurrent()) {
277
- const seen = new Set((products ?? []).map((p) => p.id));
278
- products = [...(products ?? []), ...res.products.filter((p) => (seen.has(p.id) ? false : (seen.add(p.id), true)))];
279
- cursor = res.nextCursor;
280
- }
281
- } catch (e) {
282
- if (isCurrent()) error = e instanceof Error ? e.message : "Couldn't load more products.";
283
- } finally {
284
- if (pendingMore === request) pendingMore = null;
285
- if (isCurrent()) { loadingMore = false; emit(); }
286
- }
287
- },
288
- };
289
- }
@@ -1,169 +0,0 @@
1
- // Storefront DTOs — the serializable shapes every hook, component, and page consumes.
2
- // These are plain JSON: safe to pass as Astro island props or across a server/client
3
- // boundary. Image values are already-resolved https URLs (never wix:image://), and every
4
- // displayable price is a ready formatted string.
5
-
6
- export type Availability = "IN_STOCK" | "OUT_OF_STOCK" | "PARTIALLY_OUT_OF_STOCK";
7
-
8
- /** A product as a listing/grid tile needs it. */
9
- export interface ProductSummary {
10
- id: string;
11
- slug: string;
12
- name: string;
13
- /**
14
- * The price the buyer pays for the cheapest variant, formatted (an automatic discount already
15
- * applied). When `price !== maxPrice` the product is a RANGE — render "price – maxPrice".
16
- */
17
- price: string;
18
- /** Highest variant price, formatted — differs from `price` when variants are priced differently. */
19
- maxPrice: string;
20
- /**
21
- * Struck "was" price, formatted; null when not on sale — and ALWAYS null for a range (a lone
22
- * struck minimum beside a range claims a saving that may not apply to the variant picked).
23
- */
24
- compareAtPrice: string | null;
25
- /** The primary merchant ribbon ("New", "Best Seller"); null when none. Same as ribbons[0]. */
26
- ribbon: string | null;
27
- /** EVERY merchant ribbon, primary first ("New", "Sale") — render all of them, one shared style. */
28
- ribbons: string[];
29
- /** The cheapest variant's id — what a direct add sends for a product with no options; null when unknown. */
30
- minPriceVariantId: string | null;
31
- availability: Availability;
32
- /** OUT_OF_STOCK but pre-orderable — label "Pre-order", not "Sold out". */
33
- preorder: boolean;
34
- /** Resolved https URL of the main image ("" when the product has none). */
35
- imageUrl: string;
36
- /** Resolved https URL of the second gallery image ("" when there is only one). */
37
- hoverImageUrl: string;
38
- /** e.g. "2 colors · 3 sizes"; "" for a single-variant product. */
39
- optionsSummary: string;
40
- /**
41
- * Hex colors of a color option's visible choices, catalog order — render as small dots on the
42
- * tile (a preview, not a picker: selection happens in QuickAdd or on the PDP). [] when none.
43
- */
44
- swatches: string[];
45
- /** True when the product can be added to the cart with no choices (single variant, in stock). */
46
- quickAddable: boolean;
47
- }
48
-
49
- export interface OptionChoice {
50
- choiceId: string;
51
- name: string;
52
- /** Hex color for swatch rendering; null for text choices. */
53
- colorCode: string | null;
54
- inStock: boolean;
55
- }
56
-
57
- export interface ProductOption {
58
- id: string;
59
- name: string;
60
- /** Render choices as color swatches (true) or text pills (false). */
61
- isColor: boolean;
62
- choices: OptionChoice[];
63
- }
64
-
65
- export interface ProductModifier {
66
- key: string;
67
- name: string;
68
- mandatory: boolean;
69
- /** "choices" renders pills; "text" renders a free-text input. */
70
- type: "choices" | "text";
71
- choices: { key: string; name: string }[];
72
- }
73
-
74
- export interface ProductVariant {
75
- variantId: string;
76
- /** The option selections this variant answers to: optionName -> choiceName. */
77
- choices: Record<string, string>;
78
- /** The price the buyer pays, formatted — an automatic discount beats the regular price. */
79
- price: string;
80
- /** Struck "was" price, formatted; null unless it is real and higher than `price`. */
81
- compareAtPrice: string | null;
82
- inStock: boolean;
83
- /** Out of stock but pre-orderable — still buyable (the add carries preOrderRequested). */
84
- preorderEnabled: boolean;
85
- /** This variant's own image (from its choice's linked media), resolved to an https URL; null when it has none. */
86
- imageUrl: string | null;
87
- }
88
-
89
- /** A product as the detail page needs it. */
90
- export interface ProductDetail extends ProductSummary {
91
- /** Product description as an HTML string — render with innerHTML, not as text. */
92
- descriptionHtml: string;
93
- /** Merchant info sections (materials, shipping, care…) — title + HTML; render as sections or accordions. */
94
- infoSections: { title: string; html: string }[];
95
- /** Every gallery image as a resolved https URL, main image first, de-duplicated. */
96
- gallery: string[];
97
- options: ProductOption[];
98
- modifiers: ProductModifier[];
99
- variants: ProductVariant[];
100
- }
101
-
102
- export interface Category {
103
- id: string;
104
- slug: string;
105
- name: string;
106
- /** Plain-text description when the merchant wrote one; "" otherwise. */
107
- description: string;
108
- }
109
-
110
- export interface FacetChoice {
111
- /** The option choice id — what searchCatalog({ choiceIds }) filters on. */
112
- id: string;
113
- name: string;
114
- /** Hex color for a swatch facet; null for a text facet. */
115
- colorCode: string | null;
116
- }
117
-
118
- /** One filterable option across the catalog (or a category): "Color" with its choices. */
119
- export interface Facet {
120
- name: string;
121
- isColor: boolean;
122
- choices: FacetChoice[];
123
- }
124
-
125
- /** The catalog's (or category's) lowest and highest product price, as numbers in site currency — the slider's bounds. */
126
- export interface PriceRange {
127
- min: number;
128
- max: number;
129
- currency: string;
130
- }
131
-
132
- /** What the filter panel needs beyond the product page: the facets and the price bounds of the scope. */
133
- export interface FacetData {
134
- facets: Facet[];
135
- priceRange: PriceRange | null;
136
- }
137
-
138
- export interface CartLine {
139
- /** The cart line id — what update/remove take (NOT the product id). */
140
- lineItemId: string;
141
- productName: string;
142
- quantity: number;
143
- /** Per-unit price, formatted. */
144
- unitPrice: string;
145
- /** Line total, formatted. */
146
- linePrice: string;
147
- /** Resolved https URL ("" when none). */
148
- imageUrl: string;
149
- /** Human-readable option/modifier labels, e.g. ["Color: Ink", "Size: M"]. */
150
- descriptionLines: string[];
151
- /** Not IN_STOCK → the line can't be checked out as-is. */
152
- status: string;
153
- /**
154
- * The recurring plan's terms for a subscription line — "Monthly plan · every month · 12 payments";
155
- * "" for a one-time purchase. A subscription line must read as one in the cart.
156
- */
157
- subscription: string;
158
- }
159
-
160
- export interface Cart {
161
- lines: CartLine[];
162
- /** Sum of line quantities. */
163
- itemCount: number;
164
- /** Formatted subtotal (after discounts) — from the cart estimate, not hand-summed. */
165
- subtotal: string;
166
- /** Formatted CART-level discount (a coupon or cart rule) — "" when none; item discounts are already in subtotal. */
167
- discount: string;
168
- currency: string;
169
- }
@@ -1,65 +0,0 @@
1
- ---
2
- // The site chrome for every storefront page — THIS file (header/footer/nav) plus the @theme
3
- // token block in src/styles/global.css are what you brand. Keep:
4
- // - the <slot name="seo-tags" /> in <head> (the product page's owner-editable SEO lands there,
5
- // including the <title> — which is why ours is printed only when the slot is empty)
6
- // - the global.css import (Tailwind + the design tokens every shipped component reads)
7
- // - one <CartButton> in the header and one <CartDrawer> per page (both client:only —
8
- // they read browser cart state and must not server-render)
9
- // - category links in the nav (or your own menu/footer) — every category page reachable by
10
- // a real link (`/category/<slug>`), from the live tree, so a category the owner adds later
11
- // shows up with no code change
12
- import CartButton from "../components/storefront/CartButton";
13
- import CartDrawer from "../components/storefront/CartDrawer";
14
- import { fetchCategories } from "../wix/storefront/catalog";
15
- import type { Category } from "../wix/storefront/types";
16
- import "../styles/global.css";
17
-
18
- interface Props {
19
- title: string;
20
- description?: string;
21
- }
22
- const { title, description } = Astro.props;
23
-
24
- // Non-fatal: the chrome renders without the links if the read fails. Six in the header keeps a
25
- // large tree from crowding it — put the rest in a menu or the footer, but keep them linked.
26
- let navCategories: Category[] = [];
27
- try {
28
- navCategories = (await fetchCategories()).slice(0, 6);
29
- } catch {
30
- /* the shop link still reaches everything */
31
- }
32
- ---
33
-
34
- <!doctype html>
35
- <html lang="en">
36
- <head>
37
- <meta charset="UTF-8" />
38
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
39
- {/* The product page's <SEO.Tags> renders the <title>; print ours only when no page filled the slot — two titles otherwise. */}
40
- {!Astro.slots.has("seo-tags") && <title>{title}</title>}
41
- {description && <meta name="description" content={description} />}
42
- <slot name="seo-tags" />
43
- </head>
44
- <body>
45
- <header class="sticky top-0 z-40 border-b border-border bg-background/80 backdrop-blur">
46
- <div class="mx-auto flex h-16 max-w-6xl items-center justify-between px-6">
47
- <a href="/" class="text-base font-bold tracking-tight text-foreground no-underline">Brand Name</a>
48
- <nav class="flex items-center gap-6 text-sm">
49
- <a href="/shop" class="text-foreground no-underline transition-colors hover:text-muted-foreground">Shop</a>
50
- {navCategories.map((c) => (
51
- <a href={`/category/${c.slug}`} class="hidden text-foreground no-underline transition-colors hover:text-muted-foreground md:inline">{c.name}</a>
52
- ))}
53
- <CartButton client:only="react" />
54
- </nav>
55
- </div>
56
- </header>
57
- <main class="mx-auto max-w-6xl px-6 pb-24 pt-10">
58
- <slot />
59
- </main>
60
- <footer class="border-t border-border px-6 py-10 text-center text-sm text-muted-foreground">
61
- © Brand Name
62
- </footer>
63
- <CartDrawer client:only="react" />
64
- </body>
65
- </html>