@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,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Setup Portfolio"
|
|
3
|
+
description: Initializes a Wix Portfolio backend — cleans the install's default sample collection + projects, then creates collections and creates projects assigned to them via collectionIds (collections before projects). Specifies the *how* (calls + format); the collection/project counts and names come from the request.
|
|
4
|
+
---
|
|
5
|
+
**RECIPE**: Business Recipe – Initial Setup for Wix Portfolio
|
|
6
|
+
|
|
7
|
+
> **Standard call shape (every curl below).** The `<AUTH>` placeholder is shorthand for `Authorization: Bearer <TOKEN>` **and** `wix-site-id: <SITE_ID>`. Body-bearing requests also need `Content-Type: application/json`.
|
|
8
|
+
|
|
9
|
+
A concise checklist for preparing any new Wix site that uses the Wix Portfolio app.
|
|
10
|
+
**Notice** that this recipe is **NOT** meant for coding purposes and is **ONLY** meant for initial portfolio setup.
|
|
11
|
+
|
|
12
|
+
> **This recipe is the *how*, not the *what*.** What to seed — how many collections, which ones, how many projects and their titles/descriptions — is determined by the request you're fulfilling. This recipe only specifies the calls and the request format; it does not decide quantities or which entities to create.
|
|
13
|
+
|
|
14
|
+
> **API surfaces:** everything is the Portfolio **v1** API on `https://www.wixapis.com/portfolio/v1/...` — `/collections` and `/projects`. Use the **public `/portfolio/v1/...`** form; the method pages' schema headers show an internal `/portfolio/collections/api/v1/...` / `/portfolio/projects/projects/api/v1/...` URL — **do not** call those.
|
|
15
|
+
|
|
16
|
+
> **This recipe seeds content and assumes the Portfolio app is already installed.** Installing apps is a separate, earlier step in the run (the **Setup** step — `SETUP.md` — runs before any seeding); this recipe only *creates content* on an already-installed app. So if a call returns **`428` / `APP_NOT_INSTALLED`**, it means the Setup step was skipped for Portfolio — **fail loudly with the response verbatim** and let Setup handle the install. Do **not** fabricate a limitation ("I can't install apps / do it in your Wix dashboard") — installing is not this recipe's job, but it *is* something the skill does, in Setup.
|
|
17
|
+
|
|
18
|
+
> **Visibility is `hidden`, not `visible` — and it defaults to visible.** Portfolio's polarity is the **inverse** of Stores/Restaurants: entities carry a `hidden` boolean that **defaults to `false` (shown)**. So a collection/project created with no `hidden` field **appears on the live site** — you do **not** need to set anything to make it visible. Only set `"hidden": true` to hide one. (Send a plain boolean — `"hidden": false` — never a `{"value": …}` wrapper.) **Note:** when you omit `hidden` (or send `false`), the field is **absent** from the create/list response — proto3 drops false defaults — so *absent* reads as *false* reads as *shown*; `hidden` appears in the response only when you explicitly sent `true`. Don't treat a missing `hidden` as an error.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Article: Steps for Setting Up Wix Portfolio
|
|
23
|
+
**YOU MUST** complete all the following steps **in the given order** (0-2, plus 3 when imagery is on) without skipping any and **without requiring additional user input**.
|
|
24
|
+
|
|
25
|
+
**⚠️ CRITICAL ORDER REQUIREMENT: create the COLLECTIONS first (STEP 1), then the PROJECTS (STEP 2).** A project is assigned to collections by a `collectionIds` array, and **that array is NOT validated on create** — a wrong or nonexistent collection id is **silently accepted**, producing an orphan project that appears under no collection. The only way to assign correctly is to create the collections first, read back their real ids, and thread those exact ids into each project. (There is **no** shared-revision `409` race — creating collections/projects concurrently is safe — but the id dependency still forces collections-before-projects.)
|
|
26
|
+
|
|
27
|
+
### STEP 0: Clean the portfolio — remove the default sample data
|
|
28
|
+
|
|
29
|
+
A freshly installed Wix Portfolio app comes pre-seeded with **one sample collection ("My Portfolio") and several sample projects** ("Editorial Portraits", "Seasonal Lookbook", …), all assigned to that collection. **Only remove data that is obviously the install's own sample content on a fresh install** (that "My Portfolio" collection and its sample projects). Do **not** assume existing collections/projects are samples: the site may already hold the owner's **real content** (a connect/iterate run, or an owner-populated portfolio). If what's there isn't obviously install sample data, or you're unsure, **do not delete it — ask the user first** (`SEED.md`: seeding is additive; deleting real content needs the owner's approval). When it clearly is the install's samples, remove it **before** creating yours so the site shows only the intended content.
|
|
30
|
+
|
|
31
|
+
**Delete children before the parent — projects first, then collections.** (Deleting a collection does not clean up the projects that reference it.)
|
|
32
|
+
|
|
33
|
+
1. **List the projects** — `GET https://www.wixapis.com/portfolio/v1/projects`. The projects are under `response.projects[]` (count at `response.metadata.count`). Collect every `project.id`.
|
|
34
|
+
2. **Delete each project** — `DELETE https://www.wixapis.com/portfolio/v1/projects/{projectId}`, one call per id (there is **no** bulk-delete for projects). Each returns `200`.
|
|
35
|
+
3. **List the collections** — `GET https://www.wixapis.com/portfolio/v1/collections` (`response.collections[]`); collect every `collection.id`.
|
|
36
|
+
4. **Delete each collection** — `DELETE https://www.wixapis.com/portfolio/v1/collections/{collectionId}`, one call per id. Each returns `200`.
|
|
37
|
+
5. **Verify** both lists now return `metadata.count: 0` before proceeding.
|
|
38
|
+
|
|
39
|
+
### STEP 1: Create the collections
|
|
40
|
+
|
|
41
|
+
Create the collections the request calls for — **which collections (and how many) come from the request**; this step only gives the call and format. Use **Create Collection**: `POST https://www.wixapis.com/portfolio/v1/collections`. There is **no bulk-create** — issue **one call per collection** (they may be fired concurrently — no `409` race — but sequential is just as correct and simplest).
|
|
42
|
+
|
|
43
|
+
The body wraps the entity in a `collection` object:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"collection": {
|
|
48
|
+
"title": "Brand Identity",
|
|
49
|
+
"description": "Logo systems and visual identities for growing companies.",
|
|
50
|
+
"hidden": false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**⚠️ CRITICAL FORMAT REQUIREMENTS:**
|
|
56
|
+
- **The display name is `title`, not `name`.** A `name` field is ignored.
|
|
57
|
+
- **`slug` is optional — omit it and Wix auto-generates one from the title** (`"Brand Identity"` → `brand-identity`). Only send `slug` to force a specific one.
|
|
58
|
+
- **`hidden` is optional and defaults to `false` (shown)** — omit it for a visible collection; send `"hidden": true` only to hide one.
|
|
59
|
+
- **Text-only by default** — omit `coverImage` entirely (imagery is opt-in; see **Attach images**). `description` is a plain string.
|
|
60
|
+
|
|
61
|
+
**Reading the response — the created collection is under `collection`, not a top-level field.** A `200` returns:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{ "collection": { "id": "<collectionId>", "revision": "1", "title": "Brand Identity",
|
|
65
|
+
"slug": "brand-identity", "hidden": false, "sortOrder": 1783179721633, "url": { … } } }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Keep each **`collection.id`** (and `slug`) — the ids are the `collectionIds` you thread into projects in STEP 2. If a create fails, retry that collection **once** with the same body; do not loop.
|
|
69
|
+
|
|
70
|
+
### STEP 2: Create the projects, assigned to their collections
|
|
71
|
+
|
|
72
|
+
Create the projects the request calls for (counts/titles from the request). Use **Create Project**: `POST https://www.wixapis.com/portfolio/v1/projects` — **one call per project** (no bulk-create; concurrent is safe). Each project is assigned to one or more collections via **`collectionIds`**, populated with the **real ids from STEP 1**.
|
|
73
|
+
|
|
74
|
+
The body wraps the entity in a `project` object:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"project": {
|
|
79
|
+
"title": "Northwind Rebrand",
|
|
80
|
+
"description": "Full identity refresh for a logistics firm.",
|
|
81
|
+
"collectionIds": ["<collectionId from STEP 1>"],
|
|
82
|
+
"details": [
|
|
83
|
+
{ "label": "Role", "text": "Brand & Art Direction" },
|
|
84
|
+
{ "label": "Year", "text": "2025" }
|
|
85
|
+
],
|
|
86
|
+
"hidden": false
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**⚠️ CRITICAL FORMAT REQUIREMENTS:**
|
|
92
|
+
- **`collectionIds` must hold real ids captured from STEP 1.** They are **not validated** — a wrong/missing/guessed id is accepted silently and the project surfaces under no collection. Never invent a collection id; thread the STEP 1 response ids. A project with an **empty** `collectionIds: []` is created but belongs to no collection (only reachable from the all-projects list) — include at least one id unless the request truly wants an uncollected project.
|
|
93
|
+
- **The display name is `title`, not `name`.** `slug` auto-generates from the title when omitted.
|
|
94
|
+
- **`hidden` defaults to `false` (shown)** — same as collections; omit for visible.
|
|
95
|
+
- **`details` is optional** — an array of `{ label, text }` pairs (Role, Year, Client, …) that renders as the project's metadata. Include a couple where the brief gives that info; omit for a bare project (`details` comes back `[]`).
|
|
96
|
+
- **Text-only by default** — omit `coverImage` (see **Attach images**).
|
|
97
|
+
|
|
98
|
+
**Reading the response** — the created project is under `project`:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{ "project": { "id": "<projectId>", "revision": "1", "title": "Northwind Rebrand",
|
|
102
|
+
"slug": "northwind-rebrand", "hidden": false,
|
|
103
|
+
"collectionIds": ["<collectionId>"], "details": [ … ] } }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Keep each **`project.id`** and `slug`. If a create fails, retry that project **once** with the same body; do not loop.
|
|
107
|
+
|
|
108
|
+
### Attach images (imagery opt-in — skip when imagery is off)
|
|
109
|
+
|
|
110
|
+
**Only if `imagery` is on** (`SEED.md` § "Entity images"). Portfolio is a visual showcase, so the cover-image-bearing entities are **both projects and collections**. Generate + import each image per `references/IMAGE_GENERATION.md` (generate → import to Wix Media → keep the WixMedia image **id**), then **PATCH the entity's `coverImage`**.
|
|
111
|
+
|
|
112
|
+
Attach to a project — `PATCH https://www.wixapis.com/portfolio/v1/projects/{projectId}` (collections are identical: `PATCH …/collections/{collectionId}` with a `collection` wrapper). Echo the entity's current **`revision`** (from the create response, or a fresh `GET`) — no field mask is needed:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"project": {
|
|
117
|
+
"id": "<projectId>",
|
|
118
|
+
"revision": "<current revision>",
|
|
119
|
+
"coverImage": { "imageInfo": { "id": "<WixMedia image id>", "height": 2880, "width": 1920 } }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- **`coverImage.imageInfo.id`** is the imported **WixMedia image id** (`file` id from the import step) — **and `height` + `width` are required** alongside it (`url` is read-only, returned populated). A missing revision or a stale one fails the PATCH.
|
|
125
|
+
- Image failures never block the run — skip and leave the entity text-only.
|
|
126
|
+
|
|
127
|
+
### Attach images — project gallery (imagery on only)
|
|
128
|
+
|
|
129
|
+
**Only if `imagery` is on.** The cover (attached just above) is just the **listing-card thumbnail**. A project's **media gallery** — the ordered images on its detail page, which the frontend reads via the SDK `projectItems.listProjectItems(projectId)` (`how-to-code-portfolio.md`) — is a **separate `item` entity you must create**, one call per image. Without this step an imagery-on project has a cover but an empty gallery.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
curl -X POST 'https://www.wixapis.com/portfolio/v1/items' \ # lowercase `items` — `/Items` (capital) 404s
|
|
133
|
+
-H 'Authorization: <AUTH>' -H 'Content-Type: application/json' \
|
|
134
|
+
-d '{ "item": {
|
|
135
|
+
"projectId": "<projectId from the create-projects step>",
|
|
136
|
+
"sortOrder": 1,
|
|
137
|
+
"title": "<image title>",
|
|
138
|
+
"image": { "imageInfo": { "id": "<WixMedia image id>", "height": 896, "width": 1200 } }
|
|
139
|
+
} }'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- **One call per image**; **`sortOrder`** (1, 2, 3…) sets the order the frontend renders. `image.imageInfo` is the same shape as `coverImage` (imported WixMedia id + height + width).
|
|
143
|
+
- **Response nests the created item under `item`** (a top-level empty `projectId:""` echo is also returned — ignore it).
|
|
144
|
+
- **⚠️ There is NO public list endpoint.** `GET /portfolio/v1/items?projectId=…`, `/projects/{id}/items`, `/items/project/{id}` **all 404** — do not hunt for one. To verify, `GET https://www.wixapis.com/portfolio/v1/items/{itemId}` one at a time; the frontend lists them via the SDK `projectItems.listProjectItems` (an internal URL the SDK resolves).
|
|
145
|
+
- **Cover vs items:** cover = listing thumbnail (the cover PATCH above); items = ordered detail-page gallery (this call). An imagery-on portfolio typically wants **both** — if a project has only its cover image, reuse that WixMedia id as item #1 so the gallery isn't empty.
|
|
146
|
+
- Item failures never block the run — skip and continue (a project with no items still renders from its cover).
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Conclusion
|
|
151
|
+
Following these steps **in order** sets up a new Wix Portfolio site:
|
|
152
|
+
- Starts from a **clean portfolio** — the install's default sample collection and projects are all removed first (projects before collections).
|
|
153
|
+
- Contains the collections and projects called for by the request, with **collections created first** so each project's `collectionIds` holds a real, verified collection id (the array is not validated, so a wrong id would silently orphan the project).
|
|
154
|
+
- Every collection and project is **shown** (`hidden` defaults to `false`) — nothing needs setting to be visible.
|
|
155
|
+
- Cover images are attached only when `imagery` is on; otherwise everything stays text-only. All calls use the Portfolio **v1** API.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Setup Pricing Plans"
|
|
3
|
+
description: Initializes a Wix Pricing Plans backend with Plans V3 — creates recurring / one-time / free membership plans (billing cycle + flat-rate price), then (only when bookings is also in the run) attaches bookings services to a plan through the Benefit Programs API so a member's plan covers those services. Specifies the *how* (calls + format); counts and the specific plans/prices/cycles come from the request.
|
|
4
|
+
---
|
|
5
|
+
**RECIPE**: Business Recipe – Initial Setup for Wix Pricing Plans (Plans V3) + Bookings membership integration
|
|
6
|
+
|
|
7
|
+
> **Standard call shape (every curl below).** The `<AUTH>` placeholder is shorthand for `Authorization: Bearer <TOKEN>` only. Body-bearing requests also need `Content-Type: application/json`.
|
|
8
|
+
|
|
9
|
+
A concise checklist for turning a freshly provisioned Wix site with the **Wix Pricing Plans** app installed into a set of purchasable membership plans — and, when the site also has **Wix Bookings**, for wiring those plans to cover bookable services so members can book with their membership.
|
|
10
|
+
**Notice** that this recipe is **NOT** meant for coding purposes and is **ONLY** meant for initial Pricing Plans backend setup. (The frontend read/subscribe/book-with-plan contract is the sibling recipe `how-to-code-pricing-plans.md`.)
|
|
11
|
+
|
|
12
|
+
> **This recipe is the *how*, not the *what*.** What to seed — how many plans, their names, prices, and billing cycles, and which bookings services a plan covers — is determined by the request you're fulfilling. This recipe only specifies the calls and the request format; it does not decide quantities, prices, or which plans to create.
|
|
13
|
+
|
|
14
|
+
> **API surfaces:** plans use **Plans V3** on the **public** host `https://www.wixapis.com/pricing-plans/v3/...`. The bookings integration uses the **Benefit Programs V1** API (`https://www.wixapis.com/benefit-programs/v1/...`) — a *separate* API from Pricing Plans. Both APIs' method-article headers may show an internal `…/_api/…` form — **do not use that**; call the public non-`/_api/` form shown below. Relevant **app def ids** (constants the integration needs): Wix **Bookings** = `13d21c63-b5ec-5912-8397-c3a5ddb27a97`, Wix **Pricing Plans** = `1522827f-c56c-a5c9-2ac9-00f9e6ae12d3`.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Article: Steps for Setting Up Wix Pricing Plans
|
|
19
|
+
**YOU MUST** complete the following steps **in order** without skipping any and **without requiring additional user input**.
|
|
20
|
+
|
|
21
|
+
There is **no clean-up step** — a fresh Wix Pricing Plans install ships **no sample plans**, so there is nothing to delete first.
|
|
22
|
+
|
|
23
|
+
**⚠️ CRITICAL ORDER REQUIREMENT (integration only):** STEP 2 attaches **bookings service ids** to a plan. Those service ids come from the **Bookings seed** (`setup-bookings.md` → `seeded.bookings.serviceIds[]`). So when a run has **both** pricing-plans and bookings, **seed the bookings services first**, then create the plans (STEP 1), then attach (STEP 2). STEP 2 is **skipped entirely** when bookings is not in the run — a plans-only site stops after STEP 1.
|
|
24
|
+
|
|
25
|
+
### STEP 1: Create the plan(s)
|
|
26
|
+
|
|
27
|
+
Create **one plan per create call** (Plans V3 has **no bulk-create** for plans) against `POST https://www.wixapis.com/pricing-plans/v3/plans`. **How many plans, their names, prices, and billing cycles come from the request you're fulfilling** — this step only gives the call and the required format.
|
|
28
|
+
|
|
29
|
+
**⚠️ The create body MUST include `plan.status: "ACTIVE"` and a valid, unique GUID `id` on every `pricingVariants[]` and every `perks[]` entry** — omitting any of them returns `400` (`status value is required` / `id is not a valid GUID` / `id must not be empty`). These `id`s are **client-supplied** (a confirmed won't-fix server-side gap: the Pricing-Plans team will not auto-generate them; only the plan's *own* top-level `id` comes back server-generated).
|
|
30
|
+
|
|
31
|
+
**⚠️ Generate every GUID in the SHELL — never let the model type one.** A model emitting a UUID token-by-token isn't reliably valid or unique (→ `400`, or a duplicate-id collision across plans). Generate each in the shell and inject it via command substitution, so the value is always a real, fresh GUID regardless of which coding agent or OS runs this. This portable helper tries `uuidgen` → `python3` → `node`; **at least one is present in virtually every shell (a scaffolded Wix project always has `node`), so it effectively always succeeds — the fallback below covers the rare shell with none:**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
gen_uuid() { uuidgen 2>/dev/null | tr 'A-Z' 'a-z' \
|
|
35
|
+
|| python3 -c 'import uuid; print(uuid.uuid4())' 2>/dev/null \
|
|
36
|
+
|| node -e 'console.log(require("crypto").randomUUID())'; }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then create each plan with **fresh** ids (one `gen_uuid` call per field — never reuse a value across plans or perks). Body shown is a **recurring monthly** plan at a flat $20/month (the common membership case):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
VID=$(gen_uuid); PERK1=$(gen_uuid); PERK2=$(gen_uuid)
|
|
43
|
+
curl -sS -w "\nHTTP:%{http_code}" -X POST 'https://www.wixapis.com/pricing-plans/v3/plans' \
|
|
44
|
+
-H 'Authorization: <AUTH>' -H 'Content-Type: application/json' \
|
|
45
|
+
-d "{
|
|
46
|
+
\"plan\": {
|
|
47
|
+
\"name\": \"Studio Membership\",
|
|
48
|
+
\"description\": \"Unlimited access to group classes.\",
|
|
49
|
+
\"status\": \"ACTIVE\",
|
|
50
|
+
\"visibility\": \"PUBLIC\",
|
|
51
|
+
\"buyable\": true,
|
|
52
|
+
\"buyerCanCancel\": true,
|
|
53
|
+
\"pricingVariants\": [
|
|
54
|
+
{ \"id\": \"$VID\", \"name\": \"Monthly\",
|
|
55
|
+
\"billingTerms\": { \"billingCycle\": { \"period\": \"MONTH\", \"count\": 1 }, \"startType\": \"ON_PURCHASE\", \"endType\": \"UNTIL_CANCELLED\" },
|
|
56
|
+
\"pricingStrategies\": [ { \"flatRate\": { \"amount\": \"20.00\" } } ] }
|
|
57
|
+
],
|
|
58
|
+
\"perks\": [ { \"id\": \"$PERK1\", \"description\": \"Unlimited group classes\" }, { \"id\": \"$PERK2\", \"description\": \"10% off workshops\" } ]
|
|
59
|
+
}
|
|
60
|
+
}"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
> **Fallback — only if the shell has NO generator** (`uuidgen`, `python3`, **and** `node` all absent — effectively never in a Wix project): do **not** guess UUIDs. **Skip plan creation** and record a clear note for the user listing the plans to create by hand in the Wix dashboard (name, price, billing cycle). Failing loud beats seeding malformed plans.
|
|
64
|
+
|
|
65
|
+
**⚠️ CRITICAL FORMAT REQUIREMENTS:**
|
|
66
|
+
- **Pricing lives under `pricingVariants[]`, NOT a top-level `price`.** Each variant carries `billingTerms` (the cycle) + `pricingStrategies` (the amount). Send **one** `pricingVariant` with **one** `pricingStrategy` — the schema nominally allows up to 20 variants but documents "currently limited to 1", so one is the norm.
|
|
67
|
+
- **All amounts and money-ish values are decimal STRINGS**, not numbers: `flatRate.amount` = `"20.00"` (≥ `"0"`, ≤ 4 decimals). A number is rejected.
|
|
68
|
+
- **`billingTerms` selects the plan type** (the request decides which):
|
|
69
|
+
- **Recurring** (subscription): `billingCycle: { "period": "DAY|WEEK|MONTH|YEAR", "count": 1 }`, `startType: "ON_PURCHASE"`, `endType: "UNTIL_CANCELLED"`. **Default to `MONTH`/`1`** unless the request names another cycle.
|
|
70
|
+
- **One-time** (bill once, then ends): `endType: "CYCLES_COMPLETED"` + `cyclesCompletedDetails: { "billingCycleCount": 1 }`. A one-time plan with *no* end date instead sets `"billingCycle": null` + `endType: "UNTIL_CANCELLED"`.
|
|
71
|
+
- **Free**: `pricingStrategies: [ { "flatRate": { "amount": "0" } } ]`; cap reuse with `"purchaseLimits": { "type": "PER_MEMBER_LIFETIME", "count": 1 }` (the older `maxPurchasesPerBuyer: 1` is deprecated — removal targeted 2026-11-30 — prefer `purchaseLimits`).
|
|
72
|
+
- **Currency is NOT set in the request** — it's read-only in the response and derived from the site's business currency (like Bookings prices). Don't send a `currency`; don't fight the one that comes back.
|
|
73
|
+
- **`visibility: "PUBLIC"` + `buyable: true`** make the plan appear on the public grid and be orderable. A `PRIVATE`/`buyable:false` plan is assign-only (only seed one if the request explicitly wants a hidden/manual plan).
|
|
74
|
+
- **`name`** is required, 1–50 chars. **`perks[]`** are **display-only** (`{ description }`, ≤ 1400 chars each) — they are the bullet list shown on the plan card and have **no functional effect**. The actual bookings coverage is wired in STEP 2, **not** through `perks`.
|
|
75
|
+
- **`plan.status: "ACTIVE"` is REQUIRED** — omitting it returns `400 status value is required` (undocumented but enforced; `ACTIVE` is the only value).
|
|
76
|
+
- **`pricingVariants[].id` and `perks[].id` are REQUIRED, client-supplied GUIDs** — generate each in the shell (the `gen_uuid` helper above), never model-typed (→ malformed/duplicate → `400`), fresh per field. Only the plan's **own top-level `id`** is server-generated; it echoes the variant/perk ids you sent back in the response.
|
|
77
|
+
- On partial failure across multiple plans, retry the **failed** plan(s) **once** with the same format — do not loop.
|
|
78
|
+
|
|
79
|
+
**⚠️ Reading the response — the created plan is under `plan`, keep `plan.id`.** A successful create returns `200` with:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{ "plan": {
|
|
83
|
+
"id": "<planId>",
|
|
84
|
+
"revision": "1",
|
|
85
|
+
"name": "Studio Membership",
|
|
86
|
+
"visibility": "PUBLIC",
|
|
87
|
+
"buyable": true,
|
|
88
|
+
"currency": "USD",
|
|
89
|
+
"pricingVariants": [ { "id": "<variantId>", "name": "Monthly", "billingTerms": { … }, "pricingStrategies": [ … ] } ],
|
|
90
|
+
"perks": [ { "id": "<perkId>", "description": "Unlimited group classes" } ]
|
|
91
|
+
} }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Keep each plan's **`plan.id`** into `seeded.pricing-plans.planIds[]` — it's the id the frontend orders by, **and** the `externalId` the STEP 2 integration keys on.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### STEP 2: Attach bookings services to a plan (integration — SKIP when there is no bookings in the run)
|
|
99
|
+
|
|
100
|
+
This is the **pricing-plans ↔ bookings membership link**: making a plan *cover* one or more bookable services so a member who holds the plan can book those services with their membership (frontend flow lives in `how-to-code-pricing-plans.md`). The link is **NOT** a field on the plan and **NOT** a perk — it goes through the separate **Benefit Programs API**, in three ordered sub-steps. Do this **per plan** that should cover services, using the plan's `plan.id` from STEP 1 and the **bookings service ids** from `setup-bookings.md`'s `seeded.bookings.serviceIds[]`.
|
|
101
|
+
|
|
102
|
+
**⚠️ CRITICAL: the three sub-steps are strictly ordered — each consumes an id from the previous:** `plan.id` → `programDefinition.id` → `itemSetId` → items. Don't parallelize them.
|
|
103
|
+
|
|
104
|
+
#### STEP 2a: Get the plan's program definition (READ — do not create it)
|
|
105
|
+
|
|
106
|
+
When a plan is created, the Pricing Plans app **automatically creates a matching "program definition"** in Benefit Programs. You **read** it (you never create it) by the plan id + namespace:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
curl -X GET 'https://www.wixapis.com/benefit-programs/v1/program-definitions/by-namespace-and-external-id?externalId=<PLAN_ID>&namespace=@wix/pricing-plans' \
|
|
110
|
+
-H 'Authorization: <AUTH>'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Response — keep **`programDefinition.id`** (this is the "programDefinitionId" STEP 2b needs):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{ "programDefinition": {
|
|
117
|
+
"id": "<programDefinitionId>",
|
|
118
|
+
"namespace": "@wix/pricing-plans",
|
|
119
|
+
"externalId": "<PLAN_ID>",
|
|
120
|
+
"displayName": "…"
|
|
121
|
+
} }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- **⚠️ `namespace` is literally `@wix/pricing-plans`** (with the `@` and the slash) in every sub-step 2a–2c. The generic Benefit Programs docs use placeholder namespaces (`gym_rewards`, `benefit_programs_app`) — **do not** use those.
|
|
125
|
+
- **Provisioning is effectively immediate.** The program definition is created by the Plans app within ~1s of STEP 1. It's still created *asynchronously*, so if this GET returns `404`/empty right after creating the plan, **retry once after a short backoff** as insurance — do not loop.
|
|
126
|
+
|
|
127
|
+
#### STEP 2b: Create the pool definition (one per integrating app)
|
|
128
|
+
|
|
129
|
+
Create **one** pool definition holding **exactly one** benefit that names the Bookings app as the provider:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
curl -X POST 'https://www.wixapis.com/benefit-programs/v1/pool-definitions' \
|
|
133
|
+
-H 'Authorization: <AUTH>' \
|
|
134
|
+
-H 'Content-Type: application/json' \
|
|
135
|
+
-d '{
|
|
136
|
+
"poolDefinition": {
|
|
137
|
+
"namespace": "@wix/pricing-plans",
|
|
138
|
+
"displayName": "Bookings benefit",
|
|
139
|
+
"programDefinitionIds": ["<programDefinitionId FROM 2a>"],
|
|
140
|
+
"details": {
|
|
141
|
+
"benefits": [
|
|
142
|
+
{
|
|
143
|
+
"benefitKey": "<RANDOM_UUID>",
|
|
144
|
+
"displayName": "Bookings sessions",
|
|
145
|
+
"providerAppId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97",
|
|
146
|
+
"price": "0"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"cascade": "IMMEDIATELY"
|
|
152
|
+
}'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Response — keep the generated **`itemSetId`** for the benefit (matched by its `benefitKey`):
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{ "poolDefinition": {
|
|
159
|
+
"id": "<poolDefinitionId>",
|
|
160
|
+
"programDefinitionIds": ["<programDefinitionId>"],
|
|
161
|
+
"namespace": "@wix/pricing-plans",
|
|
162
|
+
"details": { "benefits": [
|
|
163
|
+
{ "benefitKey": "<RANDOM_UUID>", "itemSetId": "<itemSetId>", "providerAppId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97", "price": "0" }
|
|
164
|
+
] }
|
|
165
|
+
} }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
- **`benefitKey`** is a **freshly generated random UUID** you supply (any v4 UUID).
|
|
169
|
+
- **`providerAppId`** is the **Bookings** app def id `13d21c63-b5ec-5912-8397-c3a5ddb27a97` (the same GUID used as the bookings app id in the cart/frontend recipes). It is **not** the Pricing Plans id.
|
|
170
|
+
- **`price`** is credit-model, not money: **`"0"` = unlimited** sessions covered (leave `creditConfiguration` empty — the "unlimited membership" case, the default here); **`"1"` = limited credits**, which then requires a `details.creditConfiguration` (e.g. `{ "amount": "10" }` for a 10-session pack). Default to **`"0"` (unlimited)** unless the request names a session count.
|
|
171
|
+
- **⚠️ Limited-credit plan (`price:"1"`): `creditConfiguration` goes at `details.creditConfiguration` — a SIBLING of `benefits[]`, NOT a field inside a benefit.** Nesting it inside the benefit makes the server treat the credit pool as "not set up" and reject the non-zero price with `400 "Price should be 0 when credit pool is not set up"`. The correct `details` shape for a limited pack (e.g. an 8-class pass):
|
|
172
|
+
```json
|
|
173
|
+
"details": {
|
|
174
|
+
"creditConfiguration": { "amount": "8" },
|
|
175
|
+
"benefits": [
|
|
176
|
+
{ "benefitKey": "<RANDOM_UUID>", "displayName": "Bookings sessions",
|
|
177
|
+
"providerAppId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97", "price": "1" }
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
(The unlimited case above keeps `price:"0"` and **no** `creditConfiguration`.)
|
|
182
|
+
- **One pool definition per integrating app** — for a plan covering bookings, that's exactly one pool with one benefit. Don't create a second pool for the same app on the same plan.
|
|
183
|
+
- **`itemSetId` path is `poolDefinition.details.benefits[i].itemSetId`** — pick the entry whose `benefitKey` matches the one you sent.
|
|
184
|
+
|
|
185
|
+
#### STEP 2c: Bulk-create the benefit items (one per covered service)
|
|
186
|
+
|
|
187
|
+
Attach the actual bookings services to the benefit — **one item per service** — via bulk create:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
curl -X POST 'https://www.wixapis.com/benefit-programs/v1/bulk/items/create' \
|
|
191
|
+
-H 'Authorization: <AUTH>' \
|
|
192
|
+
-H 'Content-Type: application/json' \
|
|
193
|
+
-d '{
|
|
194
|
+
"items": [
|
|
195
|
+
{
|
|
196
|
+
"namespace": "@wix/pricing-plans",
|
|
197
|
+
"category": "",
|
|
198
|
+
"providerAppId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97",
|
|
199
|
+
"itemSetId": "<itemSetId FROM 2b>",
|
|
200
|
+
"externalId": "<BOOKINGS_SERVICE_ID>"
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
"returnEntity": true
|
|
204
|
+
}'
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Response — standard bulk shape; each covered service lands under `results[].itemMetadata` (and `results[].item` because `returnEntity: true`):
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{ "results": [
|
|
211
|
+
{ "itemMetadata": { "id": "<benefitItemId>", "originalIndex": 0, "success": true },
|
|
212
|
+
"item": { "id": "<benefitItemId>", "externalId": "<BOOKINGS_SERVICE_ID>", "itemSetId": "<itemSetId>" } }
|
|
213
|
+
], "bulkActionMetadata": { "totalSuccesses": 1, "totalFailures": 0 } }
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
- **`externalId` is the bookings SERVICE id** (`item.id` from `setup-bookings.md` STEP 3) — one item per service the plan should cover. Up to **100** items per call.
|
|
217
|
+
- **`category` is an empty string `""`**, and **`namespace`/`providerAppId`** repeat the STEP-2b values on every item.
|
|
218
|
+
- **The public path is `POST …/benefit-programs/v1/bulk/items/create`.** Some docs examples show a bare `…/bulk/items`; ignore that and use the `/bulk/items/create` form shown here.
|
|
219
|
+
- **Check `results[].itemMetadata.success` per item** (`false` populates `.error`); retry only the failed items **once** with the same format.
|
|
220
|
+
|
|
221
|
+
Keep the linkage in the seed map so the coding handoff can reason about coverage: `seeded.pricing-plans.bookingsCoverage = { <planId>: { itemSetId, serviceIds: [ … ] } }`.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Conclusion
|
|
226
|
+
Following these steps **in order** sets up a Plans V3 Wix Pricing Plans site (and, when bookings is present, the membership integration):
|
|
227
|
+
- Each plan is created **`visibility: PUBLIC` + `buyable: true`** with pricing under **`pricingVariants[].billingTerms` + `pricingStrategies[].flatRate.amount`** (decimal **strings**), the cycle (`MONTH`/`1` by default) and type (recurring / one-time / free) chosen from the request; currency is site-derived, `perks` are display-only.
|
|
228
|
+
- **Bookings coverage is wired through the Benefit Programs API**, not the plan object: **read** the auto-created program definition (`programDefinition.id`) → create **one** pool definition with one benefit whose `providerAppId` is the **Bookings** app id (`price:"0"` = unlimited) → bulk-create **items** whose `externalId` is each covered **bookings service id**. This is **skipped** when bookings isn't in the run.
|
|
229
|
+
- IDs kept for the coding handoff: `planIds[]`, and (integration) per plan `{ itemSetId, covered serviceIds[] }`.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Setup Restaurant Experiences"
|
|
3
|
+
description: Seeds Wix Table Reservations **Experiences** — a reservation that IS a special dining occasion at the restaurant (wine tasting, cheese pairing, chef's table, tasting-menu evening), as opposed to a plain table booking or a Bookings service. Points to the live docs for the full create payload and carries only the earned gotchas the docs don't state (field-shape drift, payment policy, premium gating, when-to-use). The occasions/prices/schedule come from the request.
|
|
4
|
+
---
|
|
5
|
+
**RECIPE**: Business Recipe – Experiences Setup for Wix Table Reservations (Experiences API)
|
|
6
|
+
|
|
7
|
+
> **Standard call shape (every curl below).** `<AUTH>` = `Authorization: Bearer <TOKEN>` **and** `wix-site-id: <SITE_ID>`. Body-bearing requests also need `Content-Type: application/json`.
|
|
8
|
+
|
|
9
|
+
## When to use experiences (and when NOT to)
|
|
10
|
+
|
|
11
|
+
An **experience** is a **reservation that is itself a curated dining occasion at the restaurant** — it books seats at the restaurant's own reservation location but overrides the location's defaults with its own name, description, per-guest payment policy, party-size, schedule, and booking form. Reach for it when the brief names a **wine tasting, cheese/wine pairing, chef's table, or tasting-menu evening**.
|
|
12
|
+
|
|
13
|
+
- **Experience vs plain reservation:** a plain reservation just books a table; an experience books a *named, scheduled, often paid occasion*. Same booking mechanism, different intent.
|
|
14
|
+
- **Experience vs `bookings`:** the separate `bookings` vertical is for a **service/appointment/class with a provider** (spa, tutor, studio). If a restaurant *hosts and seats* the occasion, it's an experience — not a booking. (See `CAPABILITIES.md` — "Experiences vs bookings".)
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- The **Table Reservations app** is installed (`SETUP.md` §2). **Experiences are a feature of that app — there is no separate app to install.**
|
|
19
|
+
- A **reservation location exists** — the install auto-provisions the default one (`setup-restaurant-reservations.md` STEP 1). Discover it and take its **`id`**; every experience is created against that `reservationLocationId`. No menu dependency.
|
|
20
|
+
|
|
21
|
+
## The docs are the source of truth for the payload — read them, don't guess
|
|
22
|
+
|
|
23
|
+
Read these `.md` twins directly (first priority; append `.md` to the article URL). This recipe deliberately does **not** re-inline the full schema — it changes, and the docs carry the complete, current field tree:
|
|
24
|
+
|
|
25
|
+
- **About Experiences** (what they are, how they bind to reservations/locations/time-slots): <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/experiences/introduction.md>
|
|
26
|
+
- **Create Experience** (the full create payload + example): <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/experiences/create-experience.md>
|
|
27
|
+
- **Query / Get Experience**: <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/experiences/query-experiences.md> · <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/experiences/get-experience.md>
|
|
28
|
+
- **Sample flow** (showcase + book an experience end-to-end): <https://dev.wix.com/docs/api-reference/business-solutions/restaurants/reservations/experiences/sample-flows.md>
|
|
29
|
+
|
|
30
|
+
Endpoint: `POST https://www.wixapis.com/table-reservations/experiences/v1/experiences`.
|
|
31
|
+
|
|
32
|
+
## The flow
|
|
33
|
+
|
|
34
|
+
1. **Discover the reservation location** (`setup-restaurant-reservations.md` STEP 1) → keep `reservationLocationId`.
|
|
35
|
+
2. **Create one experience per named occasion.** Build the body from the request (occasion name, per-guest price, party size, days/times, duration) per the **Create Experience** doc. Keep each returned `experience.id`. Set `configuration.visible: true` so it shows on the live site.
|
|
36
|
+
3. Per the "simple seeds" default, create only the occasions the brief names (typically 1–3); don't invent a full calendar.
|
|
37
|
+
|
|
38
|
+
Minimal shape (the doc has the complete tree — this is only the skeleton to orient against):
|
|
39
|
+
|
|
40
|
+
```jsonc
|
|
41
|
+
{ "experience": {
|
|
42
|
+
"reservationLocationId": "<reservationLocationId>",
|
|
43
|
+
"configuration": {
|
|
44
|
+
"displayInfo": { "name": "…", "shortDescription": "…" },
|
|
45
|
+
"paymentPolicy": { "paymentPolicyType": "PER_GUEST", "perGuestOptions": { "price": "55.00" } },
|
|
46
|
+
"onlineReservations": {
|
|
47
|
+
"partySize": { "min": 2, "max": 8 },
|
|
48
|
+
"minimumReservationNotice": { "number": 24, "unit": "HOURS" },
|
|
49
|
+
"maximumReservationNotice": { "number": 60, "unit": "DAYS" },
|
|
50
|
+
"approval": { "mode": "AUTOMATIC" },
|
|
51
|
+
"maxGuests": { "number": 16 },
|
|
52
|
+
"businessSchedule": { "durationInMinutes": 90, "entries": [
|
|
53
|
+
{ "recurrence": "WEEKLY", "weeklyOptions": { "startDaysAndTimes": [ { "day": "FRIDAY", "time": "18:30" } ] } }
|
|
54
|
+
] }
|
|
55
|
+
},
|
|
56
|
+
"visible": true
|
|
57
|
+
}
|
|
58
|
+
} }
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Earned gotchas (what the docs won't tell you — verified against the live API)
|
|
62
|
+
|
|
63
|
+
- **⚠️ Notice fields are FLAT under `onlineReservations`, not wrapped.** Send `onlineReservations.minimumReservationNotice` and `.maximumReservationNotice` **directly**. The Create-Experience doc *example* nests them inside a `noticePeriod` object — that wrapper is stale; the required-parameters list (same page) shows them flat, and the flat form is what the API accepts. Follow the parameter tree, not the example blob.
|
|
64
|
+
- **Required at create** (creation 400s without them): `reservationLocationId`; `configuration.displayInfo.name`; `configuration.paymentPolicy.paymentPolicyType`; `configuration.onlineReservations.partySize.min/max`, `.approval.mode`, `.minimumReservationNotice.{number,unit}`, `.maximumReservationNotice.{number,unit}`, `.maxGuests.number`. (Confirm against the doc — the list evolves.)
|
|
65
|
+
- **`paymentPolicyType`: `PER_GUEST` or `FREE`.** `PER_GUEST` needs `perGuestOptions.price` (decimal **string**, e.g. `"55.00"`; currency is the site's). `FREE` needs no price. Creating a `PER_GUEST` experience succeeds on a free site, but a guest **completing** a paid experience booking needs the same premium + payment provider that any paid reservation does (below).
|
|
66
|
+
- **`businessSchedule.entries[]`** carries the recurrence: `WEEKLY` with `weeklyOptions.startDaysAndTimes[{ day, time }]` (`day` is `MONDAY`…`SUNDAY`, `time` is `"HH:mm"`), or `ONE_TIME` with `oneTimeOptions`. `durationInMinutes` sits on `businessSchedule`, not per entry.
|
|
67
|
+
- **⚠️ Booking an experience is PREMIUM-GATED**, exactly like turning on online reservations (`setup-restaurant-reservations.md` STEP 3 → `428 PREMIUM_ONLY` on a free site). **Creating** the experience works on a free site; **booking** it at runtime needs the site to be premium with online reservations enabled. Record the precondition in the handoff; **don't fail the seed** over it.
|
|
68
|
+
- **Cover image (opt-in):** `configuration.displayInfo.coverImage` takes a Wix Media image (`{ id, url, … }`) — attach it in the imagery pass (`IMAGE_GENERATION.md`) only when `imagery` is on; otherwise omit and the frontend renders a themed block.
|
|
69
|
+
- **⚠️ Heads-up for the booking UI (not a seed step):** the experiences **sample-flow doc** (linked above) tells the frontend to call `getScheduledTimeSlots` with the experience GUID — **that parameter doesn't exist** (neither the SDK nor REST scopes slots to an experience), so it silently returns the *location's* slots. The frontend must instead project bookable times from the experience's own `businessSchedule`. Full detail: `how-to-code-restaurant-reservations.md` (Gotcha C).
|
|
70
|
+
|
|
71
|
+
## Keep
|
|
72
|
+
|
|
73
|
+
Nothing crosses into the handoff — experiences are read **live** on the frontend (`queryExperiences`). Track the created `experienceId`(s) only transiently (to confirm success / attach cover images). Frontend booking contract: `how-to-code-restaurant-reservations.md` (Experiences section).
|