@wix/agent-skills 1.0.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 (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/package.json +29 -0
  4. package/skills/wix-app/SKILL.md +344 -0
  5. package/skills/wix-app/references/APP_IDENTIFIERS.md +35 -0
  6. package/skills/wix-app/references/APP_MARKET_REVIEW.md +311 -0
  7. package/skills/wix-app/references/APP_VALIDATION.md +171 -0
  8. package/skills/wix-app/references/BACKEND_API.md +233 -0
  9. package/skills/wix-app/references/BACKEND_EVENT.md +116 -0
  10. package/skills/wix-app/references/CODE_QUALITY.md +33 -0
  11. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +587 -0
  12. package/skills/wix-app/references/DASHBOARD_MENU_PLUGIN.md +157 -0
  13. package/skills/wix-app/references/DASHBOARD_MODAL.md +283 -0
  14. package/skills/wix-app/references/DASHBOARD_PAGE.md +403 -0
  15. package/skills/wix-app/references/DASHBOARD_PLUGIN.md +205 -0
  16. package/skills/wix-app/references/DATA_COLLECTION.md +451 -0
  17. package/skills/wix-app/references/DOCUMENTATION.md +42 -0
  18. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +65 -0
  19. package/skills/wix-app/references/EMBEDDED_SCRIPT.md +468 -0
  20. package/skills/wix-app/references/EXTENSION_REGISTRATION.md +96 -0
  21. package/skills/wix-app/references/SERVICE_PLUGIN.md +235 -0
  22. package/skills/wix-app/references/SITE_PLUGIN.md +436 -0
  23. package/skills/wix-app/references/STORES_VERSIONING.md +334 -0
  24. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +84 -0
  25. package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +345 -0
  26. package/skills/wix-app/references/dashboard-menu-plugin/blog-slots.md +71 -0
  27. package/skills/wix-app/references/dashboard-menu-plugin/bookings-slots.md +58 -0
  28. package/skills/wix-app/references/dashboard-menu-plugin/crm-slots.md +8 -0
  29. package/skills/wix-app/references/dashboard-menu-plugin/ecommerce-slots.md +17 -0
  30. package/skills/wix-app/references/dashboard-menu-plugin/events-slots.md +29 -0
  31. package/skills/wix-app/references/dashboard-menu-plugin/restaurants-slots.md +27 -0
  32. package/skills/wix-app/references/dashboard-menu-plugin/stores-slots.md +35 -0
  33. package/skills/wix-app/references/dashboard-page/API_SPEC.md +138 -0
  34. package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +573 -0
  35. package/skills/wix-app/references/dashboard-page/DYNAMIC_PARAMETERS.md +269 -0
  36. package/skills/wix-app/references/dashboard-page/ECOM_NAVIGATION.md +164 -0
  37. package/skills/wix-app/references/dashboard-plugin/SLOTS.md +294 -0
  38. package/skills/wix-app/references/data-collection/WIX_DATA.md +270 -0
  39. package/skills/wix-app/references/data-collection/extension-template.ts +107 -0
  40. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +138 -0
  41. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +454 -0
  42. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +165 -0
  43. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +576 -0
  44. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +170 -0
  45. package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +6 -0
  46. package/skills/wix-app/references/editor-react-component/PARTS.md +25 -0
  47. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +203 -0
  48. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +167 -0
  49. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +137 -0
  50. package/skills/wix-app/references/service-plugin/ADDITIONAL-FEES.md +112 -0
  51. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +118 -0
  52. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +87 -0
  53. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +86 -0
  54. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +135 -0
  55. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +79 -0
  56. package/skills/wix-app/references/service-plugin/VALIDATIONS.md +68 -0
  57. package/skills/wix-app/references/site-plugin/EXAMPLES.md +311 -0
  58. package/skills/wix-app/references/site-plugin/SLOTS.md +263 -0
  59. package/skills/wix-design-system/SKILL.md +129 -0
  60. package/skills/wix-design-system/references/file-structure.md +56 -0
  61. package/skills/wix-design-system/scripts/wds.cjs +531 -0
  62. package/skills/wix-headless/SKILL.md +418 -0
  63. package/skills/wix-headless/references/DISCOVERY.md +332 -0
  64. package/skills/wix-headless/references/ORCHESTRATION.md +269 -0
  65. package/skills/wix-headless/references/SETUP.md +154 -0
  66. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +152 -0
  67. package/skills/wix-headless/references/blog/BLOG_PAGES.md +299 -0
  68. package/skills/wix-headless/references/blog/BLOG_SETUP.md +218 -0
  69. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +32 -0
  70. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +373 -0
  71. package/skills/wix-headless/references/cms/FAQ_KNOWLEDGE_BASE.md +229 -0
  72. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +40 -0
  73. package/skills/wix-headless/references/cms/PORTFOLIO.md +454 -0
  74. package/skills/wix-headless/references/cms/RESOURCE_LIBRARY.md +356 -0
  75. package/skills/wix-headless/references/cms/TEAM_DIRECTORY.md +299 -0
  76. package/skills/wix-headless/references/commands/install-app.md +42 -0
  77. package/skills/wix-headless/references/commands/known-apps.json +5 -0
  78. package/skills/wix-headless/references/commands/mcp-bootstrap.md +28 -0
  79. package/skills/wix-headless/references/designer/INSTRUCTIONS.md +828 -0
  80. package/skills/wix-headless/references/ecom/CART_PAGES.md +120 -0
  81. package/skills/wix-headless/references/ecom/CART_WIRING.md +103 -0
  82. package/skills/wix-headless/references/ecom/COMPONENTS_CSS.md +132 -0
  83. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +59 -0
  84. package/skills/wix-headless/references/forms/CONTACT_FORM.md +477 -0
  85. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +43 -0
  86. package/skills/wix-headless/references/gift-cards/COMPONENTS.md +119 -0
  87. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +51 -0
  88. package/skills/wix-headless/references/gift-cards/PAGES.md +129 -0
  89. package/skills/wix-headless/references/images/INSTRUCTIONS.md +359 -0
  90. package/skills/wix-headless/references/shared/BUILD_NOISE.md +8 -0
  91. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +185 -0
  92. package/skills/wix-headless/references/shared/IMPLEMENTER.md +155 -0
  93. package/skills/wix-headless/references/shared/MCP_PREFIX.md +105 -0
  94. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +97 -0
  95. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +423 -0
  96. package/skills/wix-headless/references/shared/STYLING.md +117 -0
  97. package/skills/wix-headless/references/stores/BACK_IN_STOCK.md +178 -0
  98. package/skills/wix-headless/references/stores/CATEGORY_PAGES.md +86 -0
  99. package/skills/wix-headless/references/stores/COMPONENTS_CSS.md +129 -0
  100. package/skills/wix-headless/references/stores/HOME_AND_NAV.md +227 -0
  101. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +96 -0
  102. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +249 -0
  103. package/skills/wix-headless/references/stores/PRODUCT_PAGES.md +213 -0
  104. package/skills/wix-headless/references/stores/SHARED_WIRING.md +164 -0
  105. package/skills/wix-headless/references/verticals/_schema.json +160 -0
  106. package/skills/wix-headless/references/verticals/_schema.md +185 -0
  107. package/skills/wix-headless/references/verticals/blog.md +125 -0
  108. package/skills/wix-headless/references/verticals/cms.md +121 -0
  109. package/skills/wix-headless/references/verticals/ecom.md +96 -0
  110. package/skills/wix-headless/references/verticals/forms.md +106 -0
  111. package/skills/wix-headless/references/verticals/gift-cards.md +121 -0
  112. package/skills/wix-headless/references/verticals/stores.md +167 -0
  113. package/skills/wix-headless/scripts/check-manifest.mjs +198 -0
  114. package/skills/wix-headless/scripts/copy-utility-templates.mjs +153 -0
  115. package/skills/wix-headless/scripts/emit-design-tokens.mjs +77 -0
  116. package/skills/wix-headless/scripts/finalize-run-json.mjs +141 -0
  117. package/skills/wix-headless/scripts/init-site-json.mjs +63 -0
  118. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +124 -0
  119. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +190 -0
  120. package/skills/wix-headless/scripts/preview.sh +45 -0
  121. package/skills/wix-headless/scripts/release.sh +73 -0
  122. package/skills/wix-headless/scripts/scaffold.sh +53 -0
  123. package/skills/wix-headless/scripts/seed-utilities.sh +55 -0
  124. package/skills/wix-headless/shared-utilities/analytics.ts +40 -0
  125. package/skills/wix-headless/shared-utilities/ricos.ts +179 -0
  126. package/skills/wix-headless/shared-utilities/wix-image.ts +72 -0
  127. package/skills/wix-headless/templates/ecom/CartBadge.tsx +84 -0
  128. package/skills/wix-headless/templates/ecom/CartView.tsx +543 -0
  129. package/skills/wix-headless/templates/ecom/cart.astro +13 -0
  130. package/skills/wix-headless/templates/ecom/components-ecom.css +215 -0
  131. package/skills/wix-headless/templates/ecom/discounts.ts +71 -0
  132. package/skills/wix-headless/templates/ecom/thank-you.astro +24 -0
  133. package/skills/wix-headless/templates/gift-cards/GiftCardPurchase.tsx +172 -0
  134. package/skills/wix-headless/templates/gift-cards/_home-teaser-snippet.astro +42 -0
  135. package/skills/wix-headless/templates/gift-cards/_nav-snippet.astro +11 -0
  136. package/skills/wix-headless/templates/gift-cards/components-gift-cards.css +219 -0
  137. package/skills/wix-headless/templates/gift-cards/gift-cards.astro +51 -0
  138. package/skills/wix-headless/templates/gift-cards/gift-cards.ts +75 -0
  139. package/skills/wix-headless/templates/stores/AddToCartButton.tsx +77 -0
  140. package/skills/wix-headless/templates/stores/BackInStockForm.tsx +176 -0
  141. package/skills/wix-headless/templates/stores/CategoryRail.astro +69 -0
  142. package/skills/wix-headless/templates/stores/ProductCard.astro +79 -0
  143. package/skills/wix-headless/templates/stores/ProductPurchase.tsx +397 -0
  144. package/skills/wix-headless/templates/stores/SeoTags.astro +21 -0
  145. package/skills/wix-headless/templates/stores/back-in-stock.ts +67 -0
  146. package/skills/wix-headless/templates/stores/categories.ts +155 -0
  147. package/skills/wix-headless/templates/stores/category/[slug].astro +130 -0
  148. package/skills/wix-headless/templates/stores/components-stores.css +295 -0
  149. package/skills/wix-headless/templates/stores/products/[slug].astro +128 -0
  150. package/skills/wix-headless/templates/stores/products/index.astro +101 -0
  151. package/skills/wix-manage/SKILL.md +280 -0
  152. package/skills/wix-manage/references/app-installation/install-wix-apps.md +155 -0
  153. package/skills/wix-manage/references/app-installation/list-installed-apps.md +124 -0
  154. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +226 -0
  155. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +95 -0
  156. package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +416 -0
  157. package/skills/wix-manage/references/bookings/bookings-staff-setup.md +255 -0
  158. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +462 -0
  159. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +278 -0
  160. package/skills/wix-manage/references/bookings/external-calendar-integration.md +258 -0
  161. package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +231 -0
  162. package/skills/wix-manage/references/calendar/configure-default-business-hours.md +226 -0
  163. package/skills/wix-manage/references/cms/cms-data-items-crud.md +422 -0
  164. package/skills/wix-manage/references/cms/cms-data-operations-extended.md +263 -0
  165. package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +136 -0
  166. package/skills/wix-manage/references/cms/cms-references-and-relationships.md +160 -0
  167. package/skills/wix-manage/references/cms/cms-schema-management.md +143 -0
  168. package/skills/wix-manage/references/contacts/bulk-delete-contacts.md +73 -0
  169. package/skills/wix-manage/references/contacts/bulk-label-and-unlabel-contacts.md +67 -0
  170. package/skills/wix-manage/references/domains/domain-search-and-purchase.md +434 -0
  171. package/skills/wix-manage/references/ecommerce/api-recommendation-tracking.md +420 -0
  172. package/skills/wix-manage/references/ecommerce/flow-add-free-shipping.md +267 -0
  173. package/skills/wix-manage/references/ecommerce/flow-bundle-and-save.md +290 -0
  174. package/skills/wix-manage/references/ecommerce/flow-fix-coverage-gaps.md +300 -0
  175. package/skills/wix-manage/references/ecommerce/flow-optimize-shipping-rates.md +364 -0
  176. package/skills/wix-manage/references/ecommerce/flow-seasonal-promotion.md +315 -0
  177. package/skills/wix-manage/references/ecommerce/flow-stock-mover.md +308 -0
  178. package/skills/wix-manage/references/ecommerce/flow-upsell-boost.md +271 -0
  179. package/skills/wix-manage/references/ecommerce/goal-clear-inventory.md +118 -0
  180. package/skills/wix-manage/references/ecommerce/goal-drive-cross-sells.md +122 -0
  181. package/skills/wix-manage/references/ecommerce/goal-increase-aov.md +132 -0
  182. package/skills/wix-manage/references/ecommerce/goal-reduce-cart-abandonment.md +148 -0
  183. package/skills/wix-manage/references/ecommerce/goal-seasonal-revenue.md +146 -0
  184. package/skills/wix-manage/references/ecommerce/guardrail-discount-conflicts.md +118 -0
  185. package/skills/wix-manage/references/ecommerce/guardrail-margin-protection.md +88 -0
  186. package/skills/wix-manage/references/ecommerce/guardrail-rate-pricing-sanity.md +108 -0
  187. package/skills/wix-manage/references/ecommerce/guardrail-shipping-health.md +124 -0
  188. package/skills/wix-manage/references/ecommerce/recipe-apply-shipping-recommendations.md +299 -0
  189. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +582 -0
  190. package/skills/wix-manage/references/ecommerce/setup-coupons.md +338 -0
  191. package/skills/wix-manage/references/ecommerce/setup-discount-rules.md +444 -0
  192. package/skills/wix-manage/references/ecommerce/setup-shipping-rates.md +86 -0
  193. package/skills/wix-manage/references/ecommerce/setup-shipping-regions.md +56 -0
  194. package/skills/wix-manage/references/ecommerce/setup-store-pickup-location.md +209 -0
  195. package/skills/wix-manage/references/ecommerce/skill-graph.md +139 -0
  196. package/skills/wix-manage/references/ecommerce/troubleshoot-checkout-delivery-dropoff.md +124 -0
  197. package/skills/wix-manage/references/ecommerce/troubleshoot-discount-not-applying.md +95 -0
  198. package/skills/wix-manage/references/events/list-events.md +203 -0
  199. package/skills/wix-manage/references/forms/create-form.md +260 -0
  200. package/skills/wix-manage/references/get-paid/create-payment-links.md +212 -0
  201. package/skills/wix-manage/references/get-paid/how-to-setup-wix-payments.md +57 -0
  202. package/skills/wix-manage/references/get-paid/payment-links-for-bookings.md +101 -0
  203. package/skills/wix-manage/references/media/upload-media-to-wix.md +216 -0
  204. package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +77 -0
  205. package/skills/wix-manage/references/pricing-plans/pricing-plans-bookings-integration.md +166 -0
  206. package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +336 -0
  207. package/skills/wix-manage/references/rich-content/ricos-converter-service.md +295 -0
  208. package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +59 -0
  209. package/skills/wix-manage/references/sites/create-site-from-template.md +183 -0
  210. package/skills/wix-manage/references/sites/query-sites.md +125 -0
  211. package/skills/wix-manage/references/stores/add-store-pages-to-site.md +57 -0
  212. package/skills/wix-manage/references/stores/bulk-create-products-with-options.md +1041 -0
  213. package/skills/wix-manage/references/stores/create-product-catalog-v1.md +125 -0
  214. package/skills/wix-manage/references/stores/create-product-from-image.md +824 -0
  215. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +566 -0
  216. package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +194 -0
  217. package/skills/wix-manage/references/stores/query-products-catalog-v1.md +80 -0
  218. package/skills/wix-manage/references/stores/setup-online-store-catalog-v3.md +99 -0
  219. package/skills/wix-manage/references/stores/update-product-pre-order.md +213 -0
  220. package/skills/wix-manage/references/stores/update-product-with-options.md +318 -0
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ // Inject Image-Phase-1 decorative URLs into the designer-emitted page shells.
3
+ //
4
+ // The Phase 2 designer writes `<div data-decorative-slot="<key>">…</div>`
5
+ // placeholders in src/pages/*.astro. Image Phase 1 writes resolved URLs to
6
+ // .wix/image-urls.md. This script reads both, then injects an <img> element
7
+ // as the first child of each matching slot div — pure string substitution,
8
+ // no LLM, no file rewrites.
9
+ //
10
+ // Usage:
11
+ // node patch-decorative-slots.mjs <project-dir>
12
+ //
13
+ // Behavior:
14
+ // - If .wix/image-urls.md doesn't exist, exit 0 silently (Image Phase 1
15
+ // timed out / failed; the slot placeholders look complete on their own).
16
+ // - For each `data-decorative-slot="<key>"` in src/pages/*.astro:
17
+ // * If <key> has no URL in image-urls.md → leave the div alone.
18
+ // * If the div is self-closing or already has a child element other
19
+ // than whitespace/comments → skip with a warning (don't clobber).
20
+ // * Otherwise inject <img …> as the first child.
21
+ // - Output a JSON summary of patches/skips/warnings to stdout.
22
+ // - Exit 0 even when some slots couldn't be patched — placeholders fall
23
+ // back to the designer's aspect-ratio + background-color rendering.
24
+
25
+ import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from "node:fs";
26
+ import { join } from "node:path";
27
+
28
+ const projectDir = process.argv[2] ?? process.cwd();
29
+
30
+ const imageUrlsPath = join(projectDir, ".wix/image-urls.md");
31
+ if (!existsSync(imageUrlsPath)) {
32
+ console.log(JSON.stringify({ status: "skipped", reason: "no .wix/image-urls.md (Image Phase 1 didn't write — failed or timed out)" }));
33
+ process.exit(0);
34
+ }
35
+
36
+ // Parse `## <key>\n- url: <url>` blocks from .wix/image-urls.md.
37
+ const imageUrlsRaw = readFileSync(imageUrlsPath, "utf8");
38
+ const urlMap = {};
39
+ // Match `## key\n…- url: <url>` per section. The inner `(?:(?!^##\s)[\s\S])*?`
40
+ // forbids the lazy span from crossing into the next `## ` line — without
41
+ // that guard, an empty `- url:` for one slot silently steals the next
42
+ // section's URL on partial-failure runs.
43
+ const sectionRegex = /^##\s+(\S+)\s*\n(?:(?!^##\s)[\s\S])*?-\s*url:\s*(https?:\/\/\S+)/gm;
44
+ let m;
45
+ while ((m = sectionRegex.exec(imageUrlsRaw)) !== null) {
46
+ urlMap[m[1]] = m[2];
47
+ }
48
+
49
+ if (Object.keys(urlMap).length === 0) {
50
+ console.log(JSON.stringify({ status: "skipped", reason: ".wix/image-urls.md exists but has no parseable `## key` + `- url:` blocks" }));
51
+ process.exit(0);
52
+ }
53
+
54
+ // Find candidate page files: src/pages/*.astro, recursively (designer may emit
55
+ // /about.astro at top level OR /pages/about.astro).
56
+ const pagesDir = join(projectDir, "src/pages");
57
+ const candidates = [];
58
+ const walk = (dir) => {
59
+ if (!existsSync(dir)) return;
60
+ for (const entry of readdirSync(dir)) {
61
+ const full = join(dir, entry);
62
+ const stat = statSync(full);
63
+ if (stat.isDirectory()) walk(full);
64
+ else if (stat.isFile() && entry.endsWith(".astro")) candidates.push(full);
65
+ }
66
+ };
67
+ walk(pagesDir);
68
+
69
+ const patched = [];
70
+ const skipped = [];
71
+ const warnings = [];
72
+
73
+ const SLOT_DIV_REGEX = /(<div[^>]*\bdata-decorative-slot="([^"]+)"[^>]*>)([\s\S]*?)(<\/div>)/g;
74
+
75
+ for (const file of candidates) {
76
+ const original = readFileSync(file, "utf8");
77
+ let modified = original;
78
+ let fileChanged = false;
79
+
80
+ modified = modified.replace(SLOT_DIV_REGEX, (match, openTag, slotKey, inner, closeTag) => {
81
+ const url = urlMap[slotKey];
82
+ if (!url) {
83
+ skipped.push({ file, slot: slotKey, reason: "no URL for this slot in image-urls.md" });
84
+ return match;
85
+ }
86
+
87
+ // Strip HTML comments before any content checks — the designer's placeholder
88
+ // is a comment like `<!-- orchestrator injects <img> here -->`, which would
89
+ // otherwise false-positive both the idempotency and clobber-guard checks.
90
+ const stripped = inner.replace(/<!--[\s\S]*?-->/g, "").trim();
91
+
92
+ // Skip if div already contains an <img> element (idempotency).
93
+ if (/<img\b/i.test(stripped)) {
94
+ skipped.push({ file, slot: slotKey, reason: "div already contains an <img> tag (idempotent skip)" });
95
+ return match;
96
+ }
97
+
98
+ // Skip if div has substantive child content beyond whitespace/comments.
99
+ if (stripped.length > 0) {
100
+ warnings.push({ file, slot: slotKey, reason: "div has existing non-image child content; not patching to avoid clobber" });
101
+ return match;
102
+ }
103
+
104
+ fileChanged = true;
105
+ const img = `<img src="${url}" alt="" loading="lazy" decoding="async" class="decorative-slot-img" />`;
106
+ patched.push({ file, slot: slotKey });
107
+ // Preserve any whitespace inside the div (e.g., the newline + indent).
108
+ return `${openTag}\n ${img}${inner}${closeTag}`;
109
+ });
110
+
111
+ if (fileChanged) {
112
+ writeFileSync(file, modified);
113
+ }
114
+ }
115
+
116
+ const summary = {
117
+ status: warnings.length > 0 ? "partial" : "ok",
118
+ imageUrls: Object.keys(urlMap),
119
+ filesScanned: candidates.length,
120
+ patched,
121
+ skipped,
122
+ warnings,
123
+ };
124
+ console.log(JSON.stringify(summary, null, 2));
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ // Build a deterministic execution plan for Image Phase 2 from a slim image
3
+ // agent's prompt array + the orchestrator's per-product / per-cms-item GETs.
4
+ //
5
+ // The slim image agent's only job is to return a list of brand-aligned prompts
6
+ // (one per entity). This script transforms that list (plus the entity details
7
+ // the orchestrator pre-fetched) into a structured plan the orchestrator can
8
+ // execute as a sequence of concurrent batches:
9
+ //
10
+ // waves — Runware generation requests, grouped into waves of <waveSize>
11
+ // (default 3) to match the google:4@2 throttle. Each wave is
12
+ // one orchestration step with N parallel CallWixSiteAPI tool
13
+ // calls; each tool call sends one task in the body array.
14
+ //
15
+ // imports — POST /site-media/v1/files/import requests, one per generated
16
+ // image. Indexed by taskUUID so the orchestrator threads the
17
+ // wave-result URL through to the import body.
18
+ //
19
+ // patches — Per-entity-type write requests (PATCH for products & blog
20
+ // posts; PUT for CMS items). Bodies use placeholders the
21
+ // orchestrator substitutes with import results:
22
+ // __IMAGE_URL__ — the full wixstatic URL (file.url)
23
+ // __IMAGE_FILE_ID__ — the file ID (file.fileUrl)
24
+ //
25
+ // publishes — Re-publish calls for blog posts ONLY (PATCHing a published
26
+ // draft un-publishes it). One per blog-post entity.
27
+ //
28
+ // Usage:
29
+ // echo "$INPUT_JSON" | node plan-entity-image-waves.mjs
30
+ //
31
+ // The script is pure data transformation — no I/O beyond stdin / stdout, no
32
+ // MCP, no network. The encoded knowledge is the per-entity-type body shapes
33
+ // (frozen from references/images/INSTRUCTIONS.md so a single source of truth).
34
+
35
+ import { readFileSync } from "node:fs";
36
+
37
+ // Body shape constants — keep aligned with references/images/INSTRUCTIONS.md.
38
+ const RUNWARE_DEFAULTS = {
39
+ taskType: "imageInference",
40
+ outputType: "URL",
41
+ outputFormat: "PNG",
42
+ model: "google:4@2",
43
+ numberResults: 1,
44
+ };
45
+
46
+ const DEFAULT_WAVE_SIZE = 3;
47
+
48
+ let input;
49
+ try {
50
+ input = JSON.parse(readFileSync(0, "utf8"));
51
+ } catch (e) {
52
+ console.error(`plan-entity-image-waves: stdin is not valid JSON (${e.message})`);
53
+ process.exit(2);
54
+ }
55
+
56
+ const prompts = Array.isArray(input.prompts) ? input.prompts : [];
57
+ if (prompts.length === 0) {
58
+ console.error("plan-entity-image-waves: no prompts in input — nothing to plan");
59
+ process.exit(2);
60
+ }
61
+
62
+ const productDetails = input.productDetails ?? {};
63
+ const cmsDetails = input.cmsDetails ?? {};
64
+ const waveSize = Math.max(1, Math.min(input.waveSize ?? DEFAULT_WAVE_SIZE, 8));
65
+ const model = input.model ?? RUNWARE_DEFAULTS.model;
66
+
67
+ // ---- 1. Runware waves (gen-side parallelism, throttle-bucketed) -----------
68
+ const waves = [];
69
+ for (let i = 0; i < prompts.length; i += waveSize) {
70
+ const slice = prompts.slice(i, i + waveSize);
71
+ waves.push(slice.map((p) => ({
72
+ taskUUID: p.taskUUID,
73
+ body: [{
74
+ ...RUNWARE_DEFAULTS,
75
+ model,
76
+ taskUUID: p.taskUUID,
77
+ positivePrompt: p.positivePrompt,
78
+ width: p.width ?? 1024,
79
+ height: p.height ?? 1024,
80
+ outputFormat: p.outputFormat ?? RUNWARE_DEFAULTS.outputFormat,
81
+ }],
82
+ })));
83
+ }
84
+
85
+ // ---- 2. Wix Media imports (one per generated image) -----------------------
86
+ const imports = prompts.map((p) => ({
87
+ taskUUID: p.taskUUID,
88
+ mimeType: p.outputFormat === "JPG" ? "image/jpeg" : "image/png",
89
+ displayName: p.displayName ?? `${p.entityId}.${(p.outputFormat ?? "PNG").toLowerCase()}`,
90
+ }));
91
+
92
+ // ---- 3. Per-entity-type write requests ------------------------------------
93
+ const patches = [];
94
+ const publishes = [];
95
+
96
+ for (const p of prompts) {
97
+ if (p.entityType === "product") {
98
+ const detail = productDetails[p.entityId];
99
+ if (!detail) {
100
+ console.error(`plan-entity-image-waves: missing productDetails for entityId=${p.entityId}`);
101
+ process.exit(1);
102
+ }
103
+ if (detail.revision === undefined || detail.revision === null) {
104
+ console.error(`plan-entity-image-waves: productDetails[${p.entityId}].revision is required (mandatory per Update-Product endpoint)`);
105
+ process.exit(1);
106
+ }
107
+ patches.push({
108
+ taskUUID: p.taskUUID,
109
+ entityType: "product",
110
+ entityId: p.entityId,
111
+ method: "PATCH",
112
+ url: `https://www.wixapis.com/stores/v3/products/${p.entityId}`,
113
+ // Body echoes options + variantsInfo (mandatory — see images/INSTRUCTIONS.md
114
+ // §428-prevention) and embeds the URL via __IMAGE_URL__ placeholder.
115
+ body: {
116
+ product: {
117
+ revision: detail.revision,
118
+ media: {
119
+ itemsInfo: {
120
+ items: [{ url: "__IMAGE_URL__", altText: p.displayName ?? p.entityId }],
121
+ },
122
+ },
123
+ ...(detail.options !== undefined ? { options: detail.options } : {}),
124
+ ...(detail.variantsInfo !== undefined ? { variantsInfo: detail.variantsInfo } : {}),
125
+ },
126
+ },
127
+ });
128
+ } else if (p.entityType === "blogPost") {
129
+ patches.push({
130
+ taskUUID: p.taskUUID,
131
+ entityType: "blogPost",
132
+ entityId: p.entityId,
133
+ method: "PATCH",
134
+ url: `https://www.wixapis.com/blog/v3/draft-posts/${p.entityId}`,
135
+ // Blog uses the file ID (fileUrl), not the wixstatic URL.
136
+ body: {
137
+ draftPost: {
138
+ media: { wixMedia: { image: { id: "__IMAGE_FILE_ID__" } } },
139
+ },
140
+ },
141
+ });
142
+ publishes.push({
143
+ entityId: p.entityId,
144
+ method: "POST",
145
+ url: `https://www.wixapis.com/blog/v3/draft-posts/${p.entityId}/publish`,
146
+ });
147
+ } else if (p.entityType === "cmsItem") {
148
+ const detail = cmsDetails[p.entityId];
149
+ if (!detail) {
150
+ console.error(`plan-entity-image-waves: missing cmsDetails for entityId=${p.entityId}`);
151
+ process.exit(1);
152
+ }
153
+ if (!detail.collectionId || !detail.imageField || !detail.data) {
154
+ console.error(`plan-entity-image-waves: cmsDetails[${p.entityId}] requires collectionId, imageField, and data (existing item record)`);
155
+ process.exit(1);
156
+ }
157
+ // Read-merge-PUT: echo every existing data field, set the image field
158
+ // to the placeholder URL. Wipes nothing (the bug observed in 2026-04-19).
159
+ const mergedData = { ...detail.data, [detail.imageField]: "__IMAGE_URL__" };
160
+ patches.push({
161
+ taskUUID: p.taskUUID,
162
+ entityType: "cmsItem",
163
+ entityId: p.entityId,
164
+ method: "PUT",
165
+ url: `https://www.wixapis.com/wix-data/v2/items/${p.entityId}`,
166
+ body: {
167
+ dataCollectionId: detail.collectionId,
168
+ dataItem: { id: p.entityId, data: mergedData },
169
+ },
170
+ });
171
+ } else {
172
+ console.error(`plan-entity-image-waves: unknown entityType "${p.entityType}" for entityId=${p.entityId} — must be product | blogPost | cmsItem`);
173
+ process.exit(1);
174
+ }
175
+ }
176
+
177
+ const plan = {
178
+ meta: {
179
+ promptCount: prompts.length,
180
+ waveCount: waves.length,
181
+ waveSize,
182
+ model,
183
+ },
184
+ waves,
185
+ imports,
186
+ patches,
187
+ publishes,
188
+ };
189
+
190
+ console.log(JSON.stringify(plan, null, 2));
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bash
2
+ # Build the project and deploy a rotating preview URL.
3
+ #
4
+ # Usage:
5
+ # bash <SKILL_ROOT>/scripts/preview.sh
6
+ #
7
+ # Run from the project directory (CWD = <project>/). Requires wix.config.json.
8
+ #
9
+ # Output: stdout is the preview URL that `npx @wix/cli preview` printed; the
10
+ # orchestrator captures it and records as outcome.previewUrl in run.json. All
11
+ # other CLI output goes to stderr.
12
+ #
13
+ # `preview` does NOT populate the Frontend link in headless settings — that's
14
+ # what `release.sh` is for. Use preview for fast iteration on a rotating URL;
15
+ # use release for production deploy + transactional-email URL stability.
16
+ #
17
+ # Exit codes:
18
+ # 0 — ok; preview URL on stdout
19
+ # <other> — build or preview failed; stderr surfaces the underlying error
20
+ # (TypeScript / Astro errors are code bugs, not endpoint drift —
21
+ # the orchestrator's recovery ladder doesn't retry build).
22
+
23
+ set -euo pipefail
24
+
25
+ # Build first; surface compile errors verbatim if it fails.
26
+ npx @wix/cli build 1>&2
27
+
28
+ # Preview captures the deployed URL on stdout. We tee its output to stderr for
29
+ # the user-visible log AND parse the URL out for the orchestrator's stdout.
30
+ PREVIEW_OUTPUT="$(mktemp)"
31
+ trap 'rm -f "$PREVIEW_OUTPUT"' EXIT
32
+
33
+ npx @wix/cli preview 2>&1 | tee "$PREVIEW_OUTPUT" 1>&2
34
+
35
+ # Wix CLI prints `Site preview URL: <url>` (or similar) — extract the first
36
+ # https URL from the output. If multiple are printed, the first is the canonical
37
+ # preview URL.
38
+ PREVIEW_URL="$(grep -oE 'https://[A-Za-z0-9.-]+\.wix-host\.com[^[:space:]]*' "$PREVIEW_OUTPUT" | head -n 1 || true)"
39
+
40
+ if [[ -z "$PREVIEW_URL" ]]; then
41
+ echo "preview.sh: could not extract a *.wix-host.com URL from preview output" >&2
42
+ exit 1
43
+ fi
44
+
45
+ echo "$PREVIEW_URL"
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env bash
2
+ # Build the project and release to production. Unlike preview.sh, this populates
3
+ # the Frontend link in dashboard → Settings → Headless Settings → Manage URLs,
4
+ # which Wix injects into transactional emails (order confirmations, password
5
+ # resets, member invites). Use release.sh for production deploys.
6
+ #
7
+ # Usage:
8
+ # bash <SKILL_ROOT>/scripts/release.sh
9
+ #
10
+ # Run from the project directory (CWD = <project>/). Requires wix.config.json.
11
+ #
12
+ # Output: stdout is the released URL that `npx @wix/cli release` printed
13
+ # (extracted from the line `Site published on <url>`); the orchestrator
14
+ # captures it as outcome.releaseUrl in run.json. All other CLI output goes
15
+ # to stderr.
16
+ #
17
+ # Exit codes:
18
+ # 0 — ok; release URL on stdout
19
+ # <other> — build or release failed; stderr surfaces the underlying error.
20
+ # Build failures are code bugs (TypeScript / Astro / missing
21
+ # module) — the orchestrator does NOT retry. Release auth failures
22
+ # surface as `Run npx @wix/cli login and retry.`
23
+ # Known transient release failures are retried by this script.
24
+
25
+ set -euo pipefail
26
+
27
+ npx @wix/cli build 1>&2
28
+
29
+ RELEASE_OUTPUT="$(mktemp)"
30
+ trap 'rm -f "$RELEASE_OUTPUT"' EXIT
31
+
32
+ release_is_retryable() {
33
+ grep -Eiq 'ECONNRESET|ETIMEDOUT|EAI_AGAIN|STATE_MISMATCH|temporary system error|temporarily unavailable|try again shortly' "$RELEASE_OUTPUT"
34
+ }
35
+
36
+ MAX_RELEASE_ATTEMPTS="${WIX_RELEASE_ATTEMPTS:-3}"
37
+ RELEASE_STATUS=1
38
+
39
+ for ((attempt = 1; attempt <= MAX_RELEASE_ATTEMPTS; attempt++)); do
40
+ : >"$RELEASE_OUTPUT"
41
+ set +e
42
+ npx @wix/cli release 2>&1 | tee "$RELEASE_OUTPUT" 1>&2
43
+ RELEASE_STATUS=${PIPESTATUS[0]}
44
+ set -e
45
+
46
+ if [[ "$RELEASE_STATUS" -eq 0 ]]; then
47
+ break
48
+ fi
49
+
50
+ if [[ "$attempt" -lt "$MAX_RELEASE_ATTEMPTS" ]] && release_is_retryable; then
51
+ sleep_seconds=$((attempt * 5))
52
+ echo "release.sh: release attempt $attempt failed with a retryable Wix error; retrying in ${sleep_seconds}s" >&2
53
+ sleep "$sleep_seconds"
54
+ continue
55
+ fi
56
+
57
+ exit "$RELEASE_STATUS"
58
+ done
59
+
60
+ # CLI prints `Site published on <url>` — extract the URL after that marker.
61
+ # Fall back to the first Wix-hosted URL if the marker line is not found
62
+ # (CLI wording may vary between versions).
63
+ RELEASE_URL="$(sed -nE 's/.*Site published on ([^[:space:]]+).*/\1/p' "$RELEASE_OUTPUT" | head -n 1 || true)"
64
+ if [[ -z "$RELEASE_URL" ]]; then
65
+ RELEASE_URL="$(grep -oE 'https://[A-Za-z0-9.-]+\.wix-(site-)?host\.com[^[:space:]]*' "$RELEASE_OUTPUT" | head -n 1 || true)"
66
+ fi
67
+
68
+ if [[ -z "$RELEASE_URL" ]]; then
69
+ echo "release.sh: could not extract a release URL from release output" >&2
70
+ exit 1
71
+ fi
72
+
73
+ echo "$RELEASE_URL"
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ # Scaffold a new Wix Managed Headless project with the pure-headless blank template.
3
+ #
4
+ # Usage:
5
+ # bash <SKILL_ROOT>/scripts/scaffold.sh <project-slug> "<Brand Name>"
6
+ #
7
+ # <project-slug>: 3-20 lowercase alphanumeric chars (no hyphens, no spaces) — the
8
+ # Wix CLI rejects anything else. Becomes the project directory name.
9
+ # <Brand Name>: human-readable business name; quote if it contains spaces.
10
+ #
11
+ # After scaffold succeeds, read <project-slug>/wix.config.json to extract appId
12
+ # (project's appId) and siteId (used for MCP calls). The orchestrator does that
13
+ # read; this script just runs the npm create.
14
+ #
15
+ # Behavior:
16
+ # - Pre-flight validates the slug (regex ^[a-z0-9]{3,20}$).
17
+ # - Pre-flight requires both args.
18
+ # - Runs `npm create @wix/new@latest headless` with --no-publish + --skip-install
19
+ # so the orchestrator can deferred-install with its own package set.
20
+ # - Template ID is the pure-headless blank (vibe-compatible templates trigger
21
+ # an interactive prompt that blocks non-TTY runs).
22
+ #
23
+ # Exit codes:
24
+ # 0 — ok
25
+ # 2 — argument validation failed
26
+ # <other> — npm create failed; stderr surfaced to caller for orchestrator-side
27
+ # recovery (auth / invalid-template ladder lives in the orchestrator).
28
+
29
+ set -euo pipefail
30
+
31
+ if [[ $# -lt 2 || -z "${1:-}" || -z "${2:-}" ]]; then
32
+ echo "scaffold.sh: both args required. Got project-slug='${1:-}' brand-name='${2:-}'." >&2
33
+ echo "Usage: bash scaffold.sh <slug> \"<Brand Name>\" — slug first, brand quoted." >&2
34
+ exit 2
35
+ fi
36
+
37
+ if [[ ! "$1" =~ ^[a-z0-9]{3,20}$ ]]; then
38
+ echo "scaffold.sh: project-slug='$1' is not valid." >&2
39
+ echo "Slug must be 3-20 lowercase alphanumeric chars (no hyphens, no spaces)." >&2
40
+ echo "Derive from the brand: lowercase, strip non-[a-z0-9], truncate to 20." >&2
41
+ exit 2
42
+ fi
43
+
44
+ # Pure-headless blank template. Vibe-compatible templates show an interactive
45
+ # vibe setup prompt that blocks non-TTY contexts — do not substitute.
46
+ TEMPLATE_ID="blank"
47
+
48
+ npm create @wix/new@latest headless -- \
49
+ --business-name "$2" \
50
+ --project-name "$1" \
51
+ --site-template "$TEMPLATE_ID" \
52
+ --no-publish \
53
+ --skip-install
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+ # Copy the skill's shared utilities into the project's src/utils/ and strip the
3
+ # Astro starter cruft that ships with the blank template.
4
+ #
5
+ # Usage (both modes work):
6
+ # bash <SKILL_ROOT>/scripts/seed-utilities.sh # installed tgz
7
+ # bash <(curl -s https://dev.wix.com/skills/wix-headless/scripts/seed-utilities.sh)
8
+ #
9
+ # Run from the project directory (CWD = <project>/). The script auto-detects
10
+ # whether shared-utilities is available on disk (tgz install) and falls back
11
+ # to fetching from the well-known URL when streamed via process substitution
12
+ # (BASH_SOURCE is /dev/fd/N, so the on-disk lookup naturally falls through).
13
+ #
14
+ # Behavior:
15
+ # - Copies the three shared utility files into src/utils/ — never overwrites
16
+ # an existing file (users can drop in their own version to override).
17
+ # - Removes Astro starter cruft (Welcome.astro + marketing SVGs) that ships
18
+ # with the blank template but is never imported by the build skill.
19
+ #
20
+ # Shared utilities copied:
21
+ # - wix-image.ts — media URL resolver (used by stores, blog, cms)
22
+ # - analytics.ts — event tracking (used by stores, ecom, blog)
23
+ # - ricos.ts — Ricos JSON to HTML renderer for SSR Astro pages
24
+
25
+ set -euo pipefail
26
+
27
+ SKILL_URL="https://dev.wix.com/skills/wix-headless"
28
+ UTILS=(analytics.ts ricos.ts wix-image.ts)
29
+
30
+ # Mode detection: prefer on-disk skill root if the sibling dir exists, else
31
+ # fetch over HTTP. Covers both tgz install and `bash <(curl ...)` streaming.
32
+ SHARED_UTILS_DIR=""
33
+ script_path="${BASH_SOURCE[0]}"
34
+ if [[ -f "$script_path" ]]; then
35
+ candidate="$(dirname "$script_path")/../shared-utilities"
36
+ if [[ -d "$candidate" ]]; then
37
+ SHARED_UTILS_DIR="$(cd "$candidate" && pwd)"
38
+ fi
39
+ fi
40
+
41
+ mkdir -p src/utils
42
+
43
+ for f in "${UTILS[@]}"; do
44
+ dest="src/utils/$f"
45
+ if [[ -e "$dest" ]]; then continue; fi
46
+ if [[ -n "$SHARED_UTILS_DIR" ]]; then
47
+ cp "$SHARED_UTILS_DIR/$f" "$dest"
48
+ else
49
+ curl -fsSL "$SKILL_URL/shared-utilities/$f" -o "$dest"
50
+ fi
51
+ done
52
+
53
+ # Astro starter cruft cleanup.
54
+ rm -f src/components/Welcome.astro
55
+ rm -f src/assets/astro.svg src/assets/wix.svg src/assets/background.svg
@@ -0,0 +1,40 @@
1
+ export type AnalyticsEventName =
2
+ | "AddToCart"
3
+ | "RemoveFromCart"
4
+ | "InitiateCheckout"
5
+ | "Purchase"
6
+ | "ArticleView"
7
+ | "FormSubmit"
8
+ | "AddProductImpression"
9
+ | "ViewContent"
10
+ | "ClickProduct"
11
+ | (string & {});
12
+
13
+ export function trackEvent(
14
+ name: AnalyticsEventName,
15
+ payload?: Record<string, unknown>,
16
+ ): void {
17
+ if (typeof window === "undefined") return;
18
+
19
+ const event = { name, ...(payload ?? {}) };
20
+
21
+ const w = window as unknown as {
22
+ dataLayer?: unknown[];
23
+ wixAnalytics?: { track(event: { name: string } & Record<string, unknown>): void };
24
+ };
25
+
26
+ if (w.wixAnalytics?.track) {
27
+ w.wixAnalytics.track(event);
28
+ return;
29
+ }
30
+
31
+ if (w.dataLayer) {
32
+ w.dataLayer.push({ event: name, ...event });
33
+ return;
34
+ }
35
+
36
+ const meta = import.meta as unknown as { env?: { DEV?: boolean } };
37
+ if (meta.env?.DEV) {
38
+ console.debug("[analytics]", event);
39
+ }
40
+ }