@wix/agent-skills 1.14.0 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/package.json +1 -1
- package/skills/README.md +23 -0
- package/skills/wix-app/SKILL.md +10 -2
- package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +326 -0
- package/skills/wix-app/references/CODE_QUALITY.md +1 -0
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +124 -115
- package/skills/wix-app/references/DASHBOARD_PAGE.md +3 -0
- package/skills/wix-app/references/DATA_COLLECTION.md +5 -3
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +25 -9
- package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
- package/skills/wix-app/references/STORES_VERSIONING.md +9 -211
- package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
- package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
- package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
- package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
- package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
- package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
- package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
- package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
- package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
- package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
- package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
- package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +5 -0
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +151 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
- package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +57 -0
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +23 -105
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
- package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +18 -16
- package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
- package/skills/wix-app/references/stores/CATEGORIES.md +22 -0
- package/skills/wix-app/references/stores/GET_PRODUCT.md +99 -0
- package/skills/wix-app/references/stores/INVENTORY.md +37 -0
- package/skills/wix-app/references/stores/QUERY.md +87 -0
- package/skills/wix-app/references/stores/WRITE.md +55 -0
- package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
- package/skills/wix-auth/SKILL.md +12 -0
- package/skills/wix-auth/references/device-flow.md +140 -0
- package/skills/wix-docs/SKILL.md +188 -0
- package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
- package/skills/wix-docs/references/EXTRACTING.md +120 -0
- package/skills/wix-headless/SKILL.md +89 -130
- package/skills/wix-headless/entry/bootstrap.mjs +93 -0
- package/skills/wix-headless/entry/skill.md +76 -0
- package/skills/wix-headless/references/AI_FEATURES.md +178 -0
- package/skills/wix-headless/references/CAPABILITIES.md +86 -0
- package/skills/wix-headless/references/DISCOVERY.md +34 -56
- package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
- package/skills/wix-headless/references/FEEDBACK.md +129 -0
- package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
- package/skills/wix-headless/references/SDK_HANDOFF.md +99 -0
- package/skills/wix-headless/references/SEED.md +45 -187
- package/skills/wix-headless/references/SETUP.md +32 -103
- package/skills/wix-headless/references/astro.md +98 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +213 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
- package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
- package/skills/wix-headless/references/inline-recipes/setup-bookings.md +232 -0
- package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
- package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
- package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
- package/skills/wix-headless/references/inline-recipes/setup-online-store.md +192 -0
- package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +155 -0
- package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +73 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +197 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +136 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
- package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
- package/skills/wix-headless/references/managed/CONNECT.md +74 -0
- package/skills/wix-headless/references/managed/CREATE.md +130 -0
- package/skills/wix-headless/references/managed/DEPLOYMENT.md +79 -0
- package/skills/wix-headless/references/non-astro.md +59 -0
- package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
- package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +15 -0
- package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
- package/skills/wix-headless/references/stripe/DEPLOYMENT.md +71 -0
- package/skills/wix-manage/SKILL.md +29 -3
- package/skills/wix-manage/references/analytics/query-site-analytics.md +298 -0
- package/skills/wix-manage/references/app-installation/install-wix-apps.md +3 -0
- package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
- package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +6 -5
- package/skills/wix-manage/references/bookings/create-course-service.md +30 -5
- package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +299 -0
- package/skills/wix-manage/references/cms/cms-schema-management.md +6 -0
- package/skills/wix-manage/references/get-paid/how-to-setup-wix-payments.md +30 -7
- package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +517 -0
- package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +218 -0
- package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
- package/skills/wix-manage/references/sites/site-import.md +270 -0
- package/skills/wix-manage/references/stores/create-product-from-image.md +8 -6
- package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +57 -0
- package/skills/wix-vibe-headless/SKILL.md +142 -0
- package/skills/wix-vibe-headless/platforms/README.md +22 -0
- package/skills/wix-vibe-headless/platforms/base44.md +142 -0
- package/skills/wix-vibe-headless/platforms/generic.md +87 -0
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
- package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +157 -0
- package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
- package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +217 -0
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
- package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
- package/skills/wix-vibe-headless/references/events/wix-events-browse.js +136 -0
- package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
- package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
- package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +223 -0
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
- package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
- package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
- package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
- package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
- package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +164 -0
- package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
- package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +146 -0
- package/skills/wix-headless/references/BUILD-astro.md +0 -253
- package/skills/wix-headless/references/BUILD-own-build.md +0 -167
- package/skills/wix-headless/references/BUILD.md +0 -105
- package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
- package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
- package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
- package/skills/wix-headless/references/PLAN-connect.md +0 -19
- package/skills/wix-headless/references/PLAN-create.md +0 -17
- package/skills/wix-headless/references/PLAN.md +0 -92
- package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
- package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
- package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
- package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
- package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
- package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
- package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
- package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
- package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
- package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
- package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
- package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
- package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
- package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
- package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
- package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
- package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
- package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
- package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
- package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
- package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
- package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
- package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
- package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
- package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
- package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
- package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
- package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
- package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
- package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
- package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
- package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
- package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
- package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
- package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
- package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
- package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
- package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
- package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
- package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
- package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
- package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
- package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
- package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
- package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
- package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
- package/skills/wix-headless/references/astro/templates/global.css +0 -288
- package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
- package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
- package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
- package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
- package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
- package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
- package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
- package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
- package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
- package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
- package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
- package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
- package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
- package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
- package/skills/wix-headless/references/bookings/FLOW.md +0 -246
- package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
- package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
- package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
- package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
- package/skills/wix-headless/references/commands/known-apps.json +0 -6
- package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
- package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
- package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
- package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
- package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
- package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
- package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
- package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
- package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
- package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
- package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
- package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
- package/skills/wix-headless/references/seed-recipes.md +0 -49
- package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
- package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
- package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
- package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
- package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
- package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
- package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
- package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
- package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
- package/skills/wix-headless/references/shared/STYLING.md +0 -140
- package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
- package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
- package/skills/wix-headless/references/verticals/_schema.json +0 -74
- package/skills/wix-headless/references/verticals/_schema.md +0 -95
- package/skills/wix-headless/references/verticals/blog.md +0 -31
- package/skills/wix-headless/references/verticals/bookings.md +0 -41
- package/skills/wix-headless/references/verticals/cms.md +0 -30
- package/skills/wix-headless/references/verticals/ecom.md +0 -25
- package/skills/wix-headless/references/verticals/forms.md +0 -26
- package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
- package/skills/wix-headless/references/verticals/stores.md +0 -33
- package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
- package/skills/wix-headless/scripts/compose.mjs +0 -520
- package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
- package/skills/wix-headless/scripts/flatten.sh +0 -61
- package/skills/wix-headless/scripts/generate-images.mjs +0 -242
- package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -154
- package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
- package/skills/wix-headless/scripts/scaffold.sh +0 -139
- package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
- package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
- package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
- package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
- package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
|
|
2
|
+
# Wix CMS Skill
|
|
3
|
+
|
|
4
|
+
> **Source files (in this skill):** the shared transport `references/shared/wix-client.js` and this vertical's `references/cms/wix-cms.js`. Copy **both** into your app's `src/rest/` side by side — the helper does `import { wixApiRequest } from "./wix-client.js"`, so they must land in the same folder.
|
|
5
|
+
|
|
6
|
+
Builds a real, client-only Wix CMS-backed app. The browser talks to Wix Data directly
|
|
7
|
+
over a public `WIX_CLIENT_ID` to read and write items in the site's data collections.
|
|
8
|
+
Never mock data; never hand-build API URLs — always go through the helpers, which call
|
|
9
|
+
the official Wix Data endpoints.
|
|
10
|
+
|
|
11
|
+
## When to use
|
|
12
|
+
- User wants to display Wix CMS / Content Manager content (a collection of posts,
|
|
13
|
+
tutorials, recipes, team members, listings, FAQs, etc.) on a site.
|
|
14
|
+
- Replacing placeholder/mock content with live Wix Data items.
|
|
15
|
+
- Adding list pages, detail pages, category/tag filtering, or free-text search over an
|
|
16
|
+
existing Wix data collection.
|
|
17
|
+
- Wiring a public form (contact, RSVP, review, signup) that writes a row into a collection.
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
1. A Wix site with **a data collection already created and populated** (this skill does
|
|
21
|
+
NOT provision collections — it reads/writes existing ones). The merchant creates
|
|
22
|
+
collections, fields, and items in the Wix dashboard (CMS / Content Manager).
|
|
23
|
+
2. The site's public headless **`WIX_CLIENT_ID`**, provided in the handoff prompt (the
|
|
24
|
+
Wix Business Manager surfaces a copyable prompt with the id filled in — see
|
|
25
|
+
the router `SKILL.md`). Paste it into `src/rest/wix-client.js` in place of the placeholder. It is
|
|
26
|
+
a buyer-facing credential (it only mints anonymous visitor tokens), **not** a secret,
|
|
27
|
+
so hardcoding/committing it is fine.
|
|
28
|
+
3. **Collection permissions** must match what you're doing. This skill runs as an
|
|
29
|
+
anonymous visitor, so a call only works if the collection grants that action to
|
|
30
|
+
"Anyone": Read for listing content, Insert for a public form. Update/Delete are
|
|
31
|
+
almost always admin- or author-only and will fail for a visitor. The site owner sets
|
|
32
|
+
these in the Wix dashboard (CMS → collection → Permissions). This is a **separate Wix
|
|
33
|
+
setup step the user completes** — out of this skill's scope. If a read/insert fails
|
|
34
|
+
with a permission error (HTTP 403) before that's set, that's expected; flag it and
|
|
35
|
+
continue.
|
|
36
|
+
4. You need each collection's **collection ID** (its name, e.g. `Tutorials`) and its
|
|
37
|
+
**field keys** (e.g. `title`, `publishDate`). Read field keys off a fetched item, or
|
|
38
|
+
from the collection schema (see "Beyond the snippets").
|
|
39
|
+
|
|
40
|
+
## The API (copy as-is; do not re-derive it)
|
|
41
|
+
This skill ships only the REST layer — no UI components. Build the UI however the project
|
|
42
|
+
wants; wire it to these two snippets. Copy them into the app (e.g. `src/api/`) and only
|
|
43
|
+
adjust import paths:
|
|
44
|
+
- `src/rest/wix-client.js` — visitor-token mint/refresh + transport. Set `WIX_CLIENT_ID`
|
|
45
|
+
to the id from the prompt (replace the `<YOUR-CLIENT-ID>` placeholder). The visitor
|
|
46
|
+
refresh token is persisted to localStorage; do not re-mint anonymously per load.
|
|
47
|
+
- `src/rest/wix-cms.js` — exports:
|
|
48
|
+
- **Read:** `queryDataItems`, `getDataItem`, `getDataItemBy`, `countDataItems`
|
|
49
|
+
- **Write:** `insertDataItem`, `updateDataItem`, `removeDataItem`
|
|
50
|
+
|
|
51
|
+
The Data Item shape, the per-collection **permissions model**, and the **filter/sort
|
|
52
|
+
syntax** are documented as JSDoc comments at the top of `wix-cms.js`. Read them before
|
|
53
|
+
building the UI — read helpers return the item's flat `data` payload (which always
|
|
54
|
+
includes `_id`), and writes are bound by collection permissions.
|
|
55
|
+
|
|
56
|
+
## How to wire it (UI is the project's choice)
|
|
57
|
+
- **Content list** — `queryDataItems(collectionId, { filter?, sort?, limit?, cursor? })`
|
|
58
|
+
for the listing; render fields directly off each returned item (`item.title`, etc.).
|
|
59
|
+
Pass the returned `nextCursor` back as `cursor` to load the next page. Define
|
|
60
|
+
`filter`/`sort` on the first request only — cursor follow-ups reuse the original query.
|
|
61
|
+
- **Detail page** — route by the item's `_id` and call `getDataItem(collectionId, itemId)`;
|
|
62
|
+
returns null on miss → show a not-found state, never invent an item. For human-readable
|
|
63
|
+
URLs, add a slug-like field to the collection and route via
|
|
64
|
+
`getDataItemBy(collectionId, "slug", slugFromUrl)`.
|
|
65
|
+
- **Filter & search** — pass a `filter` to `queryDataItems` using the operators documented
|
|
66
|
+
in `wix-cms.js` (`$eq`, `$in`, `$gte`, `$startsWith`, `$hasSome`, `$and`/`$or`, …). For a
|
|
67
|
+
simple text search, `{ title: { $startsWith: term } }`; for richer free-text/fuzzy search
|
|
68
|
+
across fields, see "Beyond the snippets" (Search Data Items).
|
|
69
|
+
- **Public form** — on submit, `insertDataItem(collectionId, { name, email, message })`
|
|
70
|
+
(field keys must match the collection). Requires the collection's Insert permission to be
|
|
71
|
+
"Anyone". Show success/failure from the resolved/thrown result; never fake a success.
|
|
72
|
+
- **Edit / delete (admin/author flows)** — `updateDataItem(collectionId, itemId, data)`
|
|
73
|
+
(⚠ full replace — fetch + merge first to preserve other fields) and
|
|
74
|
+
`removeDataItem(collectionId, itemId)`. These need Update/Delete granted to the caller,
|
|
75
|
+
which visitors normally don't have — expect them to fail unless the collection is opened up.
|
|
76
|
+
- **Empty state** — if `countDataItems(collectionId)` is 0, show an empty state telling
|
|
77
|
+
the user to add items in their Wix dashboard. Never invent items.
|
|
78
|
+
|
|
79
|
+
## Hard rules (do not violate)
|
|
80
|
+
- ✅ Read/write ONLY through the helpers in `wix-cms.js` (which call the official Wix Data
|
|
81
|
+
`/wix-data/v2/items` endpoints).
|
|
82
|
+
- ❌ Never hand-build Wix Data URLs or invent endpoint paths.
|
|
83
|
+
- ❌ Never mock data — render live Wix Data items or the empty state.
|
|
84
|
+
- ❌ Never invent fields, reviews, ratings, or content not present in the collection.
|
|
85
|
+
- ✅ Set `WIX_CLIENT_ID` from the prompt's value (public client id — safe to hardcode).
|
|
86
|
+
- ✅ Use the item's `_id` as the route key and as `itemId` for get/update/remove.
|
|
87
|
+
- ✅ `updateDataItem` REPLACES the whole item — fetch with `getDataItem`, merge your
|
|
88
|
+
changes, then pass the full object, or use Patch Data Item (see below) for partial edits.
|
|
89
|
+
- ✅ Treat permission errors (HTTP 403) as a configuration step, not a code bug: tell the
|
|
90
|
+
user which permission to grant in the dashboard. Writes throw on failure — don't swallow
|
|
91
|
+
the error and show a fake success.
|
|
92
|
+
|
|
93
|
+
## Beyond the snippets
|
|
94
|
+
The snippets cover the common CMS paths (list, detail, filter, count, insert, update,
|
|
95
|
+
remove). If you hit a use case they don't cover, make the call yourself with
|
|
96
|
+
`wixApiRequest` — but look up the exact endpoint, HTTP method, and request body in the
|
|
97
|
+
**official Wix API reference** first; never guess:
|
|
98
|
+
- CMS / Data Items API reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items.md
|
|
99
|
+
- Data Items sample flows: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/sample-flows.md
|
|
100
|
+
- **Partial update** (change some fields, keep the rest): Patch Data Item —
|
|
101
|
+
https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/patch-data-item.md
|
|
102
|
+
- **Upsert** (insert or update by id): Save Data Item —
|
|
103
|
+
https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/save-data-item.md
|
|
104
|
+
- **Bulk** insert/update/save/remove (many items in one call):
|
|
105
|
+
https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items.md
|
|
106
|
+
- **Free-text / fuzzy search** across fields: Search Data Items —
|
|
107
|
+
https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/search-data-items.md
|
|
108
|
+
- **Aggregations** (counts/averages grouped by a field): Aggregate Data Items —
|
|
109
|
+
https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/aggregate-data-items.md
|
|
110
|
+
- **Distinct values** (e.g. all categories for a filter menu): Query Distinct Values —
|
|
111
|
+
https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/query-distinct-values.md
|
|
112
|
+
- **Referenced items** (expand a reference field beyond the inline limit): Query Referenced
|
|
113
|
+
Data Items — https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/query-referenced-data-items.md
|
|
114
|
+
- **Collection schema / field keys & types**: Get Data Collection —
|
|
115
|
+
https://dev.wix.com/docs/api-reference/business-solutions/cms/collection-management/data-collections/get-data-collection.md
|
|
116
|
+
- **Member-gated & user-generated content** → the **members** vertical
|
|
117
|
+
(`references/members/INSTRUCTIONS.md`). A collection whose permissions are `read: Anyone`,
|
|
118
|
+
`insert: Site Member`, `update/remove: Site Member Author` gives you the classic pattern: anyone
|
|
119
|
+
reads, only logged-in members write, and each member edits only their own. Sign the member in with
|
|
120
|
+
custom login (on your own UI), then `insertDataItem` runs as the member and Wix stamps the item's
|
|
121
|
+
`_owner` automatically — so a **"my items"** view is just
|
|
122
|
+
`queryDataItems(collectionId, { filter: { _owner: <memberId> } })`, and author-only
|
|
123
|
+
`updateDataItem`/`removeDataItem` are enforced server-side. (This skill never provisions the
|
|
124
|
+
collection — the owner creates it with those permissions in the dashboard.)
|
|
125
|
+
**Prefer Wix for member-generated content, and keep one feature's data and identity together.**
|
|
126
|
+
Content that belongs to the Wix site (likes, reviews, submissions) is best kept in a Wix collection
|
|
127
|
+
via these helpers, keyed on the Wix member's server-stamped `_owner`. What breaks is a *split*
|
|
128
|
+
feature — the row stored in one place while the member is identified from the Wix session elsewhere
|
|
129
|
+
(or filtered by some other `created_by`/user id): the two ids won't match, so ownership filters
|
|
130
|
+
miss. Keep them on one side; for Wix-backed rows that's `_owner`.
|
|
131
|
+
|
|
132
|
+
Keep the snippets as the default for everything they already do; reach for the API
|
|
133
|
+
reference only for the gap.
|
|
134
|
+
|
|
135
|
+
## Point the user to their dashboard
|
|
136
|
+
In some cases, users need to access the Wix dashboard in order to edit the CMS content for their site. To facilitate this, provide the user with deep links directly to the relevant dashboard pages. For CMS data those pages are:
|
|
137
|
+
- **Collections & items** — `https://manage.wix.com/dashboard/{metaSiteId}/wix-cms` (`Dashboard → CMS`) → **Create Collection**, then open a collection to add items.
|
|
138
|
+
- **Permissions** — no separate deep link; in the same CMS area, open the collection → **More Actions → Permissions & Privacy**. For the headless app to work anonymously, set **Show content** to *Everyone* (visitor reads) and, for a public form, **Collect content** to *Everyone* (visitor inserts). Update/Delete stay admin-only.
|
|
139
|
+
|
|
140
|
+
Substitute the site's `metaSiteId` to complete the links (you have it from the handoff / `ListWixSites`). Include the in-dashboard navigation as a fallback.
|
|
141
|
+
|
|
142
|
+
## Verification checklist (before declaring done)
|
|
143
|
+
- [ ] `WIX_CLIENT_ID` set to the prompt's value (not the `<YOUR-CLIENT-ID>` placeholder)
|
|
144
|
+
- [ ] Visitor token persists across reload (same anonymous visitor, no re-mint per load)
|
|
145
|
+
- [ ] `queryDataItems` returns live items; pagination via `nextCursor` loads more
|
|
146
|
+
- [ ] Detail page uses the item's `_id` (or a slug field via `getDataItemBy`) and shows a
|
|
147
|
+
not-found state on miss — no invented item
|
|
148
|
+
- [ ] Filter/sort produce the expected subset (operators match the field types)
|
|
149
|
+
- [ ] Public form `insertDataItem` succeeds only when Insert is "Anyone"; on a 403 the user
|
|
150
|
+
is told to grant the permission — no fake success
|
|
151
|
+
- [ ] Update is treated as a full replace (fetch + merge), so no fields are silently dropped
|
|
152
|
+
- [ ] Empty state shown when `countDataItems` is 0
|
|
153
|
+
- [ ] No mock data anywhere; no hand-built Wix Data URLs
|
|
154
|
+
- [ ] Told the user at least once that they can continue setting up their content in the dashboard and provided deep links.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { wixApiRequest } from "./wix-client.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wix CMS (Wix Data) — REST helpers for reading and writing data items in site data collections.
|
|
5
|
+
*
|
|
6
|
+
* COLLECTIONS & PERMISSIONS: A collection (e.g. "Tutorials") is identified by its
|
|
7
|
+
* dataCollectionId — the name set in the dashboard, NOT a GUID. Field keys are also set
|
|
8
|
+
* in the dashboard. This skill runs as an ANONYMOUS VISITOR — a call only succeeds if the
|
|
9
|
+
* collection grants that action to "Anyone" (Read for listing, Insert for forms, etc.).
|
|
10
|
+
* Permission-denied throws HTTP 403 by design. Set permissions in Wix dashboard → CMS → Permissions.
|
|
11
|
+
* https://dev.wix.com/docs/api-reference/business-solutions/cms/collection-management/data-permissions/data-permissions-object.md
|
|
12
|
+
*
|
|
13
|
+
* Data Item — every read helper returns the item's `data` payload:
|
|
14
|
+
* _id {string} — GUID (route key, itemId for get/update/remove),
|
|
15
|
+
* _createdDate, _updatedDate {string} — ISO 8601 (use { "$date": "..." } in filters),
|
|
16
|
+
* _ownerId {string}, ...fields — collection field values keyed by field key
|
|
17
|
+
* Full reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/data-item-object.md
|
|
18
|
+
*
|
|
19
|
+
* FILTERS & SORT (Wix API Query Language):
|
|
20
|
+
* filter: { field: value } for equality; { field: { $op: value } } for operators:
|
|
21
|
+
* $eq $ne $gt $gte $lt $lte $in $nin $startsWith $exists $isEmpty $hasSome $hasAll
|
|
22
|
+
* Combine with $and / $or / $not. Dates: { "$date": "2026-05-05T00:00:00.000Z" }.
|
|
23
|
+
* sort: [{ fieldName: "publishDate", order: "DESC" }]
|
|
24
|
+
* Full reference: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/data-retrieval/about-the-wix-api-query-language.md
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Query one page of items from a collection.
|
|
29
|
+
* Reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/query-data-items.md
|
|
30
|
+
*
|
|
31
|
+
* Pass `nextCursor` back as `cursor` to load the next page. Define `filter`/`sort`/`fields`
|
|
32
|
+
* on the FIRST request only — on cursor follow-ups Wix reuses the original query and
|
|
33
|
+
* ignores them (so this helper omits them when a cursor is supplied).
|
|
34
|
+
*
|
|
35
|
+
* @param {string} dataCollectionId Collection name (e.g. "Tutorials").
|
|
36
|
+
* @param {{
|
|
37
|
+
* filter?: object,
|
|
38
|
+
* sort?: Array<{ fieldName: string, order?: "ASC"|"DESC" }>,
|
|
39
|
+
* limit?: number,
|
|
40
|
+
* cursor?: string,
|
|
41
|
+
* fields?: string[],
|
|
42
|
+
* includeReferences?: Array<{ field: string, limit?: number }>
|
|
43
|
+
* }} [options]
|
|
44
|
+
* @returns {Promise<{ items: object[], nextCursor: string|null }>} items are `data` payloads (each includes `_id`).
|
|
45
|
+
*/
|
|
46
|
+
export async function queryDataItems(dataCollectionId, { filter, sort, limit = 100, cursor, fields, includeReferences } = {}) {
|
|
47
|
+
const query = {
|
|
48
|
+
...(cursor
|
|
49
|
+
? {}
|
|
50
|
+
: {
|
|
51
|
+
...(filter ? { filter } : {}),
|
|
52
|
+
...(sort ? { sort } : {}),
|
|
53
|
+
...(fields ? { fields } : {}),
|
|
54
|
+
}),
|
|
55
|
+
cursorPaging: cursor ? { limit, cursor } : { limit },
|
|
56
|
+
};
|
|
57
|
+
const res = await wixApiRequest("/wix-data/v2/items/query", {
|
|
58
|
+
method: "POST",
|
|
59
|
+
body: {
|
|
60
|
+
dataCollectionId,
|
|
61
|
+
query,
|
|
62
|
+
...(includeReferences ? { includeReferences } : {}),
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
items: (res?.dataItems ?? []).map((d) => d.data),
|
|
67
|
+
nextCursor: res?.pagingMetadata?.cursors?.next ?? null,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get a single item by its `_id`. Returns the `data` payload, or null if not found
|
|
73
|
+
* (or not readable by an anonymous visitor — see the permissions note up top).
|
|
74
|
+
* Reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/get-data-item.md
|
|
75
|
+
*
|
|
76
|
+
* @param {string} dataCollectionId
|
|
77
|
+
* @param {string} itemId The item's `_id`.
|
|
78
|
+
* @returns {Promise<object|null>}
|
|
79
|
+
*/
|
|
80
|
+
export async function getDataItem(dataCollectionId, itemId) {
|
|
81
|
+
try {
|
|
82
|
+
const res = await wixApiRequest(`/wix-data/v2/items/${encodeURIComponent(itemId)}`, {
|
|
83
|
+
method: "GET",
|
|
84
|
+
query: { dataCollectionId },
|
|
85
|
+
});
|
|
86
|
+
return res?.dataItem?.data ?? null;
|
|
87
|
+
} catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the first item whose `fieldKey` equals `value`. Use for slug-style routing —
|
|
94
|
+
* Wix Data has no native get-by-slug, so detail pages keyed off a human-readable field
|
|
95
|
+
* (e.g. a "slug" or "handle" field) resolve through this. Returns the `data` payload or null.
|
|
96
|
+
* Built on Query Data Items: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/query-data-items.md
|
|
97
|
+
*
|
|
98
|
+
* @param {string} dataCollectionId
|
|
99
|
+
* @param {string} fieldKey Field to match (e.g. "slug").
|
|
100
|
+
* @param {unknown} value Value to match.
|
|
101
|
+
* @returns {Promise<object|null>}
|
|
102
|
+
*/
|
|
103
|
+
export async function getDataItemBy(dataCollectionId, fieldKey, value) {
|
|
104
|
+
const { items } = await queryDataItems(dataCollectionId, { filter: { [fieldKey]: value }, limit: 1 });
|
|
105
|
+
return items[0] ?? null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Count items in a collection matching an optional filter. Use for empty-state logic
|
|
110
|
+
* (0 → prompt the user to add items in their Wix dashboard) and result counts.
|
|
111
|
+
* Reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/count-data-items.md
|
|
112
|
+
*
|
|
113
|
+
* @param {string} dataCollectionId
|
|
114
|
+
* @param {object} [filter] Same filter syntax as queryDataItems.
|
|
115
|
+
* @returns {Promise<number>}
|
|
116
|
+
*/
|
|
117
|
+
export async function countDataItems(dataCollectionId, filter) {
|
|
118
|
+
const res = await wixApiRequest("/wix-data/v2/items/count", {
|
|
119
|
+
method: "POST",
|
|
120
|
+
body: { dataCollectionId, ...(filter ? { filter } : {}) },
|
|
121
|
+
});
|
|
122
|
+
return res?.totalCount ?? 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Insert a new item (e.g. a public form submission). The collection's Insert permission
|
|
127
|
+
* must be "Anyone" for this to succeed as a visitor. Returns the inserted `data` payload
|
|
128
|
+
* (including the assigned `_id`). Throws on failure (e.g. permission denied, validation).
|
|
129
|
+
* Reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/insert-data-item.md
|
|
130
|
+
*
|
|
131
|
+
* @param {string} dataCollectionId
|
|
132
|
+
* @param {object} data Field-keyed values, e.g. { name, email, message }. Omit `_id`
|
|
133
|
+
* to let Wix assign one; supply `_id` only for a custom GUID.
|
|
134
|
+
* @returns {Promise<object>} The inserted item's `data` payload.
|
|
135
|
+
*/
|
|
136
|
+
export async function insertDataItem(dataCollectionId, data) {
|
|
137
|
+
const res = await wixApiRequest("/wix-data/v2/items", {
|
|
138
|
+
method: "POST",
|
|
139
|
+
body: { dataCollectionId, dataItem: { data } },
|
|
140
|
+
});
|
|
141
|
+
const inserted = res?.dataItem?.data;
|
|
142
|
+
if (!inserted) throw new Error(`Insert into "${dataCollectionId}" failed (no item returned).`);
|
|
143
|
+
return inserted;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Update (REPLACE) an existing item by `_id`. Returns the updated `data` payload. Throws
|
|
148
|
+
* if the item doesn't exist or the visitor lacks Update permission (usually admin/author only).
|
|
149
|
+
* Reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/update-data-item.md
|
|
150
|
+
*
|
|
151
|
+
* ⚠ This is a FULL REPLACE: the new `data` overwrites the whole item, and any field NOT
|
|
152
|
+
* included is dropped. To change a few fields, fetch the item first (getDataItem), spread
|
|
153
|
+
* it, then pass the merged object — or use Patch Data Item for a partial change:
|
|
154
|
+
* https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/patch-data-item.md
|
|
155
|
+
*
|
|
156
|
+
* @param {string} dataCollectionId
|
|
157
|
+
* @param {string} itemId The item's `_id`.
|
|
158
|
+
* @param {object} data The complete new field set.
|
|
159
|
+
* @returns {Promise<object>} The updated item's `data` payload.
|
|
160
|
+
*/
|
|
161
|
+
export async function updateDataItem(dataCollectionId, itemId, data) {
|
|
162
|
+
const res = await wixApiRequest(`/wix-data/v2/items/${encodeURIComponent(itemId)}`, {
|
|
163
|
+
method: "PUT",
|
|
164
|
+
body: { dataCollectionId, dataItem: { id: itemId, data: { ...data, _id: itemId } } },
|
|
165
|
+
});
|
|
166
|
+
const updated = res?.dataItem?.data;
|
|
167
|
+
if (!updated) throw new Error(`Update of "${itemId}" in "${dataCollectionId}" failed (no item returned).`);
|
|
168
|
+
return updated;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Remove an item by `_id`. Irreversible. Returns the removed `data` payload. Throws if the
|
|
173
|
+
* visitor lacks Delete permission (usually admin/author only).
|
|
174
|
+
* Reference: https://dev.wix.com/docs/api-reference/business-solutions/cms/data-items/remove-data-item.md
|
|
175
|
+
*
|
|
176
|
+
* @param {string} dataCollectionId
|
|
177
|
+
* @param {string} itemId The item's `_id`.
|
|
178
|
+
* @returns {Promise<object|null>} The removed item's `data` payload.
|
|
179
|
+
*/
|
|
180
|
+
export async function removeDataItem(dataCollectionId, itemId) {
|
|
181
|
+
const res = await wixApiRequest(`/wix-data/v2/items/${encodeURIComponent(itemId)}`, {
|
|
182
|
+
method: "DELETE",
|
|
183
|
+
query: { dataCollectionId },
|
|
184
|
+
});
|
|
185
|
+
return res?.dataItem?.data ?? null;
|
|
186
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
|
|
2
|
+
# Wix Events Skill
|
|
3
|
+
|
|
4
|
+
> **Source files (in this skill):** the shared transport `references/shared/wix-client.js` and the helper file(s) you need from `references/events/`. All helpers import from `"./wix-client.js"`, so copy them into the same folder (e.g. `src/rest/`).
|
|
5
|
+
>
|
|
6
|
+
> | Need | Copy |
|
|
7
|
+
> |---|---|
|
|
8
|
+
> | Event listing + detail (always) | `wix-events-browse.js` |
|
|
9
|
+
> | RSVP, ticketing, registration | `wix-events-registration.js` |
|
|
10
|
+
|
|
11
|
+
Builds a real, client-only Wix Events site. The browser talks to Wix directly over a
|
|
12
|
+
public `WIX_CLIENT_ID`. Never mock events; never hand-build registration or payment URLs —
|
|
13
|
+
register via the RSVP/ticketing APIs, and complete paid tickets on the official Wix-hosted
|
|
14
|
+
ticket form.
|
|
15
|
+
|
|
16
|
+
## When to use
|
|
17
|
+
- User wants an events site over Wix Events & Tickets, or asks to "connect Wix Events".
|
|
18
|
+
- Replacing placeholder/mock events with live Wix data.
|
|
19
|
+
- Adding event listings, an event detail page, RSVP, or ticket purchase over existing,
|
|
20
|
+
published Wix events.
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
1. A Wix site with **Wix Events & Tickets installed and events already published** (this skill
|
|
24
|
+
does NOT create events — it's read-only over them). Selling **paid** tickets also needs a
|
|
25
|
+
Wix premium plan + a configured payment method; **free** events and RSVP events work without.
|
|
26
|
+
2. The site's public headless **`WIX_CLIENT_ID`**, provided in the handoff prompt (the Wix
|
|
27
|
+
Business Manager surfaces a copyable prompt with the id filled in — see the router `SKILL.md`). Paste
|
|
28
|
+
it into `src/rest/wix-client.js` in place of the placeholder. It is a visitor-facing
|
|
29
|
+
credential (it only mints anonymous visitor tokens), **not** a secret, so hardcoding/
|
|
30
|
+
committing it is fine.
|
|
31
|
+
3. For paid tickets the buyer completes payment on the **Wix-hosted ticket form** (the redirect
|
|
32
|
+
target of `getTicketCheckoutUrl`). The deployed app domain may need to be allow-listed on the
|
|
33
|
+
OAuth client for that page to return cleanly — a **separate Wix setup the user completes
|
|
34
|
+
later**, out of this skill's scope. If the return fails before that's done, that's expected;
|
|
35
|
+
flag it and continue.
|
|
36
|
+
|
|
37
|
+
## The API (copy as-is; do not re-derive it)
|
|
38
|
+
This skill ships only the REST layer — no UI components. Build the events UI however the
|
|
39
|
+
project wants; wire it to these two snippets. Copy them into the app (e.g. `src/api/`) and only
|
|
40
|
+
adjust import paths:
|
|
41
|
+
- `src/rest/wix-client.js` — visitor-token mint/refresh + transport. Set `WIX_CLIENT_ID` to the
|
|
42
|
+
id from the prompt (replace the `<YOUR-CLIENT-ID>` placeholder). The visitor refresh token is
|
|
43
|
+
persisted to localStorage and IS the identity of the visitor's ticket reservation/cart — do
|
|
44
|
+
not re-mint anonymously per load.
|
|
45
|
+
- `src/rest/wix-events-browse.js` — **Browse & discovery:**
|
|
46
|
+
`queryEvents`, `getEventBySlug`, `countUpcomingEvents`, `queryEventCategories`, `listEventsByCategory`
|
|
47
|
+
- `src/rest/wix-events-registration.js` — **RSVP & ticketing:**
|
|
48
|
+
`createRsvp`, `queryTicketDefinitions`, `reserveTickets`, `getTicketCheckoutUrl`, `checkoutTickets`
|
|
49
|
+
|
|
50
|
+
The `Event`, `TicketDefinition`, and `RSVP`/`Order` shapes are documented as JSDoc comments at
|
|
51
|
+
the top of each helper file. Read the relevant file(s) before building the UI — they describe
|
|
52
|
+
the key fields and link to the full API reference for anything not shown.
|
|
53
|
+
|
|
54
|
+
## How to wire it (UI is the project's choice)
|
|
55
|
+
- **Event grid** — `queryEvents()` lists live (UPCOMING/STARTED) events, soonest first. Render
|
|
56
|
+
`title`, `mainImage.url`, `dateAndTimeSettings.formatted.dateAndTime`, `location.name`, and
|
|
57
|
+
`shortDescription`. Use `offset`/`nextOffset` from the result to page. Link each card by `slug`.
|
|
58
|
+
- **Event detail** — `getEventBySlug(slug)`; returns null on miss — show a not-found state, never
|
|
59
|
+
invent an event.
|
|
60
|
+
- **Description fields:** `event.shortDescription` is a **plain string** (safe teaser). The full
|
|
61
|
+
`event.description` is **Ricos rich content** — an object shaped `{ nodes: [...] }`, **not a string**.
|
|
62
|
+
Render it with a Ricos viewer (`@wix/ricos`) or walk `nodes` to extract text; **never** call string
|
|
63
|
+
methods (`.split`/`.slice`/`.substring`) on it — that crashes the page. When you only need text, use
|
|
64
|
+
`shortDescription`.
|
|
65
|
+
- Branch the registration UI on `event.registration.type`:
|
|
66
|
+
- `"RSVP"` → render the RSVP form (fields from `event.form.controls`).
|
|
67
|
+
- `"TICKETING"` → render the ticket picker.
|
|
68
|
+
- `"EXTERNAL"` → link out to `event.registration.external.url`.
|
|
69
|
+
- `"NONE"` → details only, no registration.
|
|
70
|
+
Only `registration.status` values starting `OPEN_` accept new registrations; otherwise show the
|
|
71
|
+
closed state.
|
|
72
|
+
- **Categories (optional)** — `queryEventCategories()` for a filter menu (`counts.assignedEventsCount`
|
|
73
|
+
per category); `listEventsByCategory(categoryId)` to list a category's events (same card fields
|
|
74
|
+
and paging as `queryEvents`).
|
|
75
|
+
- **RSVP** — `createRsvp(eventId, { firstName, lastName, email, status, additionalGuestNames?, extraFields? })`.
|
|
76
|
+
`status` defaults to `"YES"`; only offer `"NO"` when `registration.rsvp.responseType` is
|
|
77
|
+
`"YES_AND_NO"`. If the event is full with a waitlist enabled, the returned RSVP comes back with
|
|
78
|
+
status `"WAITLIST"` — tell the guest. Completes fully client-side; no redirect.
|
|
79
|
+
- **Ticketing** — show tickets, reserve, then complete on the hosted form:
|
|
80
|
+
1. `queryTicketDefinitions(eventId)` → render each ticket's `name`, price (`pricing.fixedPrice.amount`
|
|
81
|
+
+ `currency` for standard tickets; `free` boolean for free tickets; `pricing.minPrice` for
|
|
82
|
+
donation/"pay what you want"; `pricing.pricingOptions.options` for tiered), and filter on
|
|
83
|
+
`saleStatus === "SALE_STARTED"`. The endpoint already returns only non-hidden, available tickets.
|
|
84
|
+
2. `reserveTickets([{ ticketDefinitionId, quantity, guestPrice?, pricingOptionId? }])` → holds the
|
|
85
|
+
tickets; returns `{ id, expirationDate }`. Show a countdown to `expirationDate` if you like.
|
|
86
|
+
3. `window.location.href = getTicketCheckoutUrl(event, reservation.id)` → the Wix-hosted ticket
|
|
87
|
+
form collects guest details + payment and returns the buyer to the event. This is the path for
|
|
88
|
+
**all paid tickets**.
|
|
89
|
+
- **Free tickets only:** you may instead call `checkoutTickets(eventId, { reservationId, buyer, guests })`
|
|
90
|
+
to finish in-app — it returns an order with status `"FREE"`, a `ticketsPdf`, and `tickets[]`. It
|
|
91
|
+
throws for paid orders (status `INITIATED`), telling you to use the hosted form.
|
|
92
|
+
- **Empty state** — if `countUpcomingEvents()` is 0, show an empty state telling the user to publish
|
|
93
|
+
events in their Wix dashboard. Never invent events.
|
|
94
|
+
|
|
95
|
+
## Hard rules (do not violate)
|
|
96
|
+
- ✅ Complete paid ticket purchases ONLY via `reserveTickets()` → `getTicketCheckoutUrl()` redirect
|
|
97
|
+
(the official Wix-hosted ticket form).
|
|
98
|
+
- ❌ Never hand-build registration, ticket, payment, or checkout URLs — derive the hosted form URL
|
|
99
|
+
from `event.eventPageUrl` via `getTicketCheckoutUrl`.
|
|
100
|
+
- ❌ Never mock events, tickets, or guest counts — render live Wix data or the empty/closed state.
|
|
101
|
+
- ❌ Never invent reviews, ratings, attendee names, or "X spots left" numbers not returned by the API.
|
|
102
|
+
- ✅ Set `WIX_CLIENT_ID` from the prompt's value (public visitor-facing client id — safe to hardcode).
|
|
103
|
+
- ✅ Branch registration UI on `event.registration.type`; respect `registration.status` (only `OPEN_*`
|
|
104
|
+
accepts registrations) and ticket `saleStatus`/`salesDetails.soldOut`.
|
|
105
|
+
- ✅ Pass `guestPrice` for donation/"pay what you want" tickets and `pricingOptionId` for tiered tickets
|
|
106
|
+
to `reserveTickets`.
|
|
107
|
+
- The helpers fail loudly on purpose: `reserveTickets` throws when tickets aren't actually held,
|
|
108
|
+
`createRsvp` throws on closed/full registration, `checkoutTickets` throws when payment is still owed.
|
|
109
|
+
A green path means it really worked — don't swallow these.
|
|
110
|
+
|
|
111
|
+
## Beyond the snippets
|
|
112
|
+
The snippets cover the common RSVP + ticketing paths. If you hit a use case they don't cover
|
|
113
|
+
(coupons/`discount` at checkout, members/auth, schedule/agenda, seating maps, canceling a
|
|
114
|
+
reservation, a field not in the typedefs), make the call yourself with `wixApiRequest` — but look
|
|
115
|
+
up the exact endpoint, HTTP method, and request body in the **official Wix Events API reference**
|
|
116
|
+
first; never guess:
|
|
117
|
+
- Events API reference: https://dev.wix.com/docs/api-reference/business-solutions/events.md
|
|
118
|
+
- Registration (RSVP + ticketing) overview: https://dev.wix.com/docs/api-reference/business-solutions/events/registration/introduction.md
|
|
119
|
+
- Member login + a "my registrations" account view → the **members** vertical (`references/members/INSTRUCTIONS.md`).
|
|
120
|
+
- Ticketing flow (reservations → orders → tickets): https://dev.wix.com/docs/api-reference/business-solutions/events/registration/ticketing/introduction.md
|
|
121
|
+
|
|
122
|
+
Keep the snippets as the default for everything they already do; reach for the API reference only
|
|
123
|
+
for the gap.
|
|
124
|
+
|
|
125
|
+
## Point the user to their dashboard
|
|
126
|
+
In some cases, users need to access the Wix dashboard in order to edit the events content for their site. To facilitate this, provide the user with deep links directly to the relevant dashboard pages. For events data those pages are:
|
|
127
|
+
- **Events** — `https://manage.wix.com/dashboard/{metaSiteId}/events` (`Dashboard → Events` → **+ Add Event**; create the event, then set it up as **Ticketed** or **RSVP**; only published events appear in the app)
|
|
128
|
+
|
|
129
|
+
Substitute the site's `metaSiteId` to complete the links (you have it from the handoff / `ListWixSites`). Include the in-dashboard navigation as a fallback.
|
|
130
|
+
|
|
131
|
+
## Verification checklist (before declaring done)
|
|
132
|
+
- [ ] `WIX_CLIENT_ID` set to the prompt's value (not the `<YOUR-CLIENT-ID>` placeholder)
|
|
133
|
+
- [ ] Visitor token persists across reload (same visitor identity for reservations)
|
|
134
|
+
- [ ] Event grid renders live events; clicking a card opens the detail page by `slug`
|
|
135
|
+
- [ ] Detail page branches correctly on `registration.type` (RSVP form vs. ticket picker vs. external link)
|
|
136
|
+
- [ ] RSVP submit creates a real RSVP (and surfaces a `WAITLIST` result when the event is full)
|
|
137
|
+
- [ ] Ticket purchase reserves tickets, then redirects via `getTicketCheckoutUrl` (no hand-built URL)
|
|
138
|
+
- [ ] Paid checkout lands on the Wix-hosted ticket form; buyer returns to the event afterward
|
|
139
|
+
- [ ] Closed registration / sold-out tickets show a clear state rather than a dead end
|
|
140
|
+
- [ ] Empty state shown when `countUpcomingEvents()` is 0
|
|
141
|
+
- [ ] No mock events, tickets, or attendee data anywhere
|
|
142
|
+
- [ ] Told the user at least once that they can continue setting up their events in the dashboard and provided deep links.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { wixApiRequest } from "./wix-client.js";
|
|
2
|
+
|
|
3
|
+
// Data model reference: see INSTRUCTIONS.md
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Wix Events V3 Event — key fields for list cards and the detail page.
|
|
7
|
+
* Full model: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/event-object.md
|
|
8
|
+
*
|
|
9
|
+
* id {string}, title {string}, slug {string},
|
|
10
|
+
* status {string} — "UPCOMING"|"STARTED"|"ENDED"|"CANCELED"|"DRAFT" (only UPCOMING/STARTED are live),
|
|
11
|
+
* shortDescription {string} — PLAIN-TEXT teaser, safe to render directly (DETAILS fieldset),
|
|
12
|
+
* description {object} — RICH CONTENT (Ricos), shape { nodes: [...] } — NOT a string (TEXTS fieldset,
|
|
13
|
+
* returned by getEventBySlug). Render it with a Ricos viewer (@wix/ricos) or walk `nodes` to extract
|
|
14
|
+
* text; NEVER call string methods (.split/.slice/.substring/.trim) on it — that crashes the page.
|
|
15
|
+
* For a plain-string teaser use shortDescription instead.
|
|
16
|
+
* detailedDescription {string} — legacy plain/HTML description (TEXTS fieldset); prefer description/shortDescription,
|
|
17
|
+
* mainImage {object} — { id, url, width, height, altText } (DETAILS fieldset),
|
|
18
|
+
* dateAndTimeSettings {object}:
|
|
19
|
+
* startDate, endDate {string} — ISO-8601; absent when dateAndTimeTbd is true,
|
|
20
|
+
* timeZoneId {string} — IANA tz,
|
|
21
|
+
* formatted.dateAndTime {string} — ready-to-render human string,
|
|
22
|
+
* location {object}: type "VENUE"|"ONLINE", name {string}, address {object}, locationTbd {boolean},
|
|
23
|
+
* registration {object} (REGISTRATION fieldset):
|
|
24
|
+
* type {string} — "RSVP"|"TICKETING"|"EXTERNAL"|"NONE",
|
|
25
|
+
* status {string} — only OPEN_* statuses accept new registrations,
|
|
26
|
+
* rsvp.responseType — "YES_AND_NO" allows a "NO" reply,
|
|
27
|
+
* tickets.lowestPrice {object} — money { value, currency, formattedValue }; render
|
|
28
|
+
* formattedValue, not the object (see "Money/price fields" in SKILL.md). tickets.soldOut {boolean},
|
|
29
|
+
* external.url — link out when type === "EXTERNAL",
|
|
30
|
+
* eventPageUrl {object} — { base, path } (URLS fieldset) — needed for getTicketCheckoutUrl,
|
|
31
|
+
* form {object} — registration form controls (FORM fieldset),
|
|
32
|
+
* calendarUrls {object} — { google, ics } (DETAILS fieldset)
|
|
33
|
+
*
|
|
34
|
+
* Category: { id, label, slug, counts.assignedEventsCount }
|
|
35
|
+
* Full model: https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/categories
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
const LIST_FIELDS = ["DETAILS", "REGISTRATION", "URLS"];
|
|
39
|
+
const DETAIL_FIELDS = ["DETAILS", "TEXTS", "REGISTRATION", "URLS", "FORM"];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Query live (UPCOMING/STARTED) events for a listing grid, one page. Sorted soonest first.
|
|
43
|
+
* Uses offset paging — response carries total for empty state and "load more" math.
|
|
44
|
+
* https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/query-events.md
|
|
45
|
+
* @param {{ limit?: number, offset?: number, status?: string[] }} [options]
|
|
46
|
+
* @returns {Promise<{ events: object[], total: number, offset: number, nextOffset: number|null }>}
|
|
47
|
+
*/
|
|
48
|
+
export async function queryEvents({ limit = 50, offset = 0, status = ["UPCOMING", "STARTED"] } = {}) {
|
|
49
|
+
const res = await wixApiRequest("/events/v3/events/query", {
|
|
50
|
+
method: "POST",
|
|
51
|
+
body: {
|
|
52
|
+
query: {
|
|
53
|
+
filter: { status: { $in: status } },
|
|
54
|
+
sort: [{ fieldName: "dateAndTimeSettings.startDate", order: "ASC" }],
|
|
55
|
+
paging: { limit, offset },
|
|
56
|
+
},
|
|
57
|
+
fields: LIST_FIELDS,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
const events = res?.events ?? [];
|
|
61
|
+
const total = res?.pagingMetadata?.total ?? events.length;
|
|
62
|
+
const nextOffset = offset + events.length < total ? offset + events.length : null;
|
|
63
|
+
return { events, total, offset, nextOffset };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Fetch a single event by its URL slug, with full detail-page fields (description, form, page URL).
|
|
68
|
+
* Returns null if not found — show a not-found state, never invent an event.
|
|
69
|
+
* https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/get-event-by-slug.md
|
|
70
|
+
* @param {string} slug
|
|
71
|
+
* @returns {Promise<object|null>}
|
|
72
|
+
*/
|
|
73
|
+
export async function getEventBySlug(slug) {
|
|
74
|
+
try {
|
|
75
|
+
const res = await wixApiRequest(`/events/v3/events/slug/${encodeURIComponent(slug)}`, {
|
|
76
|
+
method: "GET",
|
|
77
|
+
query: { fields: DETAIL_FIELDS },
|
|
78
|
+
});
|
|
79
|
+
return res?.event ?? null;
|
|
80
|
+
} catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Total number of live events. Used for empty-state logic (0 → prompt user to publish events).
|
|
87
|
+
* @param {string[]} [status]
|
|
88
|
+
* @returns {Promise<number>}
|
|
89
|
+
*/
|
|
90
|
+
export async function countUpcomingEvents(status = ["UPCOMING", "STARTED"]) {
|
|
91
|
+
const res = await wixApiRequest("/events/v3/events/query", {
|
|
92
|
+
method: "POST",
|
|
93
|
+
body: { query: { filter: { status: { $in: status } }, paging: { limit: 1, offset: 0 } } },
|
|
94
|
+
});
|
|
95
|
+
return res?.pagingMetadata?.total ?? 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Query event categories for a category menu/filter. counts.assignedEventsCount tells you
|
|
100
|
+
* how many events are in each category.
|
|
101
|
+
* https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/categories/query-categories.md
|
|
102
|
+
* @param {{ limit?: number, offset?: number }} [options]
|
|
103
|
+
* @returns {Promise<{ categories: object[], total: number }>}
|
|
104
|
+
*/
|
|
105
|
+
export async function queryEventCategories({ limit = 100, offset = 0 } = {}) {
|
|
106
|
+
const res = await wixApiRequest("/events/v1/categories/query", {
|
|
107
|
+
method: "POST",
|
|
108
|
+
body: { query: { paging: { limit, offset } }, fieldset: ["COUNTS"] },
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
categories: res?.categories ?? [],
|
|
112
|
+
total: res?.metaData?.total ?? (res?.categories?.length ?? 0),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* List live events assigned to a category, one page. Same card fields as queryEvents.
|
|
118
|
+
* https://dev.wix.com/docs/api-reference/business-solutions/events/event-management/events-v3/list-events-by-category.md
|
|
119
|
+
* @param {string} categoryId Category GUID from queryEventCategories.
|
|
120
|
+
* @param {{ limit?: number, offset?: number }} [options]
|
|
121
|
+
* @returns {Promise<{ events: object[], total: number, offset: number, nextOffset: number|null }>}
|
|
122
|
+
*/
|
|
123
|
+
export async function listEventsByCategory(categoryId, { limit = 50, offset = 0 } = {}) {
|
|
124
|
+
const res = await wixApiRequest(`/events/v3/events/category/${encodeURIComponent(categoryId)}`, {
|
|
125
|
+
method: "GET",
|
|
126
|
+
query: {
|
|
127
|
+
fields: LIST_FIELDS,
|
|
128
|
+
"paging.limit": String(limit),
|
|
129
|
+
"paging.offset": String(offset),
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
const events = res?.events ?? [];
|
|
133
|
+
const total = res?.pagingMetadata?.total ?? events.length;
|
|
134
|
+
const nextOffset = offset + events.length < total ? offset + events.length : null;
|
|
135
|
+
return { events, total, offset, nextOffset };
|
|
136
|
+
}
|