@wix/agent-skills 1.16.3 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +115 -12
- package/skills/wix-app/references/APP_MARKET_REVIEW.md +1 -1
- package/skills/wix-app/references/BACKEND_API.md +18 -0
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +6 -0
- package/skills/wix-app/references/DASHBOARD_MODAL.md +10 -2
- package/skills/wix-app/references/DASHBOARD_PAGE.md +32 -70
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +145 -127
- package/skills/wix-app/references/SITE_PLUGIN.md +14 -2
- package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +74 -68
- package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
- package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +79 -0
- package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +73 -0
- package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +52 -0
- package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +184 -0
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +94 -49
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +16 -6
- package/skills/wix-app/references/editor-react-component/BROWSER-SUPPORT.md +56 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +35 -40
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +167 -445
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +56 -29
- package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
- package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
- package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
- package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +11 -3
- package/skills/wix-app/references/editor-react-component/PARTS.md +46 -24
- package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
- package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
- package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
- package/skills/wix-base44-connector/SKILL.md +156 -50
- package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +78 -0
- package/skills/wix-base44-connector/scripts/utils.js +239 -45
- package/skills/wix-headless/entry/bootstrap.mjs +9 -2
- package/skills/wix-headless/entry/skill.md +1 -1
- package/skills/wix-headless/references/CAPABILITIES.md +9 -1
- package/skills/wix-headless/references/DESIGN.md +1 -0
- package/skills/wix-headless/references/DISCOVERY.md +2 -1
- package/skills/wix-headless/references/IMAGE_GENERATION.md +1 -0
- package/skills/wix-headless/references/SDK_HANDOFF.md +5 -2
- package/skills/wix-headless/references/SEED.md +2 -1
- package/skills/wix-headless/references/SETUP.md +1 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +2 -2
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +68 -31
- package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +26 -10
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +8 -8
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
- package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +254 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
- package/skills/wix-headless/references/inline-recipes/setup-online-store.md +13 -0
- package/skills/wix-headless/references/inline-recipes/setup-rentals.md +254 -0
- package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
- package/skills/wix-headless/references/non-astro.md +1 -1
- package/skills/wix-headless-fast/SKILL.md +166 -0
- package/skills/wix-headless-fast/entry/skill.md +99 -0
- package/skills/wix-headless-fast/install/deploy.mjs +433 -0
- package/skills/wix-headless-fast/install/fast-path.mjs +141 -0
- package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +137 -0
- package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +137 -0
- package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +113 -0
- package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +42 -0
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +123 -0
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +70 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +99 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +76 -0
- package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +62 -0
- package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +99 -0
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +24 -0
- package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +16156 -0
- package/skills/wix-headless-fast/references/blog/seed/SEED.md +72 -0
- package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +287 -0
- package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +129 -0
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +143 -0
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +119 -0
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +138 -0
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +54 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +206 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +96 -0
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +70 -0
- package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +76 -0
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +22 -0
- package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +11962 -0
- package/skills/wix-headless-fast/references/bookings/seed/SEED.md +61 -0
- package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +302 -0
- package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +179 -0
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +83 -0
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +57 -0
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +151 -0
- package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +75 -0
- package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +11262 -0
- package/skills/wix-headless-fast/references/cms/seed/SEED.md +103 -0
- package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +324 -0
- package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +149 -0
- package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +66 -0
- package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +176 -0
- package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +118 -0
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +117 -0
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +59 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +136 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +128 -0
- package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +61 -0
- package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +12 -0
- package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +80 -0
- package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +21 -0
- package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +11884 -0
- package/skills/wix-headless-fast/references/events/seed/SEED.md +86 -0
- package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +276 -0
- package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +150 -0
- package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +317 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +269 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +231 -0
- package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +135 -0
- package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +10593 -0
- package/skills/wix-headless-fast/references/forms/seed/SEED.md +108 -0
- package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +320 -0
- package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +63 -0
- package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +60 -0
- package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +155 -0
- package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +78 -0
- package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +47 -0
- package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +66 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +88 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +53 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +122 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +50 -0
- package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +21 -0
- package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +42 -0
- package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +10 -0
- package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +11 -0
- package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +10329 -0
- package/skills/wix-headless-fast/references/members/seed/SEED.md +39 -0
- package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +94 -0
- package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +134 -0
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +110 -0
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +90 -0
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +115 -0
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +59 -0
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +39 -0
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +58 -0
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +165 -0
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +55 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +40 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +30 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +21 -0
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +29 -0
- package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +10197 -0
- package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +78 -0
- package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +258 -0
- package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +133 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +58 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +126 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +37 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +39 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +75 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +45 -0
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +30 -0
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +41 -0
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +40 -0
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +21 -0
- package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +11226 -0
- package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +71 -0
- package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +279 -0
- package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +165 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +142 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +26 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +121 -0
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +155 -0
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +55 -0
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +43 -0
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +177 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +165 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +103 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +254 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +146 -0
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +168 -0
- package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +47 -0
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +22 -0
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +12 -0
- package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +12560 -0
- package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +81 -0
- package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +479 -0
- package/skills/wix-headless-fast/references/shared/CONTENT.md +22 -0
- package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +73 -0
- package/skills/wix-headless-fast/references/shared/DESIGN.md +26 -0
- package/skills/wix-headless-fast/references/shared/app/styles/global.css +52 -0
- package/skills/wix-headless-fast/references/shared/app/wix/config.ts +15 -0
- package/skills/wix-headless-fast/references/shared/app/wix/media.ts +27 -0
- package/skills/wix-headless-fast/references/shared/app/wix/money.ts +24 -0
- package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +76 -0
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +46 -0
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +46 -0
- package/skills/wix-headless-fast/references/shared/seed/images.mjs +145 -0
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +149 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +26 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +121 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductCard.tsx +100 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductDetailView.tsx +130 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ProductGrid.tsx +48 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/ShopView.tsx +66 -0
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/VariantPicker.tsx +103 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +48 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +140 -0
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +80 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +101 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +221 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +215 -0
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +109 -0
- package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +46 -0
- package/skills/wix-headless-fast/references/storefront/app-astro/pages/products/[slug].astro +56 -0
- package/skills/wix-headless-fast/references/storefront/app-astro/pages/shop.astro +23 -0
- package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +12247 -0
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +85 -0
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +415 -0
- package/skills/wix-manage/SKILL.md +28 -2
- package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
- package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
- package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
- package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +141 -0
- package/skills/wix-manage/references/google-business-profile/connect-google-business-profile.md +134 -0
- package/skills/wix-manage/references/google-business-profile/manage-google-business-profile-locations.md +182 -0
- package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +3 -0
- package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
- package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
- package/skills/wix-manage/references/sites/query-sites.md +72 -161
- package/skills/wix-manage/references/stores/create-product-catalog-v3.md +21 -6
- package/skills/wix-manage/references/stores/update-product-with-options.md +83 -0
- package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
- package/skills/wix-vibe-headless/SKILL.md +18 -4
- package/skills/wix-vibe-headless/install/deploy.cjs +12 -4
- package/skills/wix-vibe-headless/install/pin-agents-md.cjs +2 -1
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +16 -10
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +13 -8
- package/skills/wix-vibe-headless/platforms/base44.md +27 -62
- package/skills/wix-vibe-headless/platforms/generic.md +6 -3
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +45 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +67 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +128 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +5 -3
- package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
- package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +250 -0
- package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +12 -5
- package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +41 -0
- package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.js +267 -0
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +6 -3
- package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +470 -0
- package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +425 -0
- package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +187 -0
- package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +238 -0
- package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +108 -0
- package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1762 -0
- package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +13 -0
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
- package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
- package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
- package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +152 -92
- package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
- package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +15 -8
- package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +37 -0
- package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
- package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +18 -6
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +30 -7
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +46 -10
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -516
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
- package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
- package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +0 -110
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +0 -51
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +0 -49
- package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +0 -92
- package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +0 -139
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# Wix Storefront — ready-made client
|
|
2
2
|
|
|
3
|
-
The storefront
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
The storefront **commerce engine ships as real files** — the hooks, the server cart, the REST
|
|
4
|
+
transport, the image helpers, and the `Shop` listing page, all correct (variant resolution,
|
|
5
|
+
modifiers, stock gating, checkout). It reads from your app's design tokens (base44's `src/index.css`
|
|
6
|
+
— the shadcn palette the design phase already set).
|
|
7
|
+
|
|
8
|
+
**The presentation doesn't ship — you build it** (STEP 3): the product **card**, **grid**, **variant
|
|
9
|
+
controls**, and the whole **product (PDP) page**, plus **Home** and the **header/footer**. Each is
|
|
10
|
+
built on a shipped hook whose return type + field shapes are documented in the outline right next to
|
|
11
|
+
it — the data is handed to you done, the layout and look are yours. `Shop` renders once your
|
|
12
|
+
`ProductGrid` exists; the PDP renders once you build its page — that's the point.
|
|
8
13
|
|
|
9
14
|
Talks to Wix directly over the public `WIX_CLIENT_ID` (anonymous visitor tokens). Never mock
|
|
10
15
|
products; never hand-build a `/checkout` URL — the shipped cart goes through the eCom
|
|
@@ -22,40 +27,38 @@ so you don't need to open them:**
|
|
|
22
27
|
| file | what it is |
|
|
23
28
|
|---|---|
|
|
24
29
|
| `context/CartContext.jsx` | `useCart()` provider: server cart, add/update/remove, checkout |
|
|
25
|
-
| `hooks/useProductDetail.js` | PDP data — product + variant resolution for a slug, plus load/add state |
|
|
30
|
+
| `hooks/useProductDetail.js` | PDP data — product + variant resolution for a slug, plus load/add state; **your product page (STEP 3) is built on it** |
|
|
26
31
|
| `hooks/useShop.js` | catalog listing — category menu, cursor paging, sort, failure state |
|
|
27
|
-
| `hooks/useProductCard.js` | headless data layer for a grid tile — returns `leftBadges`, `promoBadge`, `priceDisplay`, `compareAtDisplay`, `colors`, `optionLabel`, `isQuickAddable`, `image`, `hoverImage`; **
|
|
28
|
-
| `
|
|
29
|
-
| `components/ProductGrid.jsx` | reference grid layout (2-col mobile → auto-fill desktop) with skeleton + empty state — read it for the skeleton/empty-state patterns, build your own layout rather than using it directly |
|
|
30
|
-
| `components/ProductGallery.jsx` | PDP main image + thumbnails |
|
|
31
|
-
| `lib/storeImage.js` | `productImage()` / `productGallery()` / `storeImage()` — normalise Wix image urls |
|
|
32
|
+
| `hooks/useProductCard.js` | headless data layer for a grid tile — returns `leftBadges`, `promoBadge`, `priceDisplay`, `compareAtDisplay`, `colors`, `optionLabel`, `isQuickAddable`, `image`, `hoverImage`; **your `ProductCard` (STEP 3) is built on it** |
|
|
33
|
+
| `lib/storeImage.js` | `productImage()` / `productGallery()` / `storeImage()` / `choiceImage()` — normalise Wix image urls; `productGallery(product)` → `[{ url, altText }]` (your PDP gallery); `choiceImage(choice)` resolves an option choice's photo (V3 read shape: `media.items[].mediaId`, not `linkedMedia`) |
|
|
32
34
|
| `components/CartButton.jsx` | header cart **icon** button with a live-count badge |
|
|
33
35
|
| `components/CartDrawer.jsx` | slide-over cart (mount once; opens from `useCart`) |
|
|
34
|
-
| `hooks/useVariantOptions.js` | headless data layer for options/modifiers — returns `optionGroups` + `modifierGroups` (normalised, render-agnostic); **
|
|
35
|
-
| `components/VariantPicker.jsx` | reference implementation of a variant selector built on `useVariantOptions` (pills + colour swatches) — read it for inspiration, but build your own component rather than using it directly |
|
|
36
|
+
| `hooks/useVariantOptions.js` | headless data layer for options/modifiers — returns `optionGroups` + `modifierGroups` (normalised, render-agnostic); **your PDP's variant controls (STEP 3) render from it** |
|
|
36
37
|
| `components/WixManageBanner.jsx` | preview-only manage banner — drop it into your Layout (STEP 3) |
|
|
37
|
-
| `pages/Shop.jsx
|
|
38
|
+
| `pages/Shop.jsx` | the shipped `/shop` listing page — renders your `ProductGrid` (you build `/product/:slug` and `/`) |
|
|
38
39
|
| `rest/wix-config.js` | the two ids, written by the install step |
|
|
39
40
|
| `rest/wix-client.js` + `rest/wix-store-*.js` | REST transport + catalog/cart helpers |
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
Everything in the table is already in place — go **straight to wiring + building your presentation**
|
|
43
|
+
(card, grid, variant controls, the product page, Home — STEP 3), nothing to verify first.
|
|
44
|
+
**Don't `read_file` the shipped page/hook source to inspect it** — the table says what each is and
|
|
45
|
+
every field shape you need is in the outlines below. Read a shipped file's source **only** on a real
|
|
46
|
+
fallback — a runtime error, or a field the outlines don't cover (see "Fallback only" at the end).
|
|
47
|
+
(Shipped files missing? the install's `deploy` result lists what it wrote; re-run install, or copy
|
|
46
48
|
`references/storefront/app/` → `src/`.)
|
|
47
49
|
|
|
48
50
|
|
|
49
|
-
## STEP 2 — Theme
|
|
50
|
-
The shipped
|
|
51
|
+
## STEP 2 — Theme
|
|
52
|
+
The shipped pages carry **no palette of their own** — they render from base44's design tokens
|
|
51
53
|
in `src/index.css` (`:root`/`.dark`: `--background`, `--foreground`, `--card`, `--primary`,
|
|
52
54
|
`--muted`, `--border`, `--radius`, `--font-*`) via shadcn Tailwind classes (`bg-card`,
|
|
53
55
|
`text-foreground`, `bg-primary`, `text-muted-foreground`, `border-border`, `rounded-lg`,
|
|
54
56
|
`font-display`). Those tokens are **already set to the brand by the design phase**, so the shipped
|
|
55
57
|
pages are themed with zero work here. To adjust the palette, edit `index.css` (`:root` **and**
|
|
56
58
|
`.dark`) — the base44 way; **never add a parallel theme file (e.g. a `theme.css`) or restyle the
|
|
57
|
-
shipped
|
|
58
|
-
matches automatically. A dark brand is just base44's
|
|
59
|
+
shipped pages.** Style the components you build (STEP 3) and the Home/Header you add from the
|
|
60
|
+
**same** base44 tokens/classes so everything matches automatically. A dark brand is just base44's
|
|
61
|
+
dark palette in `index.css` — no per-component work.
|
|
59
62
|
|
|
60
63
|
## STEP 3 — Wire routes + provider (surgical `find_replace` on `src/App.jsx`, never a rewrite)
|
|
61
64
|
**No file reads needed to wire this.** Every shipped page and `WixManageBanner` is a default export that takes **no props** — wire them exactly as the snippet shows; nothing in those files needs looking up.
|
|
@@ -64,77 +67,126 @@ replace it.
|
|
|
64
67
|
- Wrap the routed tree in `<CartProvider>` (from `@/context/CartContext`).
|
|
65
68
|
- Put your **header + footer in a `Layout`** that renders `<Outlet/>` between them, and nest every
|
|
66
69
|
route under one pathless `<Route element={<Layout/>}>`. Your brand chrome then wraps **every** page
|
|
67
|
-
— including the shipped `Shop`
|
|
68
|
-
header/footer** (
|
|
70
|
+
— including the shipped `Shop` and your own pages — so you **never edit the shipped `Shop` to add a
|
|
71
|
+
header/footer** (it renders inside `<Outlet/>` as-is). Mount `<CartDrawer/>` once in the Layout.
|
|
69
72
|
- **Pin the top chrome as one fixed block.** Put `<WixManageBanner/>` (shipped, preview-only) **above**
|
|
70
73
|
your `<Header/>` inside a single `position:fixed` top region — the header itself is plain in-flow
|
|
71
74
|
markup, the region owns the fixing — so banner + header ride together (no scroll drift/gap). Pad
|
|
72
75
|
the content by the region's measured height so it clears the chrome and self-corrects when the
|
|
73
76
|
banner is dismissed.
|
|
74
|
-
- Routes under the Layout: `/shop` → `Shop
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
- Routes under the Layout: `/shop` → `Shop` (shipped, renders your grid); `/product/:slug` → **your
|
|
78
|
+
`ProductDetail`**; `/` → **your `Home`**.
|
|
79
|
+
|
|
80
|
+
**Build the presentation — it's all yours.** Each piece below is built on a shipped hook whose return
|
|
81
|
+
type + field shapes are in the outline right after this list — the data is done, the render is yours.
|
|
82
|
+
`Shop` won't show products until `ProductGrid` exists, and `/product/:slug` won't render until you
|
|
83
|
+
build the product page, so these aren't optional:
|
|
84
|
+
|
|
85
|
+
- **`components/ProductGrid.jsx`** — `Shop` and your Home render it. It receives `products`, `loading`,
|
|
86
|
+
`empty`, `emptyHint` and owns three states (loading, empty, list) plus the layout. A boutique might
|
|
87
|
+
want a 3-col editorial layout; a high-volume store a dense 4-col grid; a home strip a horizontal scroll.
|
|
88
|
+
- **`components/ProductCard.jsx`** — your grid maps each product to it. Built on `useProductCard`
|
|
89
|
+
(badges, price display, colour dots, quick-add flag, images) — you decide layout, shape, hover, CTA.
|
|
90
|
+
A lifestyle brand might want full-bleed images with an overlay gradient; a tech store a compact item.
|
|
91
|
+
- **`pages/ProductDetail.jsx`** — the **whole product page**, built on `useProductDetail`; route
|
|
92
|
+
`/product/:slug` to it. Gallery, price, description, the variant controls (options/modifiers via
|
|
93
|
+
`useVariantOptions`), the buy box — you arrange and style all of it (nothing PDP ships). This is the
|
|
94
|
+
surface that usually looks most generic, so make the layout the brand's: an editorial split, a sticky
|
|
95
|
+
buy column, a full-bleed gallery, large swatches vs a compact dropdown — your call.
|
|
79
96
|
|
|
80
97
|
```jsx
|
|
98
|
+
// components/ProductCard.jsx — your grid maps each product to it.
|
|
81
99
|
import { Link } from "react-router-dom";
|
|
82
|
-
import { useCart } from "@/context/CartContext";
|
|
100
|
+
import { useCart } from "@/context/CartContext"; // addToCart(product.id) for quick-add
|
|
83
101
|
import { useProductCard } from "@/hooks/useProductCard";
|
|
84
102
|
|
|
85
|
-
export default function
|
|
103
|
+
export default function ProductCard({ product }) {
|
|
86
104
|
const { addToCart } = useCart();
|
|
87
105
|
const {
|
|
88
106
|
isSoldOut, isPreorder,
|
|
89
|
-
leftBadges, // [{ type: 'pre-order'|'sold-out'|'limited-stock', label }] —
|
|
90
|
-
promoBadge, // { type: 'discount'|'ribbon', label } | null —
|
|
91
|
-
priceDisplay, // "€10"
|
|
92
|
-
compareAtDisplay, // original price string | null
|
|
93
|
-
colors, // hex strings →
|
|
94
|
-
optionLabel, // "3 sizes · 2 materials"
|
|
95
|
-
isQuickAddable, // true
|
|
96
|
-
image,
|
|
97
|
-
hoverImage, // second image URL | null
|
|
107
|
+
leftBadges, // [{ type: 'pre-order'|'sold-out'|'limited-stock', label }] — image top-left
|
|
108
|
+
promoBadge, // { type: 'discount'|'ribbon', label } | null — image top-right
|
|
109
|
+
priceDisplay, // "€10" | "€10 – €20" (range when variants differ)
|
|
110
|
+
compareAtDisplay, // original price string | null — strike-through
|
|
111
|
+
colors, // hex strings → colour dots
|
|
112
|
+
optionLabel, // "3 sizes · 2 materials" | ""
|
|
113
|
+
isQuickAddable, // true → addToCart(product.id); else <Link to={`/product/${product.slug}`}>
|
|
114
|
+
image, hoverImage,// URLs | null
|
|
98
115
|
} = useProductCard(product);
|
|
99
|
-
|
|
100
|
-
// Then render however you want:
|
|
101
|
-
return (
|
|
102
|
-
<div>
|
|
103
|
-
{/* image, badges, price, colour dots, quick-add or "Choose options" CTA */}
|
|
104
|
-
{isQuickAddable && <button onClick={() => addToCart(product.id)}>Quick add</button>}
|
|
105
|
-
{!isQuickAddable && !isSoldOut && <Link to={`/product/${product.slug}`}>Choose options</Link>}
|
|
106
|
-
{isSoldOut && isPreorder && <Link to={`/product/${product.slug}`}>Pre-order</Link>}
|
|
107
|
-
</div>
|
|
108
|
-
);
|
|
116
|
+
// …you implement the tile.
|
|
109
117
|
}
|
|
110
118
|
```
|
|
111
119
|
|
|
112
120
|
```jsx
|
|
121
|
+
// Variant controls — render the product's options/modifiers from useVariantOptions.
|
|
122
|
+
// The inputs (options, modifiers, selectedOptions, modifierValues) come from useProductDetail (below).
|
|
113
123
|
import { useVariantOptions } from "@/hooks/useVariantOptions";
|
|
114
124
|
|
|
115
|
-
// options/modifiers/selectedOptions/modifierValues come from useProductDetail:
|
|
116
125
|
const { optionGroups, modifierGroups } = useVariantOptions(options, modifiers, selectedOptions, modifierValues);
|
|
117
|
-
|
|
118
|
-
// optionGroups: [{ id, name, isColor, choices: [{ choiceId, name, colorCode, isColorSwatch, inStock, selected }] }]
|
|
126
|
+
// optionGroups: [{ id, name, isColor, choices: [{ choiceId, name, colorCode, isColorSwatch, inStock, selected }] }]
|
|
119
127
|
// modifierGroups: [{ key, name, mandatory, type: 'choices'|'text', choices?: [{ key, name, selected }], value?: string }]
|
|
128
|
+
// pick a choice: selectOption(group.id, choice.choiceId)
|
|
129
|
+
// set a modifier: setModifier(m.key, choice.key) · text type: setModifier(m.key, e.target.value)
|
|
130
|
+
```
|
|
120
131
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
132
|
+
```jsx
|
|
133
|
+
// components/ProductGrid.jsx — Shop and your Home render it.
|
|
134
|
+
import ProductCard from "./ProductCard"; // your card, above
|
|
135
|
+
|
|
136
|
+
export default function ProductGrid({ products, loading, empty, emptyHint }) {
|
|
137
|
+
// products — array | null (null while loading)
|
|
138
|
+
// loading — boolean
|
|
139
|
+
// empty — heading string for the no-products state
|
|
140
|
+
// emptyHint — sub-text string for the no-products state
|
|
141
|
+
// …you implement: the loading state, the empty state (empty + emptyHint), and the layout
|
|
142
|
+
// mapping products → <ProductCard product={p} />.
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```jsx
|
|
147
|
+
// pages/ProductDetail.jsx — YOU build the whole product page. Route `/product/:slug` to it.
|
|
148
|
+
// A thin view over useProductDetail: keep the data logic in the hook, render however fits the brand.
|
|
149
|
+
import { useMemo } from "react";
|
|
150
|
+
import { useParams, Link } from "react-router-dom";
|
|
151
|
+
import { useProductDetail } from "@/hooks/useProductDetail";
|
|
152
|
+
import { productGallery } from "@/lib/storeImage";
|
|
153
|
+
|
|
154
|
+
export default function ProductDetail() {
|
|
155
|
+
const { slug } = useParams();
|
|
156
|
+
const d = useProductDetail(slug);
|
|
157
|
+
// useProductDetail(slug) returns:
|
|
158
|
+
// product Wix product | null (loading) — has .name, .plainDescription (HTML), .slug
|
|
159
|
+
// notFound bool — dead link (distinct from error)
|
|
160
|
+
// error string | null — failed load; call retry() to reload
|
|
161
|
+
// retry () => void
|
|
162
|
+
// price formatted string, follows the selection ("€24.00")
|
|
163
|
+
// compareAtPrice formatted string — a "was" price; strike it only when it differs from price
|
|
164
|
+
// options, modifiers → feed useVariantOptions for the variant controls (block above)
|
|
165
|
+
// selectedOptions, selectOption, modifierValues, setModifier → also for the variant controls
|
|
166
|
+
// variant resolved variant | null (null until every option is picked)
|
|
167
|
+
// focusMediaUrl image url for the selected choice — make the gallery show it
|
|
168
|
+
// quantity, setQuantity(n) number (may be "" mid-edit) — keep min 1
|
|
169
|
+
// inStock, canAdd, adding booleans that gate the buy button
|
|
170
|
+
// submit async () => adds the resolved variant + quantity + modifiers to the cart
|
|
171
|
+
const images = useMemo(() => productGallery(d.product), [d.product]); // [{ url, altText }], main first, de-duped
|
|
172
|
+
|
|
173
|
+
// …you implement the page. Handle in order:
|
|
174
|
+
// error → show d.error + a retry button (onClick={d.retry})
|
|
175
|
+
// notFound → a "not found" message + a <Link to="/shop">
|
|
176
|
+
// !product → a loading placeholder
|
|
177
|
+
// else the product view, laid out to fit the brand:
|
|
178
|
+
// • gallery from `images` — main + thumbnails, a carousel, a full-bleed hero (your call);
|
|
179
|
+
// make the shown image follow d.focusMediaUrl when a choice is selected
|
|
180
|
+
// • d.product.name · d.price (strike d.compareAtPrice when it differs) ·
|
|
181
|
+
// d.product.plainDescription (HTML → dangerouslySetInnerHTML)
|
|
182
|
+
// • variant controls — render d.options/d.modifiers via useVariantOptions (block above);
|
|
183
|
+
// d.selectOption / d.setModifier update the selection
|
|
184
|
+
// • a "pick an option to continue" hint when d.options.length && !d.variant
|
|
185
|
+
// • a quantity control (d.quantity / d.setQuantity, min 1 — a −/+ stepper reads better than a
|
|
186
|
+
// native number input) + the buy button:
|
|
187
|
+
// <button disabled={!d.canAdd || d.adding} onClick={d.submit}>
|
|
188
|
+
// {d.adding ? "Adding…" : d.inStock ? "Add to cart" : "Out of stock"}</button>
|
|
189
|
+
}
|
|
138
190
|
```
|
|
139
191
|
|
|
140
192
|
```jsx
|
|
@@ -144,7 +196,7 @@ import { CartProvider } from "@/context/CartContext";
|
|
|
144
196
|
import CartDrawer from "@/components/CartDrawer";
|
|
145
197
|
import WixManageBanner from "@/components/WixManageBanner"; // shipped, preview-only · default export, no props
|
|
146
198
|
import Shop from "@/pages/Shop"; // shipped · default export, no props
|
|
147
|
-
import ProductDetail from "@/pages/ProductDetail"; //
|
|
199
|
+
import ProductDetail from "@/pages/ProductDetail"; // YOU build
|
|
148
200
|
import Home from "@/pages/Home"; // YOU build
|
|
149
201
|
import Header from "@/components/Header"; // YOU build — plain in-flow markup, NOT position:fixed
|
|
150
202
|
import Footer from "@/components/Footer"; // YOU build
|
|
@@ -163,7 +215,7 @@ function Layout() {
|
|
|
163
215
|
<Header /> {/* your brand header, in-flow inside this fixed block */}
|
|
164
216
|
</div>
|
|
165
217
|
<div style={{ paddingTop: offset }}> {/* clears the chrome; shrinks when the banner is dismissed */}
|
|
166
|
-
<Outlet /> {/* shipped Shop
|
|
218
|
+
<Outlet /> {/* shipped Shop + your pages render here */}
|
|
167
219
|
<Footer />
|
|
168
220
|
</div>
|
|
169
221
|
<CartDrawer /> {/* overlays every page */}
|
|
@@ -175,7 +227,7 @@ function Layout() {
|
|
|
175
227
|
<Route element={<Layout />}> {/* chrome wraps all */}
|
|
176
228
|
<Route path="/" element={<Home />} /> {/* yours */}
|
|
177
229
|
<Route path="/shop" element={<Shop />} /> {/* shipped, as-is */}
|
|
178
|
-
<Route path="/product/:slug" element={<ProductDetail />} /> {/*
|
|
230
|
+
<Route path="/product/:slug" element={<ProductDetail />} /> {/* yours */}
|
|
179
231
|
</Route>
|
|
180
232
|
</Routes>
|
|
181
233
|
</CartProvider>
|
|
@@ -184,8 +236,8 @@ function Layout() {
|
|
|
184
236
|
## What you build (not shipped)
|
|
185
237
|
The **home / landing page**, the **`Header`** (mount `<CartButton/>` in it) and a **`Footer`** — the
|
|
186
238
|
two you drop into the `Layout` (STEP 3) so they wrap every route — plus the overall brand story,
|
|
187
|
-
styled from the same base44 tokens/classes. **
|
|
188
|
-
featured strip is just `queryProducts` +
|
|
239
|
+
styled from the same base44 tokens/classes. **Reuse your own `ProductGrid`** (STEP 3) and the shipped
|
|
240
|
+
cart pieces — a featured strip is just `queryProducts` + your `ProductGrid`; the nav is a `<CartButton/>`
|
|
189
241
|
(a clean cart-**icon** button with a live-count badge — render it as-is, don't wrap it in your own
|
|
190
242
|
text button) + a link to `/shop`:
|
|
191
243
|
|
|
@@ -193,8 +245,8 @@ text button) + a link to `/shop`:
|
|
|
193
245
|
import { useState, useEffect } from "react";
|
|
194
246
|
import { Link } from "react-router-dom";
|
|
195
247
|
import { queryProducts } from "@/rest/wix-store-catalog";
|
|
196
|
-
import ProductGrid from "@/components/ProductGrid";
|
|
197
|
-
import CartButton from "@/components/CartButton";
|
|
248
|
+
import ProductGrid from "@/components/ProductGrid"; // yours (STEP 3)
|
|
249
|
+
import CartButton from "@/components/CartButton"; // shipped
|
|
198
250
|
|
|
199
251
|
// Responsive header: choose ONE branch with a state flag, so <CartButton/> mounts once.
|
|
200
252
|
// Do NOT render a desktop nav AND a mobile nav toggled by `hidden md:flex` / `md:hidden`:
|
|
@@ -237,6 +289,8 @@ render.
|
|
|
237
289
|
|
|
238
290
|
## Using the client from your own UI (cart, hand-built images)
|
|
239
291
|
|
|
292
|
+
> Migrating from Cart V1 / Checkout V1? These helpers are V2-only — see the [migration guide](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/migration-guide) for the before/after.
|
|
293
|
+
|
|
240
294
|
```jsx
|
|
241
295
|
import { Link } from "react-router-dom";
|
|
242
296
|
import { useCart } from "@/context/CartContext";
|
|
@@ -246,22 +300,27 @@ import { useCart } from "@/context/CartContext";
|
|
|
246
300
|
// addToCart(productId, variantId?, qty=1, { modifierChoices?, customTextFields? }?),
|
|
247
301
|
// removeItem(lineItemId), updateQuantity(lineItemId, qty), checkout(), refreshCart() }
|
|
248
302
|
// Every mutation catches its own failure into `error` (the shipped CartDrawer renders it), so a
|
|
249
|
-
// refusal — an empty cart, or a line item
|
|
303
|
+
// refusal — an empty cart, or a line item whose status left IN_STOCK — reaches the buyer instead
|
|
250
304
|
// of becoming an unhandled rejection.
|
|
251
305
|
//
|
|
252
|
-
// Cart money: every amount is { amount, convertedAmount
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
//
|
|
256
|
-
//
|
|
257
|
-
// `
|
|
306
|
+
// Cart money: every amount is a ConvertedMoney { amount, convertedAmount } with NO formatted string —
|
|
307
|
+
// `amount` is in the site currency, `convertedAmount` in the display currency; format the number
|
|
308
|
+
// yourself (Intl.NumberFormat with the cart's currency —
|
|
309
|
+
// `cart.customerInfo?.currencyCode ?? cart.businessInfo?.currencyCode`) so the symbol and grouping
|
|
310
|
+
// match the locale. The V2 cart has no `subtotalAfterDiscounts`/`discount`/`appliedDiscounts`: it
|
|
311
|
+
// carries only a raw `cart.subtotal` (ConvertedMoney). The authoritative discounted totals come from
|
|
312
|
+
// a currentCartV2 estimate/calculate `summary.priceSummary`, not the cart — call that when you need
|
|
313
|
+
// the after-coupon figure; otherwise show `cart.subtotal`. Never sum line items yourself — tax and
|
|
314
|
+
// shipping resolve at checkout.
|
|
315
|
+
// A line's `status` (IN_STOCK / PARTIALLY_IN_STOCK / OUT_OF_STOCK) tells a quantity control whether
|
|
316
|
+
// another increment is still fulfillable.
|
|
258
317
|
|
|
259
318
|
function CartCount() { // header badge
|
|
260
319
|
const { itemCount, setIsOpen } = useCart();
|
|
261
320
|
return <button onClick={() => setIsOpen(true)}>Cart ({itemCount})</button>;
|
|
262
321
|
}
|
|
263
322
|
|
|
264
|
-
// Buy from a card → link to the PDP;
|
|
323
|
+
// Buy from a card → link to the PDP; your ProductDetail (on useProductDetail) owns options/variants + add-to-cart.
|
|
265
324
|
// (Listing helpers return no variants — only getProductBySlug does — so buying happens on the PDP.)
|
|
266
325
|
const CardBuy = ({ product }) => <Link to={`/product/${product.slug}`}>View</Link>;
|
|
267
326
|
|
|
@@ -294,7 +353,7 @@ const { products: inCategory } = await queryProductsByCategory(menu[0].id, { lim
|
|
|
294
353
|
|
|
295
354
|
// product.plainDescription is HTML → render as HTML (the PDP does this):
|
|
296
355
|
<div dangerouslySetInnerHTML={{ __html: product.plainDescription }} />
|
|
297
|
-
// image urls live at: product.media.main.image.url · cart lineItems[].image.url
|
|
356
|
+
// image urls live at: product.media.main.image.url · cart lineItems[].attributes.image.url
|
|
298
357
|
```
|
|
299
358
|
|
|
300
359
|
Fallback only — when you hit an error or need something not shown here (coupons, members, a field
|
|
@@ -306,8 +365,8 @@ reference page inline; these are the areas they sit in:
|
|
|
306
365
|
- Headless redirect session (hosted checkout): https://dev.wix.com/docs/api-reference/business-management/headless/redirects.md
|
|
307
366
|
|
|
308
367
|
## Hard rules
|
|
309
|
-
- Style via base44 design tokens (`index.css` / shadcn Tailwind classes), never by rewriting the shipped
|
|
310
|
-
- Header/footer live in a `Layout` around `<Outlet/>` (STEP 3) — never edit the shipped `Shop
|
|
368
|
+
- Style via base44 design tokens (`index.css` / shadcn Tailwind classes), never by rewriting the shipped pages or adding a parallel theme file. Everything you build (card, grid, PDP, variant controls, Home) draws from the same tokens.
|
|
369
|
+
- Header/footer live in a `Layout` around `<Outlet/>` (STEP 3) — never edit the shipped `Shop` to add chrome.
|
|
311
370
|
- The Layout's fixed top region owns positioning: `<WixManageBanner/>` above `<Header/>`; your `Header` is plain in-flow markup (not `position:fixed`).
|
|
312
371
|
- Checkout goes through the shipped cart (redirect-session) — never a hand-built `/checkout` URL.
|
|
313
372
|
- Render live Wix data or the shipped empty state — never mock products.
|
|
@@ -323,9 +382,10 @@ client build; run in parallel.
|
|
|
323
382
|
|
|
324
383
|
## Verify (before declaring done)
|
|
325
384
|
- [ ] Client files copied into `src/`; `WIX_CLIENT_ID` set (not the placeholder).
|
|
326
|
-
- [ ]
|
|
327
|
-
- [ ]
|
|
328
|
-
- [ ] `
|
|
385
|
+
- [ ] **The pieces you own exist and are wired:** `components/ProductCard.jsx`, `components/ProductGrid.jsx` (imported by `Shop` + your Home), and `pages/ProductDetail.jsx` (routed at `/product/:slug`, with working variant controls). `/shop` and a PDP compile and render (they won't until these exist).
|
|
386
|
+
- [ ] Brand palette lives in `index.css` (`:root`/`.dark`); no parallel theme file; the shipped `Shop` page not restyled or rewritten.
|
|
387
|
+
- [ ] **Opened `/shop` and a product detail page** (not just the home page) and confirmed your cards render themed (surface, text, brand color) with images; the grid shows its loading + empty states; the PDP shows the gallery, price, variant controls, and add-to-cart, and its error/not-found/loading states hold.
|
|
388
|
+
- [ ] `Layout` (fixed `<WixManageBanner/>` + `<Header/>` region, then `<Outlet/>` + Footer) wraps all routes; the shipped `Shop` untouched; content clears the fixed chrome; `<CartProvider>` wraps the tree; `<CartDrawer/>` mounted; `<CartButton/>` in the header.
|
|
329
389
|
- [ ] Cart survives reload (same visitor); add / update-qty / remove work; checkout redirects; the drawer shows a **subtotal**.
|
|
330
390
|
- [ ] Empty catalog shows the shipped empty state; no mock products anywhere.
|
|
331
391
|
- [ ] A product with several images shows **thumbnails** on the PDP, and one with per-variant prices shows a **range** on its card.
|
|
@@ -2,29 +2,36 @@
|
|
|
2
2
|
// check out via the context (redirect-session URL). Styled with base44 design tokens (shadcn Tailwind classes).
|
|
3
3
|
//
|
|
4
4
|
// Load-bearing beyond the styling:
|
|
5
|
-
// • prices come from the SERVER cart
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// • `
|
|
5
|
+
// • prices come from the SERVER cart. In Cart V2 each line total is `pricing.totalPrice`, a
|
|
6
|
+
// ConvertedMoney { amount, convertedAmount } with NO formatted string — format it yourself with the
|
|
7
|
+
// cart's currency (see formatCartMoney). Never compute a total in the client: tax, shipping and
|
|
8
|
+
// promotions are resolved server-side, so the cart's `subtotal` is the only figure safe to show
|
|
9
|
+
// pre-checkout. The V2 cart has no `subtotalAfterDiscounts`/`discount`/`appliedDiscounts` — the
|
|
10
|
+
// discounted total comes from a currentCartV2 estimate/calculate `summary.priceSummary`, not the
|
|
11
|
+
// cart; absent that call, show the raw `subtotal`.
|
|
12
|
+
// • `quantityInfo.availableQuantity` caps the stepper, so exceeding stock is refused here rather than
|
|
13
13
|
// at checkout.
|
|
14
|
-
// • `
|
|
15
|
-
//
|
|
14
|
+
// • `status` is flagged per line here because checkout() refuses the whole cart when any item isn't
|
|
15
|
+
// IN_STOCK — showing it on the row is what makes that refusal understandable.
|
|
16
16
|
import { useEffect } from "react";
|
|
17
17
|
import { useCart } from "@/context/CartContext";
|
|
18
18
|
import { storeImage } from "@/lib/storeImage";
|
|
19
19
|
|
|
20
|
+
// Cart V2 money is a ConvertedMoney { amount, convertedAmount } with NO formatted string — format it
|
|
21
|
+
// with the cart's currency (buyer's display currency when present, else the site currency).
|
|
22
|
+
function formatCartMoney(money, cart) {
|
|
23
|
+
const value = money?.convertedAmount ?? money?.amount;
|
|
24
|
+
const currency = cart?.customerInfo?.currencyCode ?? cart?.businessInfo?.currencyCode ?? "USD";
|
|
25
|
+
return value == null ? "" : new Intl.NumberFormat(undefined, { style: "currency", currency }).format(Number(value));
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
export default function CartDrawer() {
|
|
21
29
|
const { cart, isOpen, setIsOpen, removeItem, updateQuantity, checkout, loading, error, clearError } = useCart();
|
|
22
30
|
const lineItems = cart?.lineItems ?? [];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const unavailable = lineItems.filter((li) => li.availability?.status && li.availability.status !== "AVAILABLE");
|
|
31
|
+
// The V2 cart carries only a raw `subtotal` (ConvertedMoney); discounted totals live on an
|
|
32
|
+
// estimate/calculate `summary.priceSummary`, which this cart helper doesn't fetch — so show `subtotal`.
|
|
33
|
+
const subtotal = formatCartMoney(cart?.subtotal, cart);
|
|
34
|
+
const unavailable = lineItems.filter((li) => li.status && li.status !== "IN_STOCK");
|
|
28
35
|
|
|
29
36
|
// Escape closes the drawer while it's open — expected of anything modal, and the only way out for
|
|
30
37
|
// keyboard users (the backdrop click is pointer-only).
|
|
@@ -70,46 +77,44 @@ export default function CartDrawer() {
|
|
|
70
77
|
className="border border-border bg-card text-foreground rounded-sm py-2 px-4 cursor-pointer text-sm">Continue shopping</button>
|
|
71
78
|
</div>
|
|
72
79
|
) : lineItems.map((item) => {
|
|
73
|
-
const image = storeImage(item.image?.url);
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const atStockLimit = Number.isFinite(stock) &&
|
|
80
|
+
const image = storeImage(item.attributes?.image?.url);
|
|
81
|
+
const paid = formatCartMoney(item.pricing?.totalPrice, cart);
|
|
82
|
+
const isOut = item.status && item.status !== "IN_STOCK";
|
|
83
|
+
const stock = item.quantityInfo?.availableQuantity;
|
|
84
|
+
const qty = item.quantityInfo?.confirmedQuantity;
|
|
85
|
+
const atStockLimit = Number.isFinite(stock) && qty >= stock;
|
|
79
86
|
return (
|
|
80
87
|
<div key={item.id} className="flex gap-3 py-3 px-0 border-b border-border">
|
|
81
88
|
<div className="w-16 h-16 shrink-0 rounded-sm bg-card overflow-hidden">
|
|
82
|
-
{image && <img src={image} alt={item.
|
|
89
|
+
{image && <img src={image} alt={item.name?.original || ""} className="w-full h-full object-cover" />}
|
|
83
90
|
</div>
|
|
84
91
|
<div className="flex-1 flex flex-col gap-1 min-w-0">
|
|
85
|
-
<span className="font-semibold truncate">{item.
|
|
86
|
-
{
|
|
92
|
+
<span className="font-semibold truncate">{item.name?.original}</span>
|
|
93
|
+
{/* V2 nests these under `attributes` — a top-level lineItem.descriptionLines no longer exists */}
|
|
94
|
+
{item.attributes?.descriptionLines?.map((dl, i) => (
|
|
87
95
|
<small key={i} className="text-muted-foreground">
|
|
88
96
|
{dl.name?.original}: {dl.plainText?.original || dl.colorInfo?.original}
|
|
89
97
|
</small>
|
|
90
98
|
))}
|
|
91
99
|
{isOut ? (
|
|
92
100
|
<small className="text-destructive">
|
|
93
|
-
{item.
|
|
101
|
+
{item.status === "PARTIALLY_IN_STOCK" ? "Not enough stock" : "No longer available"}
|
|
94
102
|
</small>
|
|
95
103
|
) : atStockLimit ? (
|
|
96
104
|
<small className="text-muted-foreground">Only {stock} left</small>
|
|
97
105
|
) : null}
|
|
98
106
|
<div className="flex items-center gap-2 mt-1">
|
|
99
|
-
<QtyButton disabled={loading ||
|
|
100
|
-
onClick={() => updateQuantity(item.id,
|
|
101
|
-
<span className="min-w-5 text-center" aria-label={`Quantity ${
|
|
107
|
+
<QtyButton disabled={loading || qty <= 1} label="Decrease quantity"
|
|
108
|
+
onClick={() => updateQuantity(item.id, qty - 1)}>−</QtyButton>
|
|
109
|
+
<span className="min-w-5 text-center" aria-label={`Quantity ${qty}`}>{qty}</span>
|
|
102
110
|
<QtyButton disabled={loading || atStockLimit} label="Increase quantity"
|
|
103
|
-
onClick={() => updateQuantity(item.id,
|
|
111
|
+
onClick={() => updateQuantity(item.id, qty + 1)}>+</QtyButton>
|
|
104
112
|
<button onClick={() => removeItem(item.id)} disabled={loading}
|
|
105
113
|
className="ml-auto border-none bg-transparent cursor-pointer text-muted-foreground text-[13px] underline disabled:opacity-50">Remove</button>
|
|
106
114
|
</div>
|
|
107
115
|
</div>
|
|
108
116
|
<div className="flex flex-col items-end shrink-0">
|
|
109
117
|
<span className="font-semibold">{paid}</span>
|
|
110
|
-
{struck && struck !== paid && (
|
|
111
|
-
<span className="text-muted-foreground line-through text-[13px]">{struck}</span>
|
|
112
|
-
)}
|
|
113
118
|
</div>
|
|
114
119
|
</div>
|
|
115
120
|
);
|
|
@@ -118,12 +123,6 @@ export default function CartDrawer() {
|
|
|
118
123
|
|
|
119
124
|
{lineItems.length > 0 && (
|
|
120
125
|
<footer className="p-4 border-t border-border flex flex-col gap-3">
|
|
121
|
-
{hasDiscount && (
|
|
122
|
-
<div className="flex justify-between items-baseline text-sm">
|
|
123
|
-
<span className="text-muted-foreground">Discount</span>
|
|
124
|
-
<span>−{discount}</span>
|
|
125
|
-
</div>
|
|
126
|
-
)}
|
|
127
126
|
{subtotal && (
|
|
128
127
|
<div className="flex justify-between items-baseline">
|
|
129
128
|
<span className="text-muted-foreground">Subtotal</span>
|
|
@@ -16,7 +16,7 @@ export function CartProvider({ children }) {
|
|
|
16
16
|
const [isOpen, setIsOpen] = useState(false);
|
|
17
17
|
const [loading, setLoading] = useState(false);
|
|
18
18
|
// The cart helpers throw on refusal with a buyer-readable reason — an empty cart, or line items
|
|
19
|
-
// whose
|
|
19
|
+
// whose status isn't IN_STOCK. Hold the message so the drawer can show it; without
|
|
20
20
|
// this the rejection is unhandled and the shopper sees the spinner stop with nothing said.
|
|
21
21
|
const [error, setError] = useState(null);
|
|
22
22
|
|
|
@@ -28,7 +28,7 @@ export function CartProvider({ children }) {
|
|
|
28
28
|
return () => document.removeEventListener("visibilitychange", onVisible);
|
|
29
29
|
}, [refreshCart]);
|
|
30
30
|
|
|
31
|
-
const itemCount = (cart?.lineItems ?? []).reduce((n, li) => n + (li.
|
|
31
|
+
const itemCount = (cart?.lineItems ?? []).reduce((n, li) => n + (li.quantityInfo?.confirmedQuantity || 0), 0);
|
|
32
32
|
|
|
33
33
|
// Every mutation runs through here so a rejection always lands somewhere visible. `run` keeps the
|
|
34
34
|
// cart untouched on failure — the server stays the source of truth — and re-reads it for anything
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// renders what this returns.
|
|
6
6
|
import { useState, useEffect, useMemo } from "react";
|
|
7
7
|
import { getProductBySlug } from "@/rest/wix-store-catalog";
|
|
8
|
-
import {
|
|
8
|
+
import { choiceImage, variantImage } from "@/lib/storeImage";
|
|
9
9
|
import { useCart } from "@/context/CartContext";
|
|
10
10
|
|
|
11
11
|
export function useProductDetail(slug) {
|
|
@@ -61,19 +61,26 @@ export function useProductDetail(slug) {
|
|
|
61
61
|
m.modifierRenderType === "FREE_TEXT" ? !!modifierValues[m.freeTextSettings?.key] : !!modifierValues[m.key]);
|
|
62
62
|
}, [options, variant, inStock, modifiers, modifierValues]);
|
|
63
63
|
|
|
64
|
+
// Everything the buyer sees follows the resolved `variant` (also returned below, so an agent can
|
|
65
|
+
// surface more from it — sku, barcode, subscriptionPricesInfo — without new plumbing). Price and
|
|
66
|
+
// its struck-through "was" price come off the variant, falling back to the product's range before
|
|
67
|
+
// every option is picked.
|
|
64
68
|
const price = variant?.price?.actualPrice?.formattedAmount || product?.actualPriceRange?.minValue?.formattedAmount || "";
|
|
69
|
+
const compareAtPrice = variant?.price?.compareAtPrice?.formattedAmount || product?.compareAtPriceRange?.minValue?.formattedAmount || "";
|
|
65
70
|
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
71
|
+
// The gallery follows the selection. Prefer the selected choice's own image (the per-swatch photo,
|
|
72
|
+
// choice.media.items[].mediaId) — Wix's per-variant media is often NOT differentiated (it defaults to
|
|
73
|
+
// the product's main image), so preferring the variant would override the correct choice image for
|
|
74
|
+
// every colour. Fall back to the resolved variant's image only when no chosen option carries one.
|
|
75
|
+
// See lib/storeImage: choiceImage() / variantImage().
|
|
69
76
|
const focusMediaUrl = useMemo(() => {
|
|
70
77
|
for (const o of options) {
|
|
71
78
|
const choice = (o.choicesSettings?.choices || []).find((c) => c.choiceId === selectedOptions[o.id]);
|
|
72
|
-
const url =
|
|
79
|
+
const url = choiceImage(choice);
|
|
73
80
|
if (url) return url;
|
|
74
81
|
}
|
|
75
|
-
return
|
|
76
|
-
}, [options, selectedOptions]);
|
|
82
|
+
return variantImage(variant);
|
|
83
|
+
}, [variant, options, selectedOptions]);
|
|
77
84
|
|
|
78
85
|
const selectOption = (optionId, choiceId) => setSelectedOptions((s) => ({ ...s, [optionId]: choiceId }));
|
|
79
86
|
const setModifier = (key, value) => setModifierValues((s) => ({ ...s, [key]: value }));
|
|
@@ -104,6 +111,6 @@ export function useProductDetail(slug) {
|
|
|
104
111
|
product, notFound, error, retry: () => setReloadKey((k) => k + 1),
|
|
105
112
|
options, modifiers,
|
|
106
113
|
selectedOptions, selectOption, modifierValues, setModifier,
|
|
107
|
-
quantity, setQuantity, variant, inStock, canAdd, adding, price, submit, focusMediaUrl,
|
|
114
|
+
quantity, setQuantity, variant, inStock, canAdd, adding, price, compareAtPrice, submit, focusMediaUrl,
|
|
108
115
|
};
|
|
109
116
|
}
|