@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,218 @@
1
+ # Reference: Blog Setup
2
+
3
+ Prerequisites, dependencies, blog service module, and astro config changes for the Wix Blog app integration.
4
+
5
+ ## Prerequisites
6
+
7
+ - A Wix Managed Headless project (has `wix.config.json` and `astro.config.mjs`)
8
+ - The **Wix Blog app** installed on the connected Wix site (via MCP after scaffolding, or installed via MCP if missing — see `BLOG_CONTENT.md` Step 0)
9
+ - At least one published blog post in the Wix dashboard
10
+
11
+ ## Package Installation
12
+
13
+ ```bash
14
+ npm install @wix/blog @wix/ricos @astrojs/rss @astrojs/sitemap
15
+ ```
16
+
17
+ ## Files to Create / Modify
18
+
19
+ | File | Action | Purpose |
20
+ |------|--------|---------|
21
+ | `astro.config.mjs` | Modify | Add `site` property and `sitemap()` integration |
22
+ | `src/lib/blog.ts` | Create | Blog service — queries posts, resolves categories/tags/media |
23
+ | `src/consts.ts` | Create | Site-wide constants (title, description) |
24
+ | `src/components/RicosViewer.tsx` | Create | React wrapper for `@wix/ricos` RicosViewer |
25
+
26
+ ---
27
+
28
+ ## 1. Astro Config Changes (`astro.config.mjs`)
29
+
30
+ Add the `site` property (required for RSS and sitemap) and the `sitemap()` integration:
31
+
32
+ ```javascript
33
+ // @ts-check
34
+ import { defineConfig } from "astro/config";
35
+ import sitemap from "@astrojs/sitemap";
36
+ import wix from "@wix/astro";
37
+ import wixPages from "@wix/astro-pages";
38
+
39
+ // https://astro.build/config
40
+ export default defineConfig({
41
+ site: "https://example.com",
42
+ integrations: [wix(), wixPages(), sitemap()]
43
+ });
44
+ ```
45
+
46
+ > Replace `"https://example.com"` with the actual site URL. The `site` property is required for `@astrojs/rss` and `@astrojs/sitemap` to generate correct URLs.
47
+
48
+ > `wix()` and `wixPages()` should already be in the config from project scaffolding. Only add `sitemap()` and the `site` property.
49
+
50
+ ---
51
+
52
+ ## 2. Site Constants (`src/consts.ts`)
53
+
54
+ ```typescript
55
+ // Place any global data in this file.
56
+ // You can import this data from anywhere in your site by using the `import` keyword.
57
+
58
+ export const SITE_TITLE = 'Astro Blog';
59
+ export const SITE_DESCRIPTION = 'Welcome to my website!';
60
+ ```
61
+
62
+ > Update `SITE_TITLE` and `SITE_DESCRIPTION` to match the user's site.
63
+
64
+ ---
65
+
66
+ ## 3. RicosViewer React Wrapper (`src/components/RicosViewer.tsx`)
67
+
68
+ A thin React wrapper around `@wix/ricos` for use in Astro pages with `client:only="react"`.
69
+
70
+ ```tsx
71
+ import { quickStartViewerPlugins, RicosViewer } from '@wix/ricos';
72
+ import '@wix/ricos/css/all-plugins-viewer.css';
73
+
74
+ const plugins = quickStartViewerPlugins();
75
+
76
+ export default function RicosContentViewer({ content }: { content: any }) {
77
+ if (!content) return null;
78
+ return (
79
+ <div className="ricos-content">
80
+ <RicosViewer content={content} plugins={plugins} />
81
+ </div>
82
+ );
83
+ }
84
+ ```
85
+
86
+ Key details:
87
+ - `quickStartViewerPlugins()` is initialized at module level (once, not per render) — provides full content-type support (links, tables, galleries, embeds, etc.)
88
+ - The CSS import is bundled by Vite into the client chunk
89
+ - No key renaming needed — `@wix/ricos` accepts camelCase keys from the `@wix/blog` SDK directly
90
+ - Used in Astro pages as `<RicosViewer client:only="react" content={post.richContent} />`
91
+ - The `.ricos-content` wrapper div provides a CSS hook for theme color overrides — the Ricos library CSS hardcodes `color: rgb(0, 0, 0)` on paragraph and list elements, which is invisible on dark themes
92
+
93
+ ---
94
+
95
+ ## 4. Blog Service Module (`src/lib/blog.ts`)
96
+
97
+ This service module handles all Wix Blog SDK calls, resolving categories, tags, and media references into ready-to-use data.
98
+
99
+ ```typescript
100
+ import { posts, categories, tags } from "@wix/blog";
101
+ import { media } from "@wix/sdk";
102
+
103
+ export interface BlogPost {
104
+ slug: string;
105
+ title: string;
106
+ excerpt: string;
107
+ coverImageUrl?: string;
108
+ date: string;
109
+ pubDate: Date;
110
+ category?: string;
111
+ richContent: any;
112
+ tags: Array<{ label: string; slug: string }>;
113
+ }
114
+
115
+ export async function queryBlogPosts(limit?: number): Promise<BlogPost[]> {
116
+ let query = posts
117
+ .queryPosts({ fieldsets: ["RICH_CONTENT", "CONTENT_TEXT"] })
118
+ .descending("firstPublishedDate");
119
+
120
+ if (limit) query = query.limit(limit);
121
+
122
+ const { items } = await query.find();
123
+
124
+ return Promise.all(
125
+ items.map(async (item) => {
126
+ const resolvedCategories = await Promise.all(
127
+ (item.categoryIds || []).map(async (id) => {
128
+ const { category } = await categories.getCategory(id);
129
+ return category!;
130
+ })
131
+ );
132
+
133
+ const resolvedTags = await Promise.all(
134
+ (item.tagIds || []).map(async (id) => {
135
+ const tag = await tags.getTag(id);
136
+ return { label: tag.label!, slug: tag.slug! };
137
+ })
138
+ );
139
+
140
+ const imageUrl = item.media?.wixMedia?.image
141
+ ? media.getImageUrl(item.media.wixMedia.image).url
142
+ : undefined;
143
+
144
+ const pubDate = new Date(item.firstPublishedDate ?? "");
145
+
146
+ return {
147
+ slug: item.slug!,
148
+ title: item.title!,
149
+ excerpt: item.excerpt ?? "",
150
+ coverImageUrl: imageUrl,
151
+ date: pubDate.toLocaleDateString("en-us", {
152
+ year: "numeric",
153
+ month: "long",
154
+ day: "numeric",
155
+ }),
156
+ pubDate,
157
+ category: resolvedCategories[0]?.label,
158
+ richContent: item.richContent,
159
+ tags: resolvedTags,
160
+ };
161
+ })
162
+ );
163
+ }
164
+
165
+ export async function getPostBySlug(slug: string): Promise<BlogPost | null> {
166
+ const { items } = await posts
167
+ .queryPosts({ fieldsets: ["RICH_CONTENT", "CONTENT_TEXT"] })
168
+ .eq("slug", slug)
169
+ .find();
170
+
171
+ const item = items[0];
172
+ if (!item) return null;
173
+
174
+ const resolvedCategories = await Promise.all(
175
+ (item.categoryIds || []).map(async (id) => {
176
+ const { category } = await categories.getCategory(id);
177
+ return category!;
178
+ })
179
+ );
180
+
181
+ const resolvedTags = await Promise.all(
182
+ (item.tagIds || []).map(async (id) => {
183
+ const tag = await tags.getTag(id);
184
+ return { label: tag.label!, slug: tag.slug! };
185
+ })
186
+ );
187
+
188
+ const imageUrl = item.media?.wixMedia?.image
189
+ ? media.getImageUrl(item.media.wixMedia.image).url
190
+ : undefined;
191
+
192
+ const pubDate = new Date(item.firstPublishedDate ?? "");
193
+
194
+ return {
195
+ slug: item.slug!,
196
+ title: item.title!,
197
+ excerpt: item.excerpt ?? "",
198
+ coverImageUrl: imageUrl,
199
+ date: pubDate.toLocaleDateString("en-us", {
200
+ year: "numeric",
201
+ month: "long",
202
+ day: "numeric",
203
+ }),
204
+ pubDate,
205
+ category: resolvedCategories[0]?.label,
206
+ richContent: item.richContent,
207
+ tags: resolvedTags,
208
+ };
209
+ }
210
+ ```
211
+
212
+ Key details:
213
+ - `categories.getCategory(id)` returns `{ category }` (envelope) — destructure it
214
+ - `tags.getTag(id)` returns the `BlogTag` directly — do NOT destructure as `{ tag }`
215
+ - `media.getImageUrl(ref).url` resolves Wix media references to real URLs
216
+ - `getPostBySlug` returns `null` for missing posts — pages must handle this with a redirect
217
+ - `queryBlogPosts()` sorts by `firstPublishedDate` descending (newest first)
218
+ - `RICH_CONTENT` fieldset is required to get renderable content for `RicosViewer`
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: blog-implementer
3
+ description: "Implements blog vertical via Wix Blog app — @wix/blog SDK, @wix/ricos rich content, RSS/sitemap. Scopes: seed, components, pages. Extends references/shared/IMPLEMENTER.md."
4
+ ---
5
+
6
+ # Blog Implementer
7
+
8
+ Extends `references/shared/IMPLEMENTER.md`. Read that file first for phase routing, MCP prefix, site.json read pattern, return contract, style conventions, and common failure modes.
9
+
10
+ ## Scope routing
11
+
12
+ | Scope | Phase | Reference |
13
+ |-------|-------|-----------|
14
+ | `seed` | Seed (post seeding via MCP with Ricos content) | `./BLOG_CONTENT.md` |
15
+ | `components` | Components (blog service module, RicosViewer, consts, astro.config sitemap) | `./BLOG_SETUP.md` |
16
+ | `pages` | Pages (listing, detail, RSS, BlogPost layout, home contribution) | `./BLOG_PAGES.md` |
17
+
18
+ Cover images are generated by the shared image agent (`image-phase-2-entity` scope) AFTER `seed` completes — not by this agent.
19
+
20
+ ## Files this vertical creates / contributes
21
+
22
+ See `<SKILL_ROOT>/references/verticals/blog.md` frontmatter.
23
+
24
+ ## Blog-specific failure modes
25
+
26
+ | Wrong | Right |
27
+ |---|---|
28
+ | `import { items } from "@wix/data"` for blog queries | `import { posts } from "@wix/blog"` — use the Blog SDK |
29
+ | `<article set:html={post.content} />` | `<RicosViewer client:only="react" content={post.richContent} />` — content is Ricos format |
30
+ | Skip `wixMetadata` on `[...slug].astro` | Required for Wix page routing + SEO |
31
+ | Query posts without `RICH_CONTENT` fieldset | Always request `RICH_CONTENT` or `post.richContent` is undefined |
32
+ | Scoped `<style>` for RicosViewer overrides | `<style is:global>` — React islands don't inherit scoped Astro styles |
@@ -0,0 +1,373 @@
1
+ # CMS Foundations — Shared Patterns for `@wix/data`
2
+
3
+ Core patterns used by all CMS use cases: service module template, `@wix/data` queries, image resolution, elevated access, MCP seeding, and rich-text (Ricos) rendering.
4
+
5
+ > **Import note (read first).** Page code in this plugin uses `import * as items from "@wix/wix-data-items-sdk"` rather than the documented `import { items } from "@wix/data"`. The Wix-headless docs still show the `@wix/data` form, but `@wix/data` 1.0.448 dropped the `items` re-export — only sub-namespaces (`backups`, `collections`, `permissions`, …) remain, and the documented form fails the build with `'items' is not exported by '@wix/data'`. The actual `items` API (with `query`, `insert`, `update`, `remove`, `bulkInsert`, etc.) lives in `@wix/wix-data-items-sdk`, which `@wix/data` depends on transitively. Importing from there directly works on every current `@wix/data` version. The cms vertical pack adds `@wix/wix-data-items-sdk` to the install list so it's always present (`references/verticals/cms.md`). Use the wix-data-items-sdk import everywhere.
6
+
7
+ ## Rendering Ricos rich-text fields
8
+
9
+ Wix CMS stores `RICH_TEXT` / `RICH_CONTENT` fields as **Ricos JSON** — a structured node tree (PARAGRAPH, HEADING, BULLETED_LIST, etc.), not HTML. The dashboard's rich-text editor reads and writes this format.
10
+
11
+ For SSR Astro pages (about, faq, portfolio, team, resource), import the seeded `renderRicos` util from `src/utils/ricos.ts`. The util is shipped by `seed-utilities.sh` (copied from `<SKILL_ROOT>/shared-utilities/ricos.ts` during Setup), so it's already on disk — do NOT inline a Ricos walker in your page.
12
+
13
+ ```astro
14
+ ---
15
+ import * as items from "@wix/wix-data-items-sdk";
16
+ import { auth } from "@wix/essentials";
17
+ import { renderRicos } from "../utils/ricos";
18
+
19
+ const elevatedQuery = auth.elevate(items.query);
20
+ const { items: results } = await elevatedQuery("about-content")
21
+ .limit(1)
22
+ .find();
23
+ const about = results[0];
24
+ const bodyHtml = renderRicos(about?.body);
25
+ ---
26
+
27
+ <article class="prose">
28
+ <h1>{about?.heading}</h1>
29
+ <div set:html={bodyHtml} />
30
+ </article>
31
+ ```
32
+
33
+ The util covers the common subset (PARAGRAPH, HEADING 1-6, BULLETED_LIST / ORDERED_LIST / LIST_ITEM, BLOCKQUOTE, DIVIDER + BOLD / ITALIC / UNDERLINE / LINK decorations). Anything outside that set renders defensively as a `<p>` with the raw text — never throws.
34
+
35
+ > **Why not @wix/ricos?** The blog vertical uses `@wix/ricos`'s React `RicosViewer` as a client island because blog posts can carry the full Ricos feature set (galleries, polls, embedded media). For static CMS pages, that's ~80kb of React for paragraphs and lists — overkill. Use the seeded SSR walker instead.
36
+
37
+ > **Do NOT `set:html={item.body}` directly.** That ships JSON-encoded text into the page (e.g. `[object Object]` or `{"nodes":...}`). Always go through `renderRicos`.
38
+
39
+ > **Critical Rules — Read Before Starting**
40
+ > 1. **Collection IDs have NO namespace** — user collections use just the name (e.g., `"Projects"`). Only Wix App collections use `<namespace>/<name>`. Verify via MCP: `GET /wix-data/v2/collections?fields=id`.
41
+ > 2. **SDK query pattern** — `items.query("CollectionId").find()`. There is no `items.queryDataItems()` in the SDK.
42
+ > 3. **`auth.elevate` on every query** — without it, restricted collections silently return no items.
43
+ > 4. **CMS only for user collections** — use `@wix/blog` for blog posts, `@wix/stores` for products, `@wix/forms` for form submissions.
44
+
45
+ ## Prerequisites
46
+
47
+ - `@wix/data` package installed (collected by features orchestrator — do NOT install independently)
48
+ - `@wix/essentials` package installed (for elevation)
49
+ - A data collection created in the Wix dashboard → CMS section
50
+ - No special Wix app installation needed — `@wix/data` works with any Wix Managed Headless project
51
+
52
+ ## Collection ID Format
53
+
54
+ Native (user-created) CMS collections use **just the collection name** — no namespace prefix.
55
+
56
+ Example: if the collection is called `Projects`, the collection ID is simply `"Projects"`.
57
+
58
+ Only Wix App collections (e.g., `Members/PublicData`, `Locations/Locations`) use a `<namespace>/<name>` format. User-created collections never use a namespace.
59
+
60
+ > **How to verify**: Call `GET /wix-data/v2/collections?fields=id` via MCP and use the exact `id` value from the response. Never guess — the dashboard name may differ from the ID.
61
+
62
+ ## Quick Reference — Inline Query (Simple Pages)
63
+
64
+ For pages that just need to list items from a collection:
65
+
66
+ ```astro
67
+ ---
68
+ import * as items from "@wix/wix-data-items-sdk";
69
+ import { auth } from "@wix/essentials";
70
+
71
+ // Always elevate queries for permission safety
72
+ const elevatedQuery = auth.elevate(items.query);
73
+ const { items: results } = await elevatedQuery("MyCollection")
74
+ .ascending("sortField")
75
+ .limit(50)
76
+ .find();
77
+
78
+ // Fields are directly on each item (NOT item.data.field)
79
+ const myItems = results.map((item) => ({
80
+ name: item.name, // correct
81
+ // name: item.data.name // wrong — REST pattern, not SDK
82
+ }));
83
+ ---
84
+ ```
85
+
86
+ > **Common mistake:** `items.queryDataItems(...)` does NOT exist in the
87
+ > `@wix/data` SDK. The REST API uses `/items/query` with a `dataCollectionId`
88
+ > body field, but the SDK uses `items.query("collectionId")` — a chainable
89
+ > QueryBuilder. Do not confuse REST and SDK patterns.
90
+
91
+ ## Service Module Template
92
+
93
+ Every CMS use case follows the same `src/lib/{usecase}.ts` pattern — a typed interface and query functions that pages import.
94
+
95
+ ```typescript
96
+ import * as items from "@wix/wix-data-items-sdk";
97
+ import { auth } from "@wix/essentials";
98
+ import { media } from "@wix/sdk";
99
+
100
+ // -- Collection ID (use exact name from Wix dashboard — no namespace for native collections) --
101
+ const COLLECTION_ID = "collection-name";
102
+
103
+ // -- Typed interface matching collection fields --
104
+ export interface CollectionItem {
105
+ _id: string;
106
+ title: string;
107
+ slug: string;
108
+ // ...add fields matching your collection schema
109
+ coverImage?: string;
110
+ }
111
+
112
+ // -- Image resolution helper --
113
+ function resolveImage(wixImageUrl: string | undefined, width = 800, height = 600): string | undefined {
114
+ if (!wixImageUrl) return undefined;
115
+ return media.getScaledToFillImageUrl(wixImageUrl, width, height, {});
116
+ }
117
+
118
+ // -- Query all items --
119
+ // Wrap every Wix SDK await in try/catch. If the query throws at SSR, an empty
120
+ // array keeps the page renderable instead of crashing it. (Unguarded SSR
121
+ // awaits truncate Astro's response stream mid-body — nav renders, then blank.)
122
+ export async function queryItems(): Promise<CollectionItem[]> {
123
+ try {
124
+ const elevatedQuery = auth.elevate(items.query);
125
+ const { items: results } = await elevatedQuery(COLLECTION_ID)
126
+ .ascending("orderIndex")
127
+ .limit(50)
128
+ .find();
129
+
130
+ return results.map((item) => ({
131
+ ...item,
132
+ coverImage: resolveImage(item.coverImage),
133
+ })) as CollectionItem[];
134
+ } catch (err) {
135
+ console.error(`[cms:${COLLECTION_ID}] query failed:`, err);
136
+ return [];
137
+ }
138
+ }
139
+
140
+ // -- Get single item by slug --
141
+ export async function getItemBySlug(slug: string): Promise<CollectionItem | null> {
142
+ try {
143
+ const elevatedQuery = auth.elevate(items.query);
144
+ const { items: results } = await elevatedQuery(COLLECTION_ID)
145
+ .eq("slug", slug)
146
+ .limit(1)
147
+ .find();
148
+
149
+ const item = results[0];
150
+ if (!item) return null;
151
+
152
+ return {
153
+ ...item,
154
+ coverImage: resolveImage(item.coverImage),
155
+ } as CollectionItem;
156
+ } catch (err) {
157
+ console.error(`[cms:${COLLECTION_ID}] getItemBySlug failed:`, err);
158
+ return null;
159
+ }
160
+ }
161
+ ```
162
+
163
+ Key details:
164
+ - `auth.elevate(items.query)` wraps the query for restricted collections — always use this by default since collection permissions vary
165
+ - `media.getScaledToFillImageUrl(url, w, h, {})` resolves `wix:image://` URLs to sized CDN URLs
166
+ - Sort by `orderIndex` (ascending) for manually ordered content, or `_createdDate` (descending) for chronological
167
+ - The interface must match the collection fields — check the dashboard, don't guess
168
+
169
+ ## Multi-Image Resolution
170
+
171
+ For collections with image arrays (e.g., gallery images):
172
+
173
+ ```typescript
174
+ function resolveImages(imageUrls: string[] | undefined, width = 800, height = 600): string[] {
175
+ if (!imageUrls || imageUrls.length === 0) return [];
176
+ return imageUrls
177
+ .map((url) => media.getScaledToFillImageUrl(url, width, height, {}))
178
+ .filter(Boolean);
179
+ }
180
+ ```
181
+
182
+ ## Category Filtering Pattern
183
+
184
+ Many use cases filter by category via URL search params (server-rendered, no client JS):
185
+
186
+ ```astro
187
+ ---
188
+ const activeCategory = Astro.url.searchParams.get("category");
189
+ const allItems = await queryItems();
190
+ const filtered = activeCategory
191
+ ? allItems.filter((item) => item.category === activeCategory)
192
+ : allItems;
193
+ const categories = [...new Set(allItems.map((item) => item.category).filter(Boolean))];
194
+ ---
195
+
196
+ <nav>
197
+ <a href="?" class:list={[!activeCategory && "active"]}>All</a>
198
+ {categories.map((cat) => (
199
+ <a
200
+ href={`?category=${encodeURIComponent(cat)}`}
201
+ class:list={[activeCategory === cat && "active"]}
202
+ >{cat}</a>
203
+ ))}
204
+ </nav>
205
+ ```
206
+
207
+ > **Styling note:** Category filter pill styling is created by the design skill. See `COMPONENT_PATTERNS.md` → Category Filter.
208
+
209
+ ## MCP Seeding (Conditional)
210
+
211
+ If Wix MCP tools are available, check if the collection has data and seed sample items if empty. This is **conditional** — only attempt if MCP is connected.
212
+
213
+ 1. Query the collection — if items exist, skip seeding
214
+ 2. If empty, create the collection and insert sample items via MCP (see templates below)
215
+ 3. Design sample data that matches the business type from the functional plan
216
+
217
+ > MCP seeding is optional. If MCP tools are not available, instruct the user to add content via the Wix dashboard → CMS section.
218
+
219
+ ### Create collection (if it doesn't exist)
220
+
221
+ ```
222
+ <prefix>CallWixSiteAPI: POST https://www.wixapis.com/wix-data/v2/collections
223
+ body: {
224
+ "collection": {
225
+ "id": "about-content",
226
+ "displayName": "About Content",
227
+ "fields": [
228
+ { "key": "heading", "displayName": "Heading", "type": "TEXT" },
229
+ { "key": "body", "displayName": "Body", "type": "RICH_TEXT" },
230
+ { "key": "image", "displayName": "Image", "type": "IMAGE" }
231
+ ]
232
+ }
233
+ }
234
+ ```
235
+
236
+ ### Insert item WITH field data
237
+
238
+ **This is the critical step that must include actual field values.** Creating an item without populating the `data` object results in an empty record — the collection schema exists but the item has no content.
239
+
240
+ ```
241
+ <prefix>CallWixSiteAPI: POST https://www.wixapis.com/wix-data/v2/items
242
+ body: {
243
+ "dataCollectionId": "about-content",
244
+ "dataItem": {
245
+ "data": {
246
+ "heading": "Our Story",
247
+ "body": "<p>Founded on a belief that...</p><p>We source the finest...</p>"
248
+ }
249
+ }
250
+ }
251
+ ```
252
+
253
+ The response returns the created item's `_id` — collect these for the Phase 1 return contract.
254
+
255
+ **Every text field must be populated in the `data` object.** Do not create items with empty `data: {}` and expect Phase 2 or the image agent to fill in text fields — they only handle their own scope (pages and images respectively).
256
+
257
+ For FAQ items, include both `question` and `answer` plus `sortOrder`:
258
+
259
+ ```
260
+ <prefix>CallWixSiteAPI: POST https://www.wixapis.com/wix-data/v2/items
261
+ body: {
262
+ "dataCollectionId": "faq",
263
+ "dataItem": {
264
+ "data": {
265
+ "question": "What is your return policy?",
266
+ "answer": "We accept returns within 30 days of purchase...",
267
+ "sortOrder": 1
268
+ }
269
+ }
270
+ }
271
+ ```
272
+
273
+ ### Verify inserts with a live query (mandatory)
274
+
275
+ After inserting all items, **query each collection once** and confirm every field you sent is present in the stored `data`. A POST without errors does NOT prove the content persisted — the API has accepted insert bodies with missing fields before, and the failure is invisible until a human opens the page.
276
+
277
+ ```
278
+ <prefix>CallWixSiteAPI: POST https://www.wixapis.com/wix-data/v2/items/query
279
+ body: { "dataCollectionId": "<collection>" }
280
+ ```
281
+
282
+ For every returned item, confirm its `data` object contains every text field you POSTed (`heading`, `body`, `question`, `answer`, etc.). If any field is missing:
283
+
284
+ - Do NOT return `status: "complete"`.
285
+ - Re-insert the item (a DELETE then POST is safest — PUT replaces the whole record) and re-verify.
286
+ - If re-insert fails twice, return `status: "partial"` with `errors: [{code: "SEED_FIELD_MISSING", collection: "<c>", itemId: "<id>", missingFields: [...]}]`.
287
+
288
+ A CMS seeder can return `complete` for an about-content item, then Image Phase 2 silently wipes its `heading` + `body` via a destructive full-record PUT. The verify-after-insert step here plus the read-merge-PUT rule in the images agent makes that class of data loss unreachable.
289
+
290
+ ### MCP Seeding with Images
291
+
292
+ For use cases with image fields (`photo`, `coverImage`, `galleryImages`),
293
+ follow `../../shared/IMAGE_GENERATION.md` (Steps 1–2) for Wix AI image
294
+ generation and Wix Media import. Image generation is MCP-authenticated
295
+ and always available — do not ask the user for credentials.
296
+
297
+ **Workflow:**
298
+
299
+ 1. Seed all items first (text fields only, no images) using `POST /wix-data/v2/items` as shown in § "Insert item WITH field data" above. Every text field must have a value in the `data` object — empty items cause "Content coming soon" placeholder pages.
300
+ 2. Run the verify-after-insert query (see § "Verify inserts with a live query" above) before touching images.
301
+ 3. Generate images via Wix AI (IMAGE_GENERATION.md Steps 1–2) using the prompt templates from each use-case reference
302
+ 4. Attach each image by reading the existing item, merging, and writing the whole record back via PUT. Do NOT use PATCH here — the endpoint expects a JsonPatch `fieldModifications` array and rejects the `{dataItem:{data}}` body. Do NOT PUT with just `{image}` — PUT replaces the entire record and erases heading/body.
303
+
304
+ ```
305
+ # Step a: read the existing item
306
+ <prefix>CallWixSiteAPI: POST https://www.wixapis.com/wix-data/v2/items/query
307
+ body: {
308
+ "dataCollectionId": "CollectionName",
309
+ "query": { "filter": { "_id": { "$in": ["{itemId}"] } } }
310
+ }
311
+
312
+ # Step b: merge image into existing data and PUT the full record
313
+ <prefix>CallWixSiteAPI: PUT https://www.wixapis.com/wix-data/v2/items/{itemId}
314
+ body: {
315
+ "dataCollectionId": "CollectionName",
316
+ "dataItem": {
317
+ "id": "{itemId}",
318
+ "data": { ...existingData, "{imageField}": "<wixstatic-url>" }
319
+ }
320
+ }
321
+ ```
322
+
323
+ `...existingData` must include every non-system field from step a (system fields `_id`, `_owner`, `_createdDate`, `_updatedDate` don't need to be echoed). Skipping the merge wipes seeded text fields and ships an empty About page.
324
+
325
+ **Prompt templates** — each use-case reference defines its own prompt template (see the "Seed with Images" section in TEAM_DIRECTORY.md, PORTFOLIO.md, RESOURCE_LIBRARY.md). Always incorporate brand context from the discovery/design phases.
326
+
327
+ **Constraints:**
328
+ - Never block the main flow on image failures — text data is already seeded
329
+ - Runware image URLs are short-lived — import to Wix Media immediately after generation
330
+ - If image generation or import fails for a single item, skip that item and continue with others
331
+ - If all generation fails (credits exhausted, MCP errors), write the sidecar with `Status: partial` and proceed — but always attempt first
332
+ - FAQ_KNOWLEDGE_BASE has no image fields — skip image generation for FAQ use cases
333
+
334
+ ## Return Results
335
+
336
+ Emit a structured JSON block at the end of your completion message per `../../shared/RETURN_CONTRACT.md`. Do NOT write sidecar files.
337
+
338
+ ```json
339
+ {
340
+ "status": "complete",
341
+ "phase": "cms-seed",
342
+ "scope": "seed-seed",
343
+ "summary": "Created {N} collections; seeded {M} items; verified every field persisted",
344
+ "data": {
345
+ "collections": [
346
+ {
347
+ "name": "<collection-slug>",
348
+ "itemIds": ["<id>", "..."],
349
+ "fields": ["<field>", "..."],
350
+ "storedFields": ["<field>", "..."],
351
+ "sampleValues": { "<field>": "<short sample value>" },
352
+ "imageField": "<field name or null>"
353
+ }
354
+ ]
355
+ },
356
+ "files": [],
357
+ "errors": []
358
+ }
359
+ ```
360
+
361
+ - `storedFields` MUST match the real keys seen in the verify-after-insert query response's `data` object (see § "Verify inserts with a live query"). Downstream pages agents compare against this — if you return `fields: ["heading", "body"]` but only `heading` was actually stored, pages render empty bodies.
362
+ - `sampleValues` is a single example item's field-to-short-string map. Lets downstream agents spot-check that content is real without another MCP round-trip. Truncate rich-text bodies to the first ~80 characters.
363
+ - For collections without image fields (e.g., FAQ), set `imageField: null`.
364
+ - The JSON block MUST be the last content in your message.
365
+
366
+ ## Testing
367
+
368
+ 1. Create a data collection in the Wix dashboard → CMS
369
+ 2. Add fields matching the use case schema (see the specific use case reference)
370
+ 3. Add at least 2–3 items with all fields populated, including `slug` and `published` (if applicable)
371
+ 4. Run `npx @wix/cli dev`
372
+ 5. Navigate to the listing page — should show items
373
+ 6. Click an item — should navigate to the detail page