@wix/agent-skills 1.15.1 → 1.16.1

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 (332) hide show
  1. package/README.md +3 -7
  2. package/package.json +1 -1
  3. package/skills/wix-app/SKILL.md +4 -1
  4. package/skills/wix-app/references/APP_TOOLS.md +134 -0
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +1 -1
  6. package/skills/wix-app/references/DASHBOARD_PAGE.md +0 -10
  7. package/skills/wix-app/references/DATA_COLLECTION.md +1 -1
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +42 -8
  9. package/skills/wix-app/references/SERVICE_PLUGIN.md +12 -10
  10. package/skills/wix-app/references/app-tools/TOOLS.md +75 -0
  11. package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +2 -2
  12. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +172 -0
  13. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +143 -0
  14. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +23 -2
  15. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +29 -0
  16. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +1 -1
  17. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +60 -0
  18. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +27 -2
  19. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +5 -3
  20. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +24 -7
  21. package/skills/wix-app/references/editor-react-component/PARTS.md +15 -2
  22. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +2 -3
  23. package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +187 -0
  24. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +13 -9
  25. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +4 -0
  26. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
  27. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +3 -1
  28. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +4 -0
  29. package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +54 -0
  30. package/skills/wix-app/references/stores/QUERY.md +32 -0
  31. package/skills/wix-app/scripts/scan-a11y-code.cjs +777 -0
  32. package/skills/wix-app/scripts/scan-a11y-eslint.cjs +201 -0
  33. package/skills/wix-docs/SKILL.md +35 -3
  34. package/skills/wix-headless/SKILL.md +3 -1
  35. package/skills/wix-headless/references/CAPABILITIES.md +16 -3
  36. package/skills/wix-headless/references/CONTENT.md +36 -0
  37. package/skills/wix-headless/references/DESIGN.md +54 -0
  38. package/skills/wix-headless/references/DISCOVERY.md +24 -0
  39. package/skills/wix-headless/references/IMAGE_GENERATION.md +10 -0
  40. package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
  41. package/skills/wix-headless/references/SEED.md +1 -1
  42. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +3 -2
  43. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +560 -102
  44. package/skills/wix-headless/references/inline-recipes/setup-forms.md +210 -143
  45. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +32 -23
  46. package/skills/wix-headless/references/managed/CONNECT.md +1 -1
  47. package/skills/wix-headless/references/managed/CREATE.md +14 -0
  48. package/skills/wix-headless/references/managed/DEPLOYMENT.md +25 -0
  49. package/skills/wix-manage/SKILL.md +130 -7
  50. package/skills/wix-manage/references/accessibility/scan-site-accessibility.md +98 -0
  51. package/skills/wix-manage/references/analytics/analytics-dashboard-navigation.md +40 -0
  52. package/skills/wix-manage/references/app-installation/app-installation-dashboard-navigation.md +28 -0
  53. package/skills/wix-manage/references/blog/blog-dashboard-navigation.md +56 -0
  54. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +31 -6
  55. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -1
  56. package/skills/wix-manage/references/bookings/bookings-dashboard-navigation.md +63 -0
  57. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +10 -1
  58. package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +44 -0
  59. package/skills/wix-manage/references/cms/cms-data-items-crud.md +31 -3
  60. package/skills/wix-manage/references/cms/cms-publishing-flow.md +287 -0
  61. package/skills/wix-manage/references/cms/cms-schema-management.md +27 -1
  62. package/skills/wix-manage/references/contacts/contacts-dashboard-navigation.md +46 -0
  63. package/skills/wix-manage/references/contacts/create-a-contact.md +82 -0
  64. package/skills/wix-manage/references/contacts/update-a-contact.md +119 -0
  65. package/skills/wix-manage/references/dashboard-navigation/dashboard-navigation.md +82 -0
  66. package/skills/wix-manage/references/dashboard-navigation/routes.json +1733 -0
  67. package/skills/wix-manage/references/domains/domains-dashboard-navigation.md +32 -0
  68. package/skills/wix-manage/references/ecommerce/ecom-pricing.md +4 -4
  69. package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
  70. package/skills/wix-manage/references/ecommerce/gift-cards/ecom-gift-cards-goal-sell-gift-cards.md +338 -0
  71. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md +42 -78
  72. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-bundle-and-save.md +1 -1
  73. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md +1 -1
  74. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md +1 -1
  75. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +90 -92
  76. package/skills/wix-manage/references/events/create-wix-event.md +176 -0
  77. package/skills/wix-manage/references/events/manage-wix-events.md +174 -0
  78. package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +44 -0
  79. package/skills/wix-manage/references/get-paid/get-paid-dashboard-navigation.md +52 -0
  80. package/skills/wix-manage/references/google-ads/billing-and-payment.md +80 -0
  81. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +212 -0
  82. package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +110 -0
  83. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +25 -0
  84. package/skills/wix-manage/references/google-ads/install-and-create-account.md +155 -0
  85. package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +63 -0
  86. package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +155 -0
  87. package/skills/wix-manage/references/marketing/marketing-dashboard-navigation.md +52 -0
  88. package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +99 -1
  89. package/skills/wix-manage/references/pricing-plans/pricing-plans-dashboard-navigation.md +45 -0
  90. package/skills/wix-manage/references/restaurants/restaurants-dashboard-navigation.md +68 -0
  91. package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +94 -125
  92. package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +48 -9
  93. package/skills/wix-manage/references/site-properties/site-properties-dashboard-navigation.md +31 -0
  94. package/skills/wix-manage/references/sites/create-headless-site.md +52 -0
  95. package/skills/wix-manage/references/sites/create-site-from-template.md +2 -25
  96. package/skills/wix-manage/references/sites/site-import.md +217 -192
  97. package/skills/wix-manage/references/sites/sites-dashboard-navigation.md +29 -0
  98. package/skills/wix-manage/references/stores/add-store-pages-to-site.md +17 -1
  99. package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +26 -8
  100. package/skills/wix-manage/references/stores/stores-dashboard-navigation.md +65 -0
  101. package/skills/wix-manage/references/stores/update-product-with-options.md +39 -7
  102. package/skills/wix-replatform/.publish-manifest.json +8 -0
  103. package/skills/wix-replatform/SKILL.md +693 -0
  104. package/skills/wix-replatform/lib/artifact-freshness.js +215 -0
  105. package/skills/wix-replatform/lib/completion-report.js +200 -0
  106. package/skills/wix-replatform/lib/config-env.js +59 -0
  107. package/skills/wix-replatform/lib/execution-manifest.js +185 -0
  108. package/skills/wix-replatform/lib/execution-state.js +173 -0
  109. package/skills/wix-replatform/lib/import-recovery.js +313 -0
  110. package/skills/wix-replatform/lib/local-state.js +642 -0
  111. package/skills/wix-replatform/lib/orchestration-preflight.js +143 -0
  112. package/skills/wix-replatform/lib/orchestration-router.js +122 -0
  113. package/skills/wix-replatform/lib/orchestration-state.js +455 -0
  114. package/skills/wix-replatform/lib/progress-log.js +224 -0
  115. package/skills/wix-replatform/lib/progress-log.sh +140 -0
  116. package/skills/wix-replatform/lib/url-preservation-state.js +391 -0
  117. package/skills/wix-replatform/resources/rp-discovery/SKILL.md +184 -0
  118. package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +529 -0
  119. package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +316 -0
  120. package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +64 -0
  121. package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +1114 -0
  122. package/skills/wix-replatform/resources/rp-mapper/SKILL.md +430 -0
  123. package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +217 -0
  124. package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +148 -0
  125. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +378 -0
  126. package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +183 -0
  127. package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +478 -0
  128. package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +136 -0
  129. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
  130. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +310 -0
  131. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +1081 -0
  132. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +618 -0
  133. package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +949 -0
  134. package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +196 -0
  135. package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +66 -0
  136. package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +60 -0
  137. package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +95 -0
  138. package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +82 -0
  139. package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +256 -0
  140. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +249 -0
  141. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +444 -0
  142. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +774 -0
  143. package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +71 -0
  144. package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +632 -0
  145. package/skills/wix-replatform/resources/rp-target-wix/SPEC-product-reviews-and-blog-authorship.md +330 -0
  146. package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +21 -0
  147. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +19 -0
  148. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +37 -0
  149. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +37 -0
  150. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +39 -0
  151. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +35 -0
  152. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +14 -0
  153. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +35 -0
  154. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +36 -0
  155. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +35 -0
  156. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +14 -0
  157. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +131 -0
  158. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +37 -0
  159. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +37 -0
  160. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +21 -0
  161. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +37 -0
  162. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +37 -0
  163. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +97 -0
  164. package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +528 -0
  165. package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +14 -0
  166. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +38 -0
  167. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +37 -0
  168. package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +13 -0
  169. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +37 -0
  170. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +53 -0
  171. package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +84 -0
  172. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +25 -0
  173. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +37 -0
  174. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +37 -0
  175. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +38 -0
  176. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +37 -0
  177. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +90 -0
  178. package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +64 -0
  179. package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +141 -0
  180. package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +384 -0
  181. package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +260 -0
  182. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +238 -0
  183. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +237 -0
  184. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +238 -0
  185. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +2219 -0
  186. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +31 -0
  187. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +100 -0
  188. package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +107 -0
  189. package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +344 -0
  190. package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +250 -0
  191. package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +1927 -0
  192. package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +83 -0
  193. package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +141 -0
  194. package/skills/wix-replatform/scripts/artifact-freshness.js +76 -0
  195. package/skills/wix-replatform/scripts/execution-manifest-validate.js +43 -0
  196. package/skills/wix-replatform/scripts/execution-state-prepare.js +128 -0
  197. package/skills/wix-replatform/scripts/orchestration-preflight.js +48 -0
  198. package/skills/wix-replatform/scripts/orchestration-route.js +46 -0
  199. package/skills/wix-replatform/scripts/orchestration-state.js +245 -0
  200. package/skills/wix-vibe-headless/SKILL.md +49 -25
  201. package/skills/wix-vibe-headless/install/deploy.cjs +156 -0
  202. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +34 -0
  203. package/skills/wix-vibe-headless/platforms/README.md +8 -4
  204. package/skills/wix-vibe-headless/platforms/base44.md +111 -101
  205. package/skills/wix-vibe-headless/platforms/generic.md +99 -64
  206. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +226 -119
  207. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +43 -0
  208. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +25 -0
  209. package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +15 -0
  210. package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +35 -0
  211. package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +38 -0
  212. package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +40 -0
  213. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +54 -0
  214. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +65 -0
  215. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +50 -0
  216. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +103 -0
  217. package/skills/wix-vibe-headless/references/blog/seed/seed-blog.js +270 -0
  218. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +256 -149
  219. package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +65 -0
  220. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +47 -0
  221. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +13 -0
  222. package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +126 -0
  223. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +108 -0
  224. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +58 -0
  225. package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +95 -0
  226. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +94 -0
  227. package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +89 -0
  228. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-checkout.js → app/rest/wix-bookings-checkout.js} +1 -1
  229. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-services.js → app/rest/wix-bookings-services.js} +87 -11
  230. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +117 -0
  231. package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.js +333 -0
  232. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +168 -147
  233. package/skills/wix-vibe-headless/references/cms/app/collection.config.js +31 -0
  234. package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +18 -0
  235. package/skills/wix-vibe-headless/references/cms/{wix-cms.js → app/rest/wix-cms.js} +47 -2
  236. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +145 -0
  237. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +223 -131
  238. package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +23 -0
  239. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +43 -0
  240. package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +13 -0
  241. package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +29 -0
  242. package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +57 -0
  243. package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +78 -0
  244. package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +27 -0
  245. package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +54 -0
  246. package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +40 -0
  247. package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +81 -0
  248. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +48 -0
  249. package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +36 -0
  250. package/skills/wix-vibe-headless/references/events/{wix-events-browse.js → app/rest/wix-events-browse.js} +1 -1
  251. package/skills/wix-vibe-headless/references/events/seed/SEED.md +107 -0
  252. package/skills/wix-vibe-headless/references/events/seed/seed-events.js +251 -0
  253. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +272 -188
  254. package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +101 -0
  255. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +33 -0
  256. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +21 -0
  257. package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +29 -0
  258. package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +54 -0
  259. package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +77 -0
  260. package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +36 -0
  261. package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +32 -0
  262. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +35 -0
  263. package/skills/wix-vibe-headless/references/members/{wix-members-auth.js → app/rest/wix-members-auth.js} +6 -3
  264. package/skills/wix-vibe-headless/references/members/install/Register.jsx +22 -0
  265. package/skills/wix-vibe-headless/references/members/seed/SEED.md +22 -0
  266. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +229 -104
  267. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +31 -0
  268. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +15 -0
  269. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +39 -0
  270. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +15 -0
  271. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +29 -0
  272. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +35 -0
  273. package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +27 -0
  274. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +25 -0
  275. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +39 -0
  276. package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +27 -0
  277. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +60 -0
  278. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +94 -0
  279. package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js +236 -0
  280. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +236 -117
  281. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +35 -0
  282. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +48 -0
  283. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +16 -0
  284. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +35 -0
  285. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +25 -0
  286. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +28 -0
  287. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +30 -0
  288. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +30 -0
  289. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +53 -0
  290. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +28 -0
  291. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +86 -0
  292. package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.js +251 -0
  293. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +244 -124
  294. package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +81 -0
  295. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +71 -0
  296. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +43 -0
  297. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +21 -0
  298. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +60 -0
  299. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +63 -0
  300. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +32 -0
  301. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +73 -0
  302. package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +28 -0
  303. package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +102 -0
  304. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +180 -0
  305. package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.js +452 -0
  306. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +56 -0
  307. package/skills/wix-vibe-headless/references/shared/{wix-client.js → app/rest/wix-client.js} +6 -8
  308. package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +8 -0
  309. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +259 -157
  310. package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +20 -0
  311. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +150 -0
  312. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +167 -0
  313. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +51 -0
  314. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +54 -0
  315. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +119 -0
  316. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +71 -0
  317. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +109 -0
  318. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +98 -0
  319. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +27 -0
  320. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +139 -0
  321. package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +75 -0
  322. package/skills/wix-vibe-headless/references/storefront/{wix-store-cart.js → app/rest/wix-store-cart.js} +1 -1
  323. package/skills/wix-vibe-headless/references/storefront/{wix-store-catalog.js → app/rest/wix-store-catalog.js} +20 -1
  324. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +111 -0
  325. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +338 -0
  326. /package/skills/wix-vibe-headless/references/blog/{wix-blog.js → app/rest/wix-blog.js} +0 -0
  327. /package/skills/wix-vibe-headless/references/events/{wix-events-registration.js → app/rest/wix-events-registration.js} +0 -0
  328. /package/skills/wix-vibe-headless/references/portfolio/{wix-portfolio.js → app/rest/wix-portfolio.js} +0 -0
  329. /package/skills/wix-vibe-headless/references/pricing-plans/{wix-pricing-plans.js → app/rest/wix-pricing-plans.js} +0 -0
  330. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-menu.js → app/rest/wix-restaurants-menu.js} +0 -0
  331. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-ordering.js → app/rest/wix-restaurants-ordering.js} +0 -0
  332. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-reservations.js → app/rest/wix-restaurants-reservations.js} +0 -0
@@ -0,0 +1,39 @@
1
+ // Collection page — collection header + its project grid (paged). Thin view over
2
+ // useCollectionProjects (all data logic lives in the hook). Styled with base44 design tokens (shadcn Tailwind classes).
3
+ import { useParams } from "react-router-dom";
4
+ import { useCollectionProjects } from "@/hooks/useCollectionProjects";
5
+ import ProjectGrid from "@/components/ProjectGrid";
6
+
7
+ export default function CollectionPage() {
8
+ const { slug } = useParams();
9
+ const { collection, notFound, projects, cursor, loadMore } = useCollectionProjects(slug, { limit: 24 });
10
+
11
+ if (notFound) return <Centered>Collection not found.</Centered>;
12
+ if (!collection) return <Centered>Loading…</Centered>;
13
+
14
+ return (
15
+ <main className="max-w-[1200px] mx-auto p-4">
16
+ <header className="mb-6">
17
+ <h1 className="font-display m-0 mb-2">{collection.title}</h1>
18
+ {collection.description && (
19
+ <p className="text-muted-foreground leading-relaxed m-0">{collection.description}</p>
20
+ )}
21
+ </header>
22
+ {projects === null
23
+ ? <p className="text-muted-foreground">Loading…</p>
24
+ : <ProjectGrid projects={projects} empty="No projects in this collection yet." />}
25
+ {cursor && (
26
+ <div className="flex justify-center mt-6">
27
+ <button onClick={loadMore}
28
+ className="px-6 py-2.5 cursor-pointer bg-primary text-primary-foreground border-none rounded-sm text-[15px] font-semibold">
29
+ Load more
30
+ </button>
31
+ </div>
32
+ )}
33
+ </main>
34
+ );
35
+ }
36
+
37
+ function Centered({ children }) {
38
+ return <div className="p-12 text-center text-muted-foreground">{children}</div>;
39
+ }
@@ -0,0 +1,27 @@
1
+ // Portfolio page — collections gallery (grid + empty state + paging). Thin view over
2
+ // usePortfolioGallery (all data logic lives in the hook). Styled with base44 design tokens (shadcn Tailwind classes).
3
+ import { usePortfolioGallery } from "@/hooks/usePortfolioGallery";
4
+ import CollectionGrid from "@/components/CollectionGrid";
5
+
6
+ export default function Portfolio() {
7
+ const { collections, total, cursor, loadMore } = usePortfolioGallery({ limit: 24 });
8
+
9
+ return (
10
+ <main className="max-w-[1200px] mx-auto p-4">
11
+ <h1 className="font-display mb-4">Work</h1>
12
+ {collections === null
13
+ ? <p className="text-muted-foreground">Loading…</p>
14
+ : <CollectionGrid
15
+ collections={collections}
16
+ empty={total === 0 ? "No collections yet — add them from your Wix dashboard." : "No collections to show."} />}
17
+ {cursor && (
18
+ <div className="flex justify-center mt-6">
19
+ <button onClick={loadMore}
20
+ className="px-6 py-2.5 cursor-pointer bg-primary text-primary-foreground border-none rounded-sm text-[15px] font-semibold">
21
+ Load more
22
+ </button>
23
+ </div>
24
+ )}
25
+ </main>
26
+ );
27
+ }
@@ -0,0 +1,60 @@
1
+ // Project detail — thin view over useProjectDetail (all data logic lives in the hook). Renders the
2
+ // header, the details[] rows (text OR link), and the media gallery (each item via ProjectMedia,
3
+ // which branches on item.type). Styled with base44 design tokens (shadcn Tailwind classes).
4
+ import { useParams } from "react-router-dom";
5
+ import { useProjectDetail } from "@/hooks/useProjectDetail";
6
+ import ProjectMedia from "@/components/ProjectMedia";
7
+
8
+ export default function ProjectDetail() {
9
+ const { slug } = useParams();
10
+ const { project, notFound, items } = useProjectDetail(slug);
11
+
12
+ if (notFound) return <Centered>Project not found.</Centered>;
13
+ if (!project) return <Centered>Loading…</Centered>;
14
+
15
+ const details = project.details || [];
16
+ return (
17
+ <main className="max-w-[1200px] mx-auto p-4">
18
+ <header className="mb-6">
19
+ <h1 className="font-display m-0 mb-2">{project.title}</h1>
20
+ {project.description && (
21
+ <p className="text-muted-foreground leading-relaxed m-0">{project.description}</p>
22
+ )}
23
+ </header>
24
+
25
+ {/* details[] row: { label, text? } OR { label, link: { text, url, target } } */}
26
+ {details.length > 0 && (
27
+ <dl className="grid [grid-template-columns:auto_1fr] gap-x-6 gap-y-2 m-0 mb-8 items-baseline">
28
+ {details.map((d, i) => (
29
+ <div key={i} className="contents">
30
+ <dt className="text-muted-foreground text-sm">{d.label}</dt>
31
+ <dd className="m-0">
32
+ {d.link
33
+ ? <a href={d.link.url} target={d.link.target} rel="noopener"
34
+ className="text-primary">{d.link.text}</a>
35
+ : d.text}
36
+ </dd>
37
+ </div>
38
+ ))}
39
+ </dl>
40
+ )}
41
+
42
+ <div className="flex flex-col gap-4">
43
+ {items.map((item) => (
44
+ <figure key={item.id} className="m-0">
45
+ {item.link
46
+ ? <a href={item.link.url} target={item.link.target} rel="noopener"><ProjectMedia item={item} /></a>
47
+ : <ProjectMedia item={item} />}
48
+ {item.title && (
49
+ <figcaption className="text-muted-foreground text-sm mt-1.5">{item.title}</figcaption>
50
+ )}
51
+ </figure>
52
+ ))}
53
+ </div>
54
+ </main>
55
+ );
56
+ }
57
+
58
+ function Centered({ children }) {
59
+ return <div className="p-12 text-center text-muted-foreground">{children}</div>;
60
+ }
@@ -0,0 +1,94 @@
1
+ # Portfolio — seeding
2
+
3
+ Seed a Wix Portfolio by **calling `seed-portfolio.js`** — don't hand-write the REST calls. It's
4
+ a build-time module (run via `exec_tool`, not shipped in the app) that abstracts every Wix
5
+ Portfolio seed operation. `require` it and call the functions with plain data.
6
+
7
+ **Collections before projects.** A project is assigned to collections by a `collectionIds` array
8
+ that Wix does **not** validate — a wrong id silently orphans the project. Create the collections
9
+ first, then thread their real ids into each project.
10
+
11
+ **Seeding is additive — never delete or overwrite existing content.** Don't clean up, don't remove
12
+ "sample" data, don't reset. Just add.
13
+
14
+ **DEFAULT — one call.** `setupPortfolio(ctx, plan)` runs the whole flow in the right order
15
+ (collections → projects → items → covers), threading ids in memory. Pass covers/items only when you have them. Drop to the individual functions below only for step-by-step control.
16
+
17
+ ```js
18
+ // build-time exec_tool
19
+ const { accessToken } = await base44.asServiceRole.connectors.getConnection("wix"); // Base44 (generic: use $TOKEN)
20
+ const fs = require("fs");
21
+ // exec_tool's require can return EMPTY exports for these build-time modules — load the file itself:
22
+ const seed = (() => { const m = { exports: {} };
23
+ new Function("module", "exports", "require", fs.readFileSync("/app/.agents/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js", "utf8"))(m, m.exports, require);
24
+ return m.exports; })();
25
+ const ctx = { token: accessToken, siteId: WIX_METASITE_ID };
26
+
27
+ const summary = await seed.setupPortfolio(ctx, {
28
+ collections: [
29
+ { title: "Brand Identity", description: "Logo systems and visual identities." },
30
+ ],
31
+ projects: [
32
+ { title: "Northwind Rebrand", description: "Full identity refresh for a logistics firm.",
33
+ collection: "Brand Identity", // resolved to that collection's id
34
+ details: [{ label: "Year", text: "2025" }],
35
+ // cover/items are optional and attached IN this one call. Pass plain urls — the module imports
36
+ // them to Wix Media for you (portfolio binds by file id). Use the FINAL https://media.base44.com/...
37
+ // url from the COMPLETED generate_image (it runs in the background while you build — wait for it),
38
+ // never a still-generating /__generating__/<id>.png placeholder.
39
+ coverImageUrl: "https://media.base44.com/…",
40
+ items: [{ sortOrder: 1, title: "Hero", imageUrl: "https://media.base44.com/…" }] },
41
+ ],
42
+ });
43
+ // summary => { collections:[{id,slug,revision}], projects:[{id,slug,revision}], itemsCreated, coversAttached }
44
+ ```
45
+
46
+ ## Escape hatch — individual functions
47
+ Reach for the functions below only when the one-call `setupPortfolio` doesn't fit (step-by-step
48
+ control, partial re-seed). `setupPortfolio` is built from them, in this order:
49
+
50
+ ```js
51
+ const collections = await seed.createCollections(ctx, [ // STEP 1
52
+ { title: "Brand Identity", description: "Logo systems and visual identities." },
53
+ ]);
54
+ const projects = await seed.createProjects(ctx, [ // STEP 2
55
+ { title: "Northwind Rebrand", description: "Full identity refresh for a logistics firm.",
56
+ collectionIds: [collections[0].id], details: [{ label: "Year", text: "2025" }] },
57
+ ]);
58
+
59
+ // optional — import each url to Wix Media first (portfolio binds by file id), then attach
60
+ const files = await Promise.all(imageUrls.map((u) => seed.importImage(ctx, u))); // → [{ id, url }]
61
+ await seed.attachProjectCovers(ctx, projects.map((p, i) => ({ id: p.id, revision: p.revision, imageId: files[i].id, height: 1024, width: 1024 })));
62
+ await seed.attachCollectionCovers(ctx, collections.map((c, i) => ({ id: c.id, revision: c.revision, imageId: files[i].id, height: 1024, width: 1024 })));
63
+ await seed.createProjectItems(ctx, [{ projectId: projects[0].id, sortOrder: 1, title: "Hero", imageId: files[0].id, height: 1024, width: 1024 }]);
64
+ ```
65
+
66
+ ## Functions
67
+ | fn | does |
68
+ |---|---|
69
+ | `setupPortfolio(ctx, plan)` | **DEFAULT** — one call: collections → projects → items → covers; returns `{collections,projects,itemsCreated,coversAttached}` |
70
+ | `createCollections(ctx, collections)` | STEP 1 — `[{title,description?,hidden?}]` → `[{id,slug,revision}]` |
71
+ | `createProjects(ctx, projects)` | STEP 2 — `[{title,description?,collectionIds,details?,hidden?}]` → `[{id,slug,revision}]` |
72
+ | `importImage(ctx, url)` | import an external url into Wix Media → `{id,url}` (file id + wixstatic url); covers + items bind by this file id |
73
+ | `attachProjectCovers(ctx, [{id,revision,imageId,height,width}])` | PATCH each project's cover (optional); `imageId` = a Wix Media file id from `importImage` |
74
+ | `attachCollectionCovers(ctx, [{id,revision,imageId,height,width}])` | PATCH each collection's cover (optional) |
75
+ | `createProjectItems(ctx, [{projectId,sortOrder,title,imageId,height,width}])` | one POST per gallery image (optional) |
76
+
77
+ `hidden` defaults to `false` (shown) — omit it for visible entities; send `hidden: true` only to
78
+ hide. `setupPortfolio` **installs the Wix Portfolio app first** (`installPortfolioApp`, idempotent), so seeding works even if the site doesn't have it yet.
79
+
80
+ ## Reference
81
+ If a call returns a shape you didn't expect, or you need an operation this module doesn't cover,
82
+ use the **`wix-docs`** skill to search + read the live Wix API reference — never guess. The
83
+ authoritative source recipe is `wix-headless/references/inline-recipes/setup-portfolio.md`.
84
+
85
+ **Transcribed from the recipe — NOT yet live-verified.** The endpoints/fields mirror
86
+ `setup-portfolio.md`; confirm against a real run or the Wix docs before trusting edge shapes.
87
+
88
+ Read a method's page before writing its call: it carries the exact body shape, the required
89
+ permission scope, and the response envelope.
90
+ - Install a Wix app onto the site: https://dev.wix.com/docs/api-reference/business-management/app-installation/app-installation/install-app.md
91
+ - Import an image into Wix Media: https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/import-file.md
92
+ - Create Collection: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/collections/create-collection.md
93
+ - Create Project: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/projects/create-project.md
94
+ - Create Project Item: https://dev.wix.com/docs/api-reference/business-solutions/portfolio/project-items/create-project-item.md
@@ -0,0 +1,236 @@
1
+ // Portfolio seed helpers — run at BUILD TIME via exec_tool (NOT shipped in the app).
2
+ // The agent requires this and calls the functions with plain data; all Wix Portfolio
3
+ // request/response mechanics (the collection/project wrappers, title-not-name, the
4
+ // hidden-defaults-to-false polarity, collections-before-projects, cover PATCH + gallery
5
+ // items) live here, once.
6
+ //
7
+ // Usage (build-time exec_tool):
8
+ // const { accessToken } = await base44.asServiceRole.connectors.getConnection("wix"); // Base44
9
+ // const seed = require("/app/.agents/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js");
10
+ // const ctx = { token: accessToken, siteId: WIX_METASITE_ID };
11
+ //
12
+ // const collections = await seed.createCollections(ctx, [{ title, description }]); // STEP 1
13
+ // const projects = await seed.createProjects(ctx, [ // STEP 2
14
+ // { title, description, collectionIds: [collections[0].id], details: [{ label, text }] },
15
+ // ]);
16
+ // // optional — import each image url to Wix Media first (portfolio binds by file id), then attach.
17
+ // const files = await Promise.all(imageUrls.map((u) => seed.importImage(ctx, u))); // → [{ id, url }]
18
+ // await seed.attachProjectCovers(ctx, projects.map((p,i) => ({ id:p.id, revision:p.revision, imageId:files[i].id, height:1024, width:1024 })));
19
+ // await seed.createProjectItems(ctx, [{ projectId: projects[0].id, sortOrder: 1, title, imageId: files[0].id, height:1024, width:1024 }]);
20
+ //
21
+ // **NOT yet live-verified — transcribed from setup-portfolio.md.** If any call fails with a
22
+ // shape the caller didn't expect, fall back to the wix-docs skill (search + read the live Wix
23
+ // API reference) — never guess. Source recipe (authoritative):
24
+ // wix-headless/references/inline-recipes/setup-portfolio.md.
25
+
26
+ const API = "https://www.wixapis.com";
27
+ const PORTFOLIO_APP_ID = "d90652a2-f5a1-4c7c-84c4-d4cdcc41f130"; // installPortfolioApp installs this before seeding
28
+
29
+ async function req(ctx, path, { method = "POST", body } = {}) {
30
+ const res = await fetch(API + path, {
31
+ method,
32
+ headers: {
33
+ Authorization: `Bearer ${ctx.token}`,
34
+ "wix-site-id": ctx.siteId,
35
+ "Content-Type": "application/json",
36
+ },
37
+ body: body ? JSON.stringify(body) : undefined,
38
+ });
39
+ const json = await res.json().catch(() => ({}));
40
+ if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
41
+ return json;
42
+ }
43
+
44
+ // ---- exported operations ----
45
+
46
+ // Read-only listing helpers.
47
+ async function listProjects(ctx) {
48
+ const r = await req(ctx, "/portfolio/v1/projects", { method: "GET" });
49
+ return (r.projects ?? []).map((p) => ({ id: p.id, title: p.title }));
50
+ }
51
+ async function listCollections(ctx) {
52
+ const r = await req(ctx, "/portfolio/v1/collections", { method: "GET" });
53
+ return (r.collections ?? []).map((c) => ({ id: c.id, title: c.title }));
54
+ }
55
+
56
+ /**
57
+ * STEP 1 — Create the collections. MUST run before createProjects: a project's collectionIds
58
+ * are NOT validated, so projects need the real collection ids read back from here.
59
+ * @param collections [{ title, description?, hidden? }] (display name is `title`, not `name`;
60
+ * `slug` auto-generates from title when omitted; `hidden` defaults to false = shown, so omit
61
+ * it for a visible collection and send `hidden: true` only to hide.)
62
+ * No bulk-create — one call per collection; concurrent is safe (no 409 race) but sequential
63
+ * is just as correct and simplest.
64
+ * @returns [{ id, slug, revision }] (id feeds each project's collectionIds; revision feeds covers)
65
+ */
66
+ async function createCollections(ctx, collections) {
67
+ const out = [];
68
+ for (const c of collections) {
69
+ const body = { collection: { title: c.title, description: c.description } };
70
+ if (c.hidden) body.collection.hidden = true; // omit otherwise — defaults to shown
71
+ const r = await req(ctx, "/portfolio/v1/collections", { body });
72
+ out.push({ id: r.collection?.id, slug: r.collection?.slug, revision: r.collection?.revision });
73
+ }
74
+ return out;
75
+ }
76
+
77
+ /**
78
+ * STEP 2 — Create the projects, each assigned to its collection(s) via collectionIds.
79
+ * @param projects [{ title, description?, collectionIds: [id], details?, hidden? }]
80
+ * collectionIds MUST hold real ids from createCollections — they are NOT validated, so a
81
+ * wrong/missing id is accepted silently and orphans the project (reachable only from the
82
+ * all-projects list). `details` is an optional [{ label, text }] array (Role, Year, Client…).
83
+ * `hidden` defaults to false = shown. No bulk-create — one call per project; concurrent safe.
84
+ * @returns [{ id, slug, revision }] (revision feeds attachProjectCovers)
85
+ */
86
+ async function createProjects(ctx, projects) {
87
+ const out = [];
88
+ for (const p of projects) {
89
+ const project = {
90
+ title: p.title,
91
+ description: p.description,
92
+ collectionIds: p.collectionIds ?? [],
93
+ };
94
+ if (p.details) project.details = p.details;
95
+ if (p.hidden) project.hidden = true; // omit otherwise — defaults to shown
96
+ const r = await req(ctx, "/portfolio/v1/projects", { body: { project } });
97
+ out.push({ id: r.project?.id, slug: r.project?.slug, revision: r.project?.revision });
98
+ }
99
+ return out;
100
+ }
101
+
102
+ // Import an external image URL into Wix Media → { id, url }. Portfolio binds covers + gallery items
103
+ // by the Wix Media file **id**, NOT a url — an external url (e.g. a base44 generate_image result)
104
+ // MUST be imported first; the raw url renders nothing. id = wixstatic file id, url = wixstatic url.
105
+ async function importImage(ctx, url, displayName = "image.png") {
106
+ const r = await req(ctx, "/site-media/v1/files/import", { body: { url, mimeType: "image/png", displayName } });
107
+ const f = r.file || r;
108
+ if (!f?.id) throw new Error(`import-file returned no file id: ${JSON.stringify(r).slice(0, 200)}`);
109
+ return { id: f.id, url: f.url };
110
+ }
111
+
112
+ // Optional — pass a cover/items to attach, omit to skip. Cover = the listing-card thumbnail. PATCH per entity,
113
+ // echoing the current revision (a missing/stale revision fails). height + width are required
114
+ // alongside the imported WixMedia image id (from importImage). items: [{ id, revision, imageId, height, width }].
115
+ async function attachProjectCovers(ctx, items) {
116
+ for (const it of items) {
117
+ await req(ctx, `/portfolio/v1/projects/${it.id}`, {
118
+ method: "PATCH",
119
+ body: { project: { id: it.id, revision: it.revision, coverImage: { imageInfo: { id: it.imageId, height: it.height, width: it.width } } } },
120
+ });
121
+ }
122
+ }
123
+ async function attachCollectionCovers(ctx, items) {
124
+ for (const it of items) {
125
+ await req(ctx, `/portfolio/v1/collections/${it.id}`, {
126
+ method: "PATCH",
127
+ body: { collection: { id: it.id, revision: it.revision, coverImage: { imageInfo: { id: it.imageId, height: it.height, width: it.width } } } },
128
+ });
129
+ }
130
+ }
131
+
132
+ // Optional — the project's media gallery (detail-page images) is a SEPARATE `item` entity,
133
+ // one POST per image. sortOrder (1,2,3…) sets render order. lowercase `items` — `/Items` 404s.
134
+ // There is NO public list endpoint. items: [{ projectId, sortOrder, title, imageId, height, width }].
135
+ async function createProjectItems(ctx, items) {
136
+ const out = [];
137
+ for (const it of items) {
138
+ const r = await req(ctx, "/portfolio/v1/items", {
139
+ body: { item: { projectId: it.projectId, sortOrder: it.sortOrder, title: it.title, image: { imageInfo: { id: it.imageId, height: it.height, width: it.width } } } },
140
+ });
141
+ out.push({ id: r.item?.id });
142
+ }
143
+ return out;
144
+ }
145
+
146
+ /**
147
+ * DEFAULT one-call path — seed a whole portfolio from one plan; ids stay in memory so
148
+ * collections→projects→items→covers are wired without hand-threading ids. Order matches SEED.md:
149
+ * createCollections → createProjects (into collections) → createProjectItems → attach*Covers.
150
+ * @param plan {
151
+ * collections: [{ title, description?, hidden?, coverImageUrl? }],
152
+ * projects: [{ title, description?, details?, hidden?,
153
+ * collection?: "<collection title>", // resolved to that collection's id
154
+ * items?: [{ sortOrder, title, imageUrl }],
155
+ * coverImageUrl? }],
156
+ * }
157
+ * coverImageUrl / items[].imageUrl are plain image urls — imported to Wix Media here. Covers/items
158
+ * are optional — a project/collection without one skips it.
159
+ * @returns { collections:[{id,slug,revision}], projects:[{id,slug,revision}], itemsCreated, coversAttached }
160
+ */
161
+ // Install the Wix Portfolio app before seeding — base44 sites aren't guaranteed to have it (no
162
+ // separate Setup step here, unlike the wix-headless recipe). Idempotent: re-installing returns 200.
163
+ async function installPortfolioApp(ctx) {
164
+ return req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
165
+ tenant: { tenantType: "SITE", id: ctx.siteId },
166
+ appInstance: { appDefId: PORTFOLIO_APP_ID, enabled: true },
167
+ } });
168
+ }
169
+
170
+ async function setupPortfolio(ctx, { collections = [], projects = [] } = {}) {
171
+ await installPortfolioApp(ctx);
172
+ const cols = await createCollections(ctx, collections); // STEP 1
173
+ const idByName = new Map(collections.map((c, i) => [c.title, cols[i].id]));
174
+
175
+ const projs = await createProjects( // STEP 2
176
+ ctx,
177
+ projects.map((p) => ({
178
+ title: p.title, description: p.description, details: p.details, hidden: p.hidden,
179
+ collectionIds: p.collection ? [idByName.get(p.collection)].filter(Boolean) : [],
180
+ })),
181
+ );
182
+
183
+ // resolve a plain image url → { imageId, height, width } by importing to Wix Media (binds by file id)
184
+ const toImage = async (url, name) => {
185
+ const file = await importImage(ctx, url, name);
186
+ return { imageId: file.id, height: 1024, width: 1024 };
187
+ };
188
+
189
+ // STEP 3 — project media-gallery items (import each image; a failed import skips that item)
190
+ const itemsFlat = [];
191
+ for (let i = 0; i < projects.length; i++) {
192
+ for (const it of projects[i].items ?? []) {
193
+ if (!it.imageUrl) continue;
194
+ try {
195
+ const img = await toImage(it.imageUrl, `${it.title || "item"}.png`);
196
+ itemsFlat.push({ projectId: projs[i].id, sortOrder: it.sortOrder, title: it.title, ...img });
197
+ } catch { /* skip this item's image */ }
198
+ }
199
+ }
200
+ const items = itemsFlat.length ? await createProjectItems(ctx, itemsFlat) : [];
201
+
202
+ // STEP 4 — covers (import each; a failed import skips that cover)
203
+ const projCovers = [];
204
+ for (let i = 0; i < projects.length; i++) {
205
+ if (!projects[i].coverImageUrl) continue;
206
+ try {
207
+ const img = await toImage(projects[i].coverImageUrl, `${projects[i].title || "project"}-cover.png`);
208
+ projCovers.push({ id: projs[i].id, revision: projs[i].revision, ...img });
209
+ } catch { /* skip */ }
210
+ }
211
+ if (projCovers.length) await attachProjectCovers(ctx, projCovers);
212
+
213
+ const colCovers = [];
214
+ for (let i = 0; i < collections.length; i++) {
215
+ if (!collections[i].coverImageUrl) continue;
216
+ try {
217
+ const img = await toImage(collections[i].coverImageUrl, `${collections[i].title || "collection"}-cover.png`);
218
+ colCovers.push({ id: cols[i].id, revision: cols[i].revision, ...img });
219
+ } catch { /* skip */ }
220
+ }
221
+ if (colCovers.length) await attachCollectionCovers(ctx, colCovers);
222
+
223
+ return {
224
+ collections: cols,
225
+ projects: projs,
226
+ itemsCreated: items.length,
227
+ coversAttached: projCovers.length + colCovers.length,
228
+ };
229
+ }
230
+
231
+ module.exports = {
232
+ setupPortfolio, installPortfolioApp,
233
+ listProjects, listCollections,
234
+ createCollections, createProjects, importImage,
235
+ attachProjectCovers, attachCollectionCovers, createProjectItems,
236
+ };