@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,356 @@
1
+ # Recipe: Resource Library / Downloads
2
+
3
+ Build a downloadable resource library using `@wix/data` — file listings with category filtering, file type badges, and detail pages with download buttons. Use for documents, guides, templates, whitepapers, or any downloadable assets.
4
+
5
+ > Read `CMS_FOUNDATIONS.md` first for shared patterns (service module, image resolution, elevation, MCP seeding).
6
+
7
+ ## Collection Schema
8
+
9
+ Create a collection in the Wix dashboard → CMS with these fields:
10
+
11
+ | Field | Type | Purpose |
12
+ |-------|------|---------|
13
+ | `title` | Text | Resource name |
14
+ | `slug` | Text | URL-friendly identifier |
15
+ | `description` | Rich Text | Resource description (HTML) |
16
+ | `category` | Text | Resource category (e.g., "Guides", "Templates") |
17
+ | `fileType` | Text | File extension — `PDF`, `DOC`, `ZIP`, `XLS`, etc. |
18
+ | `fileUrl` | URL | Download URL (external link or Wix media URL) |
19
+ | `fileSize` | Text | Human-readable file size (e.g., "2.4 MB") |
20
+ | `coverImage` | Image | Thumbnail (`wix:image://` — resolve with `media.getScaledToFillImageUrl()`) |
21
+ | `published` | Boolean | Publish status |
22
+ | `_createdDate` | Date | Auto-populated creation date |
23
+
24
+ ## Files to Create
25
+
26
+ | File | Purpose |
27
+ |------|---------|
28
+ | `src/lib/resources.ts` | Service module — queries, category filtering, related resources |
29
+ | `src/pages/resources/index.astro` | Listing with category filter + file type badges |
30
+ | `src/pages/resources/[slug].astro` | Detail page with download button + related resources |
31
+ | `src/components/ResourceCard.astro` | Card with file type icon, title, size |
32
+ | `src/components/FileTypeIcon.astro` | SVG switch for PDF/DOC/ZIP/generic |
33
+
34
+ ## Implementation
35
+
36
+ ### 1. Resources Service Module (`src/lib/resources.ts`)
37
+
38
+ ```typescript
39
+ import * as items from "@wix/wix-data-items-sdk";
40
+ import { auth } from "@wix/essentials";
41
+ import { media } from "@wix/sdk";
42
+
43
+ const COLLECTION_ID = "Resources";
44
+
45
+ export interface Resource {
46
+ _id: string;
47
+ title: string;
48
+ slug: string;
49
+ description?: string;
50
+ category: string;
51
+ fileType: string;
52
+ fileUrl: string;
53
+ fileSize?: string;
54
+ coverImage?: string;
55
+ published: boolean;
56
+ _createdDate?: string;
57
+ }
58
+
59
+ function resolveImage(url: string | undefined): string | undefined {
60
+ if (!url) return undefined;
61
+ return media.getScaledToFillImageUrl(url, 600, 400, {});
62
+ }
63
+
64
+ function mapResource(item: Record<string, any>): Resource {
65
+ return {
66
+ _id: item._id,
67
+ title: item.title ?? "",
68
+ slug: item.slug ?? "",
69
+ description: item.description,
70
+ category: item.category ?? "",
71
+ fileType: (item.fileType ?? "FILE").toUpperCase(),
72
+ fileUrl: item.fileUrl ?? "",
73
+ fileSize: item.fileSize,
74
+ coverImage: resolveImage(item.coverImage),
75
+ published: item.published ?? false,
76
+ _createdDate: item._createdDate,
77
+ };
78
+ }
79
+
80
+ export async function queryResources(): Promise<Resource[]> {
81
+ const elevatedQuery = auth.elevate(items.query);
82
+ const { items: results } = await elevatedQuery(COLLECTION_ID)
83
+ .eq("published", true)
84
+ .descending("_createdDate")
85
+ .limit(50)
86
+ .find();
87
+
88
+ return results.map(mapResource);
89
+ }
90
+
91
+ export async function getResourceBySlug(slug: string): Promise<Resource | null> {
92
+ const elevatedQuery = auth.elevate(items.query);
93
+ const { items: results } = await elevatedQuery(COLLECTION_ID)
94
+ .eq("slug", slug)
95
+ .eq("published", true)
96
+ .limit(1)
97
+ .find();
98
+
99
+ const item = results[0];
100
+ if (!item) return null;
101
+ return mapResource(item);
102
+ }
103
+
104
+ export async function queryRelatedResources(category: string, excludeId: string, limit = 3): Promise<Resource[]> {
105
+ const elevatedQuery = auth.elevate(items.query);
106
+ const { items: results } = await elevatedQuery(COLLECTION_ID)
107
+ .eq("published", true)
108
+ .eq("category", category)
109
+ .ne("_id", excludeId)
110
+ .descending("_createdDate")
111
+ .limit(limit)
112
+ .find();
113
+
114
+ return results.map(mapResource);
115
+ }
116
+ ```
117
+
118
+ Key details:
119
+ - `queryRelatedResources()` finds same-category items excluding the current one
120
+ - `fileType` normalized to uppercase for consistent badge display
121
+ - Sorted by `_createdDate` descending (newest first)
122
+ - Update `COLLECTION_ID` to match the exact collection name from the Wix dashboard (no namespace prefix for native collections)
123
+
124
+ ### 2. File Type Icon (`src/components/FileTypeIcon.astro`)
125
+
126
+ ```astro
127
+ ---
128
+ interface Props {
129
+ type: string;
130
+ class?: string;
131
+ }
132
+
133
+ const { type, class: className = "w-8 h-8" } = Astro.props;
134
+ const fileType = type.toUpperCase();
135
+
136
+ // File type colors are applied by the design skill's component styles
137
+ ---
138
+
139
+ <div class={className}>
140
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="w-full h-full">
141
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" />
142
+ <polyline points="14 2 14 8 20 8" />
143
+ <text x="12" y="17" text-anchor="middle" font-size="5" fill="currentColor" stroke="none" font-weight="bold">{fileType.slice(0, 4)}</text>
144
+ </svg>
145
+ </div>
146
+ ```
147
+
148
+ Key details:
149
+ - Color-coded by file type — red for PDF, blue for DOC, green for XLS, yellow for ZIP
150
+ - Falls back to neutral gray for unknown types
151
+ - File type label rendered inside the document icon SVG
152
+
153
+ ### 3. Resource Card (`src/components/ResourceCard.astro`)
154
+
155
+ ```astro
156
+ ---
157
+ import FileTypeIcon from "./FileTypeIcon.astro";
158
+
159
+ interface Props {
160
+ resource: {
161
+ title: string;
162
+ slug: string;
163
+ category: string;
164
+ fileType: string;
165
+ fileSize?: string;
166
+ coverImage?: string;
167
+ };
168
+ }
169
+
170
+ const { resource } = Astro.props;
171
+ ---
172
+
173
+ <a href={`/resources/${resource.slug}`}>
174
+ {resource.coverImage ? (
175
+ <div><img src={resource.coverImage} alt={resource.title} /></div>
176
+ ) : (
177
+ <div><FileTypeIcon type={resource.fileType} /></div>
178
+ )}
179
+ <div>
180
+ <div>
181
+ <span>{resource.fileType}</span>
182
+ {resource.fileSize && <span>{resource.fileSize}</span>}
183
+ </div>
184
+ <h3>{resource.title}</h3>
185
+ <p>{resource.category}</p>
186
+ </div>
187
+ </a>
188
+ ```
189
+
190
+ > **Styling note:** ResourceCard styling is created by the design skill. See `COMPONENT_PATTERNS.md` → Resource Card.
191
+
192
+ ### 4. Resource Listing Page (`src/pages/resources/index.astro`)
193
+
194
+ ```astro
195
+ ---
196
+ import Layout from "../../layouts/Layout.astro";
197
+ import ResourceCard from "../../components/ResourceCard.astro";
198
+ import CategoryFilter from "../../components/CategoryFilter.astro";
199
+ import { queryResources } from "../../lib/resources";
200
+
201
+ const activeCategory = Astro.url.searchParams.get("category");
202
+ const allResources = await queryResources();
203
+ const filtered = activeCategory
204
+ ? allResources.filter((r) => r.category === activeCategory)
205
+ : allResources;
206
+ const categories = [...new Set(allResources.map((r) => r.category).filter(Boolean))];
207
+ ---
208
+
209
+ <Layout title="Resources">
210
+ <main>
211
+ <div>
212
+ <h1>Resources</h1>
213
+ <p>Download guides, templates, and documents.</p>
214
+
215
+ <CategoryFilter categories={categories} activeCategory={activeCategory} basePath="/resources" />
216
+
217
+ <div>
218
+ {filtered.map((resource) => (
219
+ <ResourceCard resource={resource} />
220
+ ))}
221
+ </div>
222
+
223
+ {filtered.length === 0 && (
224
+ <p>No resources found.</p>
225
+ )}
226
+ </div>
227
+ </main>
228
+ </Layout>
229
+ ```
230
+
231
+ > Reuses the same `CategoryFilter.astro` component from the portfolio use case. If building both, no need to create it twice.
232
+
233
+ ### 5. Resource Detail Page (`src/pages/resources/[slug].astro`)
234
+
235
+ ```astro
236
+ ---
237
+ import Layout from "../../layouts/Layout.astro";
238
+ import ResourceCard from "../../components/ResourceCard.astro";
239
+ import FileTypeIcon from "../../components/FileTypeIcon.astro";
240
+ import { getResourceBySlug, queryRelatedResources } from "../../lib/resources";
241
+
242
+ const { slug } = Astro.params;
243
+ const resource = await getResourceBySlug(slug!);
244
+ if (!resource) return Astro.redirect("/404");
245
+
246
+ const related = await queryRelatedResources(resource.category, resource._id);
247
+
248
+ const date = resource._createdDate
249
+ ? new Date(resource._createdDate).toLocaleDateString("en-US", {
250
+ year: "numeric",
251
+ month: "long",
252
+ day: "numeric",
253
+ })
254
+ : "";
255
+ ---
256
+
257
+ <Layout title={resource.title}>
258
+ <main>
259
+ <div>
260
+ <a href="/resources">
261
+ &larr; Back to resources
262
+ </a>
263
+
264
+ <div>
265
+ <FileTypeIcon type={resource.fileType} />
266
+ <div>
267
+ <div>
268
+ <span>{resource.fileType}</span>
269
+ {resource.fileSize && (
270
+ <span>{resource.fileSize}</span>
271
+ )}
272
+ </div>
273
+ {date && <p>Added {date}</p>}
274
+ </div>
275
+ </div>
276
+
277
+ <h1>{resource.title}</h1>
278
+
279
+ {resource.coverImage && (
280
+ <div>
281
+ <img
282
+ src={resource.coverImage}
283
+ alt={resource.title}
284
+ />
285
+ </div>
286
+ )}
287
+
288
+ {resource.description && (
289
+ <article set:html={resource.description} />
290
+ )}
291
+
292
+ {resource.fileUrl && (
293
+ <a
294
+ href={resource.fileUrl}
295
+ download
296
+ >
297
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
298
+ Download {resource.fileType}
299
+ </a>
300
+ )}
301
+
302
+ {related.length > 0 && (
303
+ <section>
304
+ <h2>Related Resources</h2>
305
+ <div>
306
+ {related.map((r) => (
307
+ <ResourceCard resource={r} />
308
+ ))}
309
+ </div>
310
+ </section>
311
+ )}
312
+ </div>
313
+ </main>
314
+ </Layout>
315
+ ```
316
+
317
+ Key details:
318
+ - `<a download>` triggers browser download for the file
319
+ - Related resources query pulls same-category items, excluding the current one
320
+ - File type icon and badge prominently displayed
321
+
322
+ ## Seed with Images
323
+
324
+ After seeding resources via MCP, generate cover images following `../../shared/IMAGE_GENERATION.md` and `CMS_FOUNDATIONS.md` → "MCP Seeding with Images".
325
+
326
+ **Prompt template:**
327
+
328
+ ```
329
+ Cover image for [TITLE], a [FILE TYPE]. Abstract [BRAND AESTHETIC]. Color tones: [BRAND COLORS]. No text, no watermarks
330
+ ```
331
+
332
+ **Patch field:** `coverImage`
333
+
334
+ Example patch:
335
+
336
+ ```
337
+ CallWixSiteAPI: PATCH /wix-data/v2/items/{resourceId}
338
+ body: {
339
+ "dataCollectionId": "Resources",
340
+ "dataItem": {
341
+ "data": {
342
+ "coverImage": "<wixstatic-url>"
343
+ }
344
+ }
345
+ }
346
+ ```
347
+
348
+ ## Testing
349
+
350
+ 1. Create a "Resources" collection in the Wix dashboard → CMS with the schema above
351
+ 2. Add 4+ resources across 2+ categories with different file types (PDF, DOC, ZIP)
352
+ 3. Include `fileUrl` links (can be any downloadable URL for testing)
353
+ 4. Run `npx @wix/cli dev`
354
+ 5. `/resources` — shows all resources with category filters and file type badges
355
+ 6. Click a category — filters resources
356
+ 7. Click a resource — detail page with download button and related resources
@@ -0,0 +1,299 @@
1
+ # Recipe: Team / Staff Directory
2
+
3
+ Build a team directory using `@wix/data` — staff cards grouped by department with individual profile pages. Use for about us, our team, meet the staff, or any people directory.
4
+
5
+ > Read `CMS_FOUNDATIONS.md` first for shared patterns (service module, image resolution, elevation, MCP seeding).
6
+
7
+ ## Collection Schema
8
+
9
+ Create a collection in the Wix dashboard → CMS with these fields:
10
+
11
+ | Field | Type | Purpose |
12
+ |-------|------|---------|
13
+ | `name` | Text | Full name |
14
+ | `slug` | Text | URL-friendly identifier |
15
+ | `role` | Text | Job title or role |
16
+ | `department` | Text | Department or team (e.g., "Engineering", "Design") |
17
+ | `bio` | Rich Text | Bio or description (HTML) |
18
+ | `photo` | Image | Headshot (`wix:image://` — resolve with `media.getScaledToFillImageUrl()`) |
19
+ | `email` | Text | Contact email |
20
+ | `linkedIn` | URL | LinkedIn profile URL |
21
+ | `twitter` | URL | Twitter/X profile URL |
22
+ | `orderIndex` | Number | Manual sort order within department |
23
+
24
+ ## Files to Create
25
+
26
+ | File | Purpose |
27
+ |------|---------|
28
+ | `src/lib/team.ts` | Service module — queries, department grouping |
29
+ | `src/pages/team/index.astro` | Department-sectioned directory |
30
+ | `src/pages/team/[slug].astro` | Individual member profile |
31
+ | `src/components/TeamMemberCard.astro` | Photo, name, role, social icons |
32
+
33
+ ## Implementation
34
+
35
+ ### 1. Team Service Module (`src/lib/team.ts`)
36
+
37
+ ```typescript
38
+ import * as items from "@wix/wix-data-items-sdk";
39
+ import { auth } from "@wix/essentials";
40
+ import { media } from "@wix/sdk";
41
+
42
+ const COLLECTION_ID = "Team";
43
+
44
+ export interface TeamMember {
45
+ _id: string;
46
+ name: string;
47
+ slug: string;
48
+ role: string;
49
+ department: string;
50
+ bio?: string;
51
+ photo?: string;
52
+ email?: string;
53
+ linkedIn?: string;
54
+ twitter?: string;
55
+ orderIndex: number;
56
+ }
57
+
58
+ function resolvePhoto(url: string | undefined): string | undefined {
59
+ if (!url) return undefined;
60
+ return media.getScaledToFillImageUrl(url, 400, 400, {});
61
+ }
62
+
63
+ function mapMember(item: Record<string, any>): TeamMember {
64
+ return {
65
+ _id: item._id,
66
+ name: item.name ?? "",
67
+ slug: item.slug ?? "",
68
+ role: item.role ?? "",
69
+ department: item.department ?? "",
70
+ bio: item.bio,
71
+ photo: resolvePhoto(item.photo),
72
+ email: item.email,
73
+ linkedIn: item.linkedIn,
74
+ twitter: item.twitter,
75
+ orderIndex: item.orderIndex ?? 0,
76
+ };
77
+ }
78
+
79
+ export async function queryTeamMembers(): Promise<TeamMember[]> {
80
+ const elevatedQuery = auth.elevate(items.query);
81
+ const { items: results } = await elevatedQuery(COLLECTION_ID)
82
+ .ascending("orderIndex")
83
+ .limit(100)
84
+ .find();
85
+
86
+ return results.map(mapMember);
87
+ }
88
+
89
+ export async function getMemberBySlug(slug: string): Promise<TeamMember | null> {
90
+ const elevatedQuery = auth.elevate(items.query);
91
+ const { items: results } = await elevatedQuery(COLLECTION_ID)
92
+ .eq("slug", slug)
93
+ .limit(1)
94
+ .find();
95
+
96
+ const item = results[0];
97
+ if (!item) return null;
98
+ return mapMember(item);
99
+ }
100
+
101
+ export function groupByDepartment(members: TeamMember[]): Map<string, TeamMember[]> {
102
+ return members.reduce((map, member) => {
103
+ const dept = member.department || "Team";
104
+ if (!map.has(dept)) map.set(dept, []);
105
+ map.get(dept)!.push(member);
106
+ return map;
107
+ }, new Map<string, TeamMember[]>());
108
+ }
109
+ ```
110
+
111
+ Key details:
112
+ - `resolvePhoto()` uses 400x400 for square headshot crops
113
+ - `groupByDepartment()` returns a `Map` preserving insertion order — departments appear in the order of their first member
114
+ - Update `COLLECTION_ID` to match the exact collection name from the Wix dashboard (no namespace prefix for native collections)
115
+
116
+ ### 2. Team Member Card (`src/components/TeamMemberCard.astro`)
117
+
118
+ ```astro
119
+ ---
120
+ interface Props {
121
+ member: {
122
+ name: string;
123
+ slug: string;
124
+ role: string;
125
+ photo?: string;
126
+ email?: string;
127
+ linkedIn?: string;
128
+ twitter?: string;
129
+ };
130
+ }
131
+
132
+ const { member } = Astro.props;
133
+ ---
134
+
135
+ <a href={`/team/${member.slug}`}>
136
+ <div>
137
+ {member.photo ? (
138
+ <img src={member.photo} alt={member.name} />
139
+ ) : (
140
+ <div>{member.name.charAt(0)}</div>
141
+ )}
142
+ </div>
143
+ <h3>{member.name}</h3>
144
+ <p>{member.role}</p>
145
+ <div>
146
+ {member.email && (
147
+ <a href={`mailto:${member.email}`} onclick="event.stopPropagation()">Email</a>
148
+ )}
149
+ {member.linkedIn && (
150
+ <a href={member.linkedIn} target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">LinkedIn</a>
151
+ )}
152
+ {member.twitter && (
153
+ <a href={member.twitter} target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">Twitter</a>
154
+ )}
155
+ </div>
156
+ </a>
157
+ ```
158
+
159
+ > **Styling note:** TeamMemberCard styling is created by the design skill. See `COMPONENT_PATTERNS.md` → Team Member Card.
160
+
161
+ Key details:
162
+ - Inline SVG icons — no icon library dependency
163
+ - Fallback initial letter when no photo
164
+ - Social links use `onclick="event.stopPropagation()"` to prevent navigation to profile when clicking social icons
165
+
166
+ ### 3. Team Directory Page (`src/pages/team/index.astro`)
167
+
168
+ ```astro
169
+ ---
170
+ import Layout from "../../layouts/Layout.astro";
171
+ import TeamMemberCard from "../../components/TeamMemberCard.astro";
172
+ import { queryTeamMembers, groupByDepartment } from "../../lib/team";
173
+
174
+ const members = await queryTeamMembers();
175
+ const departments = groupByDepartment(members);
176
+ ---
177
+
178
+ <Layout title="Our Team">
179
+ <main>
180
+ <div>
181
+ <h1>Our Team</h1>
182
+
183
+ {[...departments.entries()].map(([dept, deptMembers]) => (
184
+ <section>
185
+ <h2>{dept}</h2>
186
+ <div>
187
+ {deptMembers.map((member) => (
188
+ <TeamMemberCard member={member} />
189
+ ))}
190
+ </div>
191
+ </section>
192
+ ))}
193
+
194
+ {members.length === 0 && (
195
+ <p>No team members found.</p>
196
+ )}
197
+ </div>
198
+ </main>
199
+ </Layout>
200
+ ```
201
+
202
+ ### 4. Member Profile Page (`src/pages/team/[slug].astro`)
203
+
204
+ ```astro
205
+ ---
206
+ import Layout from "../../layouts/Layout.astro";
207
+ import { getMemberBySlug } from "../../lib/team";
208
+
209
+ const { slug } = Astro.params;
210
+ const member = await getMemberBySlug(slug!);
211
+ if (!member) return Astro.redirect("/404");
212
+ ---
213
+
214
+ <Layout title={member.name}>
215
+ <main>
216
+ <div>
217
+ <a href="/team">
218
+ &larr; Back to team
219
+ </a>
220
+
221
+ <div>
222
+ {member.photo && (
223
+ <div>
224
+ <img
225
+ src={member.photo}
226
+ alt={member.name}
227
+ />
228
+ </div>
229
+ )}
230
+ <div>
231
+ <h1>{member.name}</h1>
232
+ <p>{member.role}</p>
233
+ {member.department && (
234
+ <p>{member.department}</p>
235
+ )}
236
+ <div>
237
+ {member.email && (
238
+ <a href={`mailto:${member.email}`}>
239
+ {member.email}
240
+ </a>
241
+ )}
242
+ {member.linkedIn && (
243
+ <a href={member.linkedIn} target="_blank" rel="noopener noreferrer">
244
+ LinkedIn
245
+ </a>
246
+ )}
247
+ {member.twitter && (
248
+ <a href={member.twitter} target="_blank" rel="noopener noreferrer">
249
+ Twitter
250
+ </a>
251
+ )}
252
+ </div>
253
+ </div>
254
+ </div>
255
+
256
+ {member.bio && (
257
+ <article set:html={member.bio} />
258
+ )}
259
+ </div>
260
+ </main>
261
+ </Layout>
262
+ ```
263
+
264
+ ## Seed with Images
265
+
266
+ > **Do not skip:** Team members without photos appear as initial-letter placeholders.
267
+ > Always ask the user if they want to generate headshot images before moving on.
268
+
269
+ After seeding team members via MCP, generate headshot images following `../../shared/IMAGE_GENERATION.md` and `CMS_FOUNDATIONS.md` → "MCP Seeding with Images".
270
+
271
+ **Prompt template:**
272
+
273
+ ```
274
+ Professional headshot portrait of [NAME], [ROLE] at [BUSINESS NAME]. [BRAND AESTHETIC]. Warm studio lighting, neutral background with [BRAND COLORS]. No text, no watermarks
275
+ ```
276
+
277
+ **Patch field:** `photo`
278
+
279
+ Example: after generating and importing the image, patch the team member item:
280
+
281
+ ```
282
+ CallWixSiteAPI: PATCH /wix-data/v2/items/{memberId}
283
+ body: {
284
+ "dataCollectionId": "Team",
285
+ "dataItem": {
286
+ "data": {
287
+ "photo": "<wixstatic-url>"
288
+ }
289
+ }
290
+ }
291
+ ```
292
+
293
+ ## Testing
294
+
295
+ 1. Create a "Team" collection in the Wix dashboard → CMS with the schema above
296
+ 2. Add 4+ members across 2+ departments, with photos and social links
297
+ 3. Run `npx @wix/cli dev`
298
+ 4. `/team` — shows members grouped by department
299
+ 5. Click a member — profile page with photo, bio, and social links
@@ -0,0 +1,42 @@
1
+ # Install a Wix app onto a site
2
+
3
+ Reference for the orchestrator. Invoked from `SKILL.md` Step 2 once per app entry across the loaded packs' `apps[*]`. Can't be a bash script — the install goes through the Wix MCP tool `CallWixSiteAPI`, not over the wire from the local shell.
4
+
5
+ ## Inputs
6
+
7
+ - `siteId` — from `wix.config.json`.
8
+ - `appName` — e.g. `wix-stores`, `wix-forms`, `wix-blog`. Resolved to `appDefId` via `<SKILL_ROOT>/references/commands/known-apps.json`. Unknown name → fail fast (`"Unknown app: {appName}. Known: [list]. Add it to references/commands/known-apps.json before retrying."`); do not guess.
9
+ - `mcpPrefix` — captured in Step 0 (the discovered Wix MCP prefix; see `<SKILL_ROOT>/references/shared/MCP_PREFIX.md`).
10
+
11
+ ## Call
12
+
13
+ Wrap in `date -u` captures so timing flows into `run.json.phases[]` as `{ phase: "app-install-{appName}", seconds: <duration> }`.
14
+
15
+ ```
16
+ {mcpPrefix}CallWixSiteAPI
17
+ siteId: {siteId}
18
+ url: https://www.wixapis.com/apps-installer-service/v1/app-instance/install
19
+ method: POST
20
+ body: (a JSON object — NOT a string)
21
+ {
22
+ "tenant": { "tenantType": "SITE", "id": "{siteId}" },
23
+ "appInstance": { "appDefId": "{appDefId}", "enabled": true }
24
+ }
25
+ reason: Install {appName} on the new headless site
26
+ sourceDocUrl: https://dev.wix.com/docs/api-reference/business-management/app-installation/skills/install-wix-apps
27
+ ```
28
+
29
+ The MCP tool requires explicit `url` / `method` / `body` / `reason` / `sourceDocUrl`. Do NOT pass `endpoint:`. Do NOT stringify `body` — pass it as a JSON object. (The Step 0 MCP bootstrap — see `<SKILL_ROOT>/references/commands/mcp-bootstrap.md` — preloads the `CallWixSiteAPI` schema so the orchestrator and subagents both see the right shape.)
30
+
31
+ ## Strict-then-recover
32
+
33
+ | Outcome | Action |
34
+ |---|---|
35
+ | 2xx | Done. |
36
+ | 4xx / 5xx with parseable body | Enter recover loop (max 1 retry): `{mcpPrefix}SearchWixRESTDocumentation` for `install app instance`, then `{mcpPrefix}ReadFullDocsMethodSchema` on the top match, then retry with the discovered shape. |
37
+ | Recovery succeeds | Append to `run.json.commandDrift[]`: `{ command: "install-app", primaryError: { status, body }, recoveredWith: { endpoint, bodyPatch }, suggestedFix: "Update references/commands/install-app.md body template" }`. |
38
+ | Both paths fail | Surface the original response body and the doc link to the user. Do not loop further. |
39
+
40
+ ## Why this is a reference doc, not a script
41
+
42
+ The body shape and the strict-then-recover ladder are the parts that need to stay frozen across runs. Encoding them in a markdown reference the orchestrator reads (instead of a slash command the orchestrator dispatches) keeps the source of truth inside the skill and removes the round-trip through a slash-command shim.
@@ -0,0 +1,5 @@
1
+ {
2
+ "wix-stores": "215238eb-22a5-4c36-9e7b-e7c08025e04e",
3
+ "wix-forms": "225dd912-7dea-4738-8688-4b8c6955ffc2",
4
+ "wix-blog": "14bcded7-0066-7c35-14d7-466cb3f09103"
5
+ }