@wix/agent-skills 1.15.1 → 1.16.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/README.md +3 -7
- package/package.json +1 -1
- package/skills/wix-app/SKILL.md +4 -1
- package/skills/wix-app/references/APP_TOOLS.md +134 -0
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +1 -1
- package/skills/wix-app/references/DASHBOARD_PAGE.md +0 -10
- package/skills/wix-app/references/DATA_COLLECTION.md +1 -1
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +28 -9
- package/skills/wix-app/references/SERVICE_PLUGIN.md +12 -10
- package/skills/wix-app/references/app-tools/TOOLS.md +75 -0
- package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +2 -2
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +172 -0
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +138 -0
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +23 -2
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +29 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +1 -1
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +27 -2
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +5 -3
- package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +18 -1
- package/skills/wix-app/references/editor-react-component/PARTS.md +15 -2
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +2 -3
- package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +13 -9
- package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +4 -0
- package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
- package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +3 -1
- package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +4 -0
- package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +54 -0
- package/skills/wix-app/references/stores/QUERY.md +32 -0
- package/skills/wix-docs/SKILL.md +35 -3
- package/skills/wix-headless/SKILL.md +3 -1
- package/skills/wix-headless/references/CONTENT.md +36 -0
- package/skills/wix-headless/references/DESIGN.md +54 -0
- package/skills/wix-headless/references/DISCOVERY.md +24 -0
- package/skills/wix-headless/references/IMAGE_GENERATION.md +10 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +3 -2
- package/skills/wix-headless/references/inline-recipes/setup-online-store.md +32 -23
- package/skills/wix-headless/references/managed/CONNECT.md +1 -1
- package/skills/wix-headless/references/managed/CREATE.md +14 -0
- package/skills/wix-headless/references/managed/DEPLOYMENT.md +25 -0
- package/skills/wix-manage/SKILL.md +123 -7
- package/skills/wix-manage/references/analytics/analytics-dashboard-navigation.md +41 -0
- package/skills/wix-manage/references/app-installation/app-installation-dashboard-navigation.md +28 -0
- package/skills/wix-manage/references/blog/blog-dashboard-navigation.md +56 -0
- package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +31 -6
- package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -1
- package/skills/wix-manage/references/bookings/bookings-dashboard-navigation.md +63 -0
- package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +10 -1
- package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +44 -0
- package/skills/wix-manage/references/cms/cms-data-items-crud.md +31 -3
- package/skills/wix-manage/references/cms/cms-publishing-flow.md +287 -0
- package/skills/wix-manage/references/cms/cms-schema-management.md +27 -1
- package/skills/wix-manage/references/contacts/contacts-dashboard-navigation.md +46 -0
- package/skills/wix-manage/references/contacts/create-a-contact.md +82 -0
- package/skills/wix-manage/references/contacts/update-a-contact.md +119 -0
- package/skills/wix-manage/references/dashboard-navigation/dashboard-navigation.md +82 -0
- package/skills/wix-manage/references/dashboard-navigation/routes.json +1733 -0
- package/skills/wix-manage/references/domains/domains-dashboard-navigation.md +32 -0
- package/skills/wix-manage/references/ecommerce/ecom-pricing.md +4 -4
- package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
- package/skills/wix-manage/references/ecommerce/gift-cards/ecom-gift-cards-goal-sell-gift-cards.md +338 -0
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md +42 -78
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-bundle-and-save.md +1 -1
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md +1 -1
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md +1 -1
- package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +90 -92
- package/skills/wix-manage/references/events/create-wix-event.md +176 -0
- package/skills/wix-manage/references/events/manage-wix-events.md +174 -0
- package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +44 -0
- package/skills/wix-manage/references/get-paid/get-paid-dashboard-navigation.md +52 -0
- package/skills/wix-manage/references/google-ads/billing-and-payment.md +80 -0
- package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +212 -0
- package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +110 -0
- package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +25 -0
- package/skills/wix-manage/references/google-ads/install-and-create-account.md +155 -0
- package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +63 -0
- package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +155 -0
- package/skills/wix-manage/references/marketing/marketing-dashboard-navigation.md +52 -0
- package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +99 -1
- package/skills/wix-manage/references/pricing-plans/pricing-plans-dashboard-navigation.md +45 -0
- package/skills/wix-manage/references/restaurants/restaurants-dashboard-navigation.md +68 -0
- package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +94 -125
- package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +48 -9
- package/skills/wix-manage/references/site-properties/site-properties-dashboard-navigation.md +31 -0
- package/skills/wix-manage/references/sites/create-headless-site.md +52 -0
- package/skills/wix-manage/references/sites/create-site-from-template.md +2 -25
- package/skills/wix-manage/references/sites/site-import.md +163 -190
- package/skills/wix-manage/references/sites/sites-dashboard-navigation.md +29 -0
- package/skills/wix-manage/references/stores/add-store-pages-to-site.md +17 -1
- package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +26 -8
- package/skills/wix-manage/references/stores/stores-dashboard-navigation.md +65 -0
- package/skills/wix-manage/references/stores/update-product-with-options.md +39 -7
- package/skills/wix-replatform/.publish-manifest.json +8 -0
- package/skills/wix-replatform/SKILL.md +693 -0
- package/skills/wix-replatform/lib/artifact-freshness.js +215 -0
- package/skills/wix-replatform/lib/completion-report.js +200 -0
- package/skills/wix-replatform/lib/config-env.js +59 -0
- package/skills/wix-replatform/lib/execution-manifest.js +185 -0
- package/skills/wix-replatform/lib/execution-state.js +173 -0
- package/skills/wix-replatform/lib/import-recovery.js +313 -0
- package/skills/wix-replatform/lib/local-state.js +642 -0
- package/skills/wix-replatform/lib/orchestration-preflight.js +143 -0
- package/skills/wix-replatform/lib/orchestration-router.js +122 -0
- package/skills/wix-replatform/lib/orchestration-state.js +455 -0
- package/skills/wix-replatform/lib/progress-log.js +224 -0
- package/skills/wix-replatform/lib/progress-log.sh +140 -0
- package/skills/wix-replatform/lib/url-preservation-state.js +391 -0
- package/skills/wix-replatform/resources/rp-discovery/SKILL.md +184 -0
- package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +529 -0
- package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +316 -0
- package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +64 -0
- package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +1114 -0
- package/skills/wix-replatform/resources/rp-mapper/SKILL.md +430 -0
- package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +217 -0
- package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +148 -0
- package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +378 -0
- package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +183 -0
- package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +478 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +136 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +310 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +1081 -0
- package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +618 -0
- package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +949 -0
- package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +196 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +66 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +60 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +95 -0
- package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +82 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +256 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +249 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +444 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +774 -0
- package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +71 -0
- package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +632 -0
- package/skills/wix-replatform/resources/rp-target-wix/SPEC-product-reviews-and-blog-authorship.md +330 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +21 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +19 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +39 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +35 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +14 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +35 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +36 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +35 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +14 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +131 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +21 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +97 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +528 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +14 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +38 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +13 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +53 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +84 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +25 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +38 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +37 -0
- package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +90 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +64 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +141 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +384 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +260 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +238 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +237 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +238 -0
- package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +2219 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +31 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +100 -0
- package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +107 -0
- package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +344 -0
- package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +250 -0
- package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +1927 -0
- package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +83 -0
- package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +141 -0
- package/skills/wix-replatform/scripts/artifact-freshness.js +76 -0
- package/skills/wix-replatform/scripts/execution-manifest-validate.js +43 -0
- package/skills/wix-replatform/scripts/execution-state-prepare.js +128 -0
- package/skills/wix-replatform/scripts/orchestration-preflight.js +48 -0
- package/skills/wix-replatform/scripts/orchestration-route.js +46 -0
- package/skills/wix-replatform/scripts/orchestration-state.js +245 -0
- package/skills/wix-vibe-headless/SKILL.md +48 -25
- package/skills/wix-vibe-headless/install/deploy.cjs +95 -0
- package/skills/wix-vibe-headless/install/pin-agents-md.cjs +34 -0
- package/skills/wix-vibe-headless/platforms/README.md +8 -4
- package/skills/wix-vibe-headless/platforms/base44.md +133 -98
- package/skills/wix-vibe-headless/platforms/generic.md +99 -64
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +230 -119
- package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +43 -0
- package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +25 -0
- package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +15 -0
- package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +35 -0
- package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +38 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +40 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +54 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +65 -0
- package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +50 -0
- package/skills/wix-vibe-headless/references/blog/seed/SEED.md +103 -0
- package/skills/wix-vibe-headless/references/blog/seed/seed-blog.js +270 -0
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +260 -149
- package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +65 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +47 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +13 -0
- package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +126 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +108 -0
- package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +58 -0
- package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +95 -0
- package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +94 -0
- package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +89 -0
- package/skills/wix-vibe-headless/references/bookings/{wix-bookings-checkout.js → app/rest/wix-bookings-checkout.js} +1 -1
- package/skills/wix-vibe-headless/references/bookings/{wix-bookings-services.js → app/rest/wix-bookings-services.js} +87 -11
- package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +117 -0
- package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.js +333 -0
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +169 -147
- package/skills/wix-vibe-headless/references/cms/app/collection.config.js +31 -0
- package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +18 -0
- package/skills/wix-vibe-headless/references/cms/{wix-cms.js → app/rest/wix-cms.js} +47 -2
- package/skills/wix-vibe-headless/references/cms/seed/SEED.md +145 -0
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +228 -131
- package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +23 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +43 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +13 -0
- package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +29 -0
- package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +57 -0
- package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +78 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +27 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +54 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +40 -0
- package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +81 -0
- package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +48 -0
- package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +36 -0
- package/skills/wix-vibe-headless/references/events/{wix-events-browse.js → app/rest/wix-events-browse.js} +1 -1
- package/skills/wix-vibe-headless/references/events/seed/SEED.md +107 -0
- package/skills/wix-vibe-headless/references/events/seed/seed-events.js +251 -0
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +276 -188
- package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +101 -0
- package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +33 -0
- package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +21 -0
- package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +29 -0
- package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +54 -0
- package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +77 -0
- package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +36 -0
- package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +32 -0
- package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +35 -0
- package/skills/wix-vibe-headless/references/members/{wix-members-auth.js → app/rest/wix-members-auth.js} +6 -3
- package/skills/wix-vibe-headless/references/members/install/Register.jsx +22 -0
- package/skills/wix-vibe-headless/references/members/seed/SEED.md +22 -0
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +233 -104
- package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +31 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +15 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +39 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +15 -0
- package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +29 -0
- package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +35 -0
- package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +27 -0
- package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +25 -0
- package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +39 -0
- package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +27 -0
- package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +60 -0
- package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +94 -0
- package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js +236 -0
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +240 -117
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +35 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +48 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +16 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +35 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +25 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +28 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +30 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +30 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +53 -0
- package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +28 -0
- package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +86 -0
- package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.js +251 -0
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +248 -124
- package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +81 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +71 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +43 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +21 -0
- package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +60 -0
- package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +63 -0
- package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +32 -0
- package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +73 -0
- package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +28 -0
- package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +102 -0
- package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +180 -0
- package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.js +452 -0
- package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +56 -0
- package/skills/wix-vibe-headless/references/shared/{wix-client.js → app/rest/wix-client.js} +6 -8
- package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +6 -0
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +263 -157
- package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +20 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +150 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +167 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +51 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +54 -0
- package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +119 -0
- package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +71 -0
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +109 -0
- package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +98 -0
- package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +27 -0
- package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +139 -0
- package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +75 -0
- package/skills/wix-vibe-headless/references/storefront/{wix-store-cart.js → app/rest/wix-store-cart.js} +1 -1
- package/skills/wix-vibe-headless/references/storefront/{wix-store-catalog.js → app/rest/wix-store-catalog.js} +20 -1
- package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +111 -0
- package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +299 -0
- /package/skills/wix-vibe-headless/references/blog/{wix-blog.js → app/rest/wix-blog.js} +0 -0
- /package/skills/wix-vibe-headless/references/events/{wix-events-registration.js → app/rest/wix-events-registration.js} +0 -0
- /package/skills/wix-vibe-headless/references/portfolio/{wix-portfolio.js → app/rest/wix-portfolio.js} +0 -0
- /package/skills/wix-vibe-headless/references/pricing-plans/{wix-pricing-plans.js → app/rest/wix-pricing-plans.js} +0 -0
- /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-menu.js → app/rest/wix-restaurants-menu.js} +0 -0
- /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-ordering.js → app/rest/wix-restaurants-ordering.js} +0 -0
- /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-reservations.js → app/rest/wix-restaurants-reservations.js} +0 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
// Restaurants seed helpers — run at BUILD TIME via exec_tool (NOT shipped in the app).
|
|
2
|
+
// The agent requires this and calls the functions with plain data; all Wix Restaurants
|
|
3
|
+
// request/response mechanics (bottom-up items→sections→menu, the priceInfo decimal-string rule,
|
|
4
|
+
// the visible:true-at-every-level rule, the full-replace image PATCH, the per-micro-service host
|
|
5
|
+
// prefixes for ordering, the premium/address preconditions) live here, once.
|
|
6
|
+
//
|
|
7
|
+
// Usage (build-time exec_tool):
|
|
8
|
+
// const { accessToken } = await base44.asServiceRole.connectors.getConnection("wix"); // Base44 (generic: use $TOKEN)
|
|
9
|
+
// const seed = require("/app/.agents/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.js");
|
|
10
|
+
// const ctx = { token: accessToken, siteId: WIX_METASITE_ID };
|
|
11
|
+
//
|
|
12
|
+
// // --- MENU (always; the seedable core) ---
|
|
13
|
+
// await seed.installMenusApp(ctx); // if the site doesn't have Wix Restaurants Menus yet
|
|
14
|
+
// const menu = await seed.createMenu(ctx, { // builds items → sections → menu bottom-up
|
|
15
|
+
// name: "Dinner", description: "Evening menu",
|
|
16
|
+
// sections: [
|
|
17
|
+
// { name: "Antipasti", description: "To start", items: [
|
|
18
|
+
// { name: "Bruschetta al Pomodoro", description: "Grilled sourdough, San Marzano tomatoes, basil.", price: 9.50 },
|
|
19
|
+
// ] },
|
|
20
|
+
// ],
|
|
21
|
+
// }); // → { menuId, sectionIds, itemIds }
|
|
22
|
+
//
|
|
23
|
+
// // --- ONLINE ORDERING (add-on, on demand; MENU-FIRST — seed the menu above first) ---
|
|
24
|
+
// await seed.installOrdersApp(ctx); // auto-provisions a working ordering setup
|
|
25
|
+
// await seed.setBusinessLocation(ctx, address); // STEP 0 — REQUIRED (see preconditions below)
|
|
26
|
+
// const ops = await seed.listOperations(ctx); // verify the auto-created operation (never create one)
|
|
27
|
+
// const methods = await seed.listFulfillmentMethods(ctx); // reshape only what the request names
|
|
28
|
+
// const mos = await seed.queryMenuOrderingSettings(ctx); // confirm each menu is onlineOrderingEnabled
|
|
29
|
+
//
|
|
30
|
+
// // --- TABLE RESERVATIONS (add-on, on demand; INDEPENDENT of menu/ordering) ---
|
|
31
|
+
// await seed.installTableReservationsApp(ctx); // auto-provisions a default reservation location
|
|
32
|
+
// await seed.setBusinessLocation(ctx, address); // STEP 0 — shared with ordering (do it once if both)
|
|
33
|
+
// const [loc] = await seed.listReservationLocations(ctx); // discover the default (never create one)
|
|
34
|
+
// await seed.enableOnlineReservations(ctx, loc.id, loc.revision);// PREMIUM-GATED — 428 on a free site (record, don't fail)
|
|
35
|
+
//
|
|
36
|
+
// // --- EXPERIENCES (add-on WITHIN Table Reservations, on demand) ---
|
|
37
|
+
// await seed.createExperiences(ctx, loc.id, experiences); // one per named dining occasion
|
|
38
|
+
//
|
|
39
|
+
// **NOT yet live-verified — transcribed from setup-restaurants.md / setup-restaurant-orders.md /
|
|
40
|
+
// setup-restaurant-reservations.md / setup-restaurant-experiences.md.** If any call fails with a
|
|
41
|
+
// shape the caller didn't expect, fall back to the wix-docs skill (search + read the live Wix API
|
|
42
|
+
// reference) — never guess.
|
|
43
|
+
//
|
|
44
|
+
// ── PRECONDITIONS the recipes flag (record in the handoff, do NOT fail the seed) ─────────────────
|
|
45
|
+
// • Ordering STEP 0 address is REQUIRED: without a real business-location address Wix limits
|
|
46
|
+
// ordering to "testing only" and checkout breaks. If the brief names no address, set a clearly
|
|
47
|
+
// marked placeholder and flag the owner to fix it.
|
|
48
|
+
// • Completing a PAID order needs a premium plan + a configured payment method (dashboard/premium
|
|
49
|
+
// provisioning the skill can't do headlessly).
|
|
50
|
+
// • enableOnlineReservations is PREMIUM-ONLY: on a non-premium site it throws `428 PREMIUM_ONLY`.
|
|
51
|
+
// That is EXPECTED and non-fatal — record it as a precondition and continue; do not retry-spiral.
|
|
52
|
+
// • Booking an Experience is premium-gated the same way (create works on a free site; booking needs
|
|
53
|
+
// premium + online reservations enabled).
|
|
54
|
+
|
|
55
|
+
const API = "https://www.wixapis.com";
|
|
56
|
+
|
|
57
|
+
// App definition ids (SETUP.md §2). Menus is the seedable core; Orders + Table Reservations are
|
|
58
|
+
// separate optional apps. Experiences are a FEATURE of Table Reservations — no separate install.
|
|
59
|
+
const MENUS_APP_ID = "b278a256-2757-4f19-9313-c05c783bec92";
|
|
60
|
+
const ORDERS_APP_ID = "9a5d83fd-8570-482e-81ab-cfa88942ee60";
|
|
61
|
+
const TABLE_RESERVATIONS_APP_ID = "f9c07de2-5341-40c6-b096-8eb39de391fb";
|
|
62
|
+
|
|
63
|
+
async function req(ctx, path, { method = "POST", body } = {}) {
|
|
64
|
+
const res = await fetch(API + path, {
|
|
65
|
+
method,
|
|
66
|
+
headers: {
|
|
67
|
+
Authorization: `Bearer ${ctx.token}`,
|
|
68
|
+
"wix-site-id": ctx.siteId,
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
},
|
|
71
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
72
|
+
});
|
|
73
|
+
const json = await res.json().catch(() => ({}));
|
|
74
|
+
if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
|
|
75
|
+
return json;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── app install ─────────────────────────────────────────────────────────────────────────────────
|
|
79
|
+
// Body shape per SETUP.md §2 (tenant + appInstance). One install call per app.
|
|
80
|
+
async function installApp(ctx, appDefId) {
|
|
81
|
+
return req(ctx, "/apps-installer-service/v1/app-instance/install", {
|
|
82
|
+
body: {
|
|
83
|
+
tenant: { tenantType: "SITE", id: ctx.siteId },
|
|
84
|
+
appInstance: { appDefId, enabled: true },
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async function installMenusApp(ctx) { return installApp(ctx, MENUS_APP_ID); }
|
|
89
|
+
async function installOrdersApp(ctx) { return installApp(ctx, ORDERS_APP_ID); }
|
|
90
|
+
async function installTableReservationsApp(ctx) { return installApp(ctx, TABLE_RESERVATIONS_APP_ID); }
|
|
91
|
+
|
|
92
|
+
// ══ MENU (setup-restaurants.md) ═══════════════════════════════════════════════════════════════════
|
|
93
|
+
// Everything is the Restaurants Menus V1 API on /restaurants/menus/v1/... — one service.
|
|
94
|
+
// REST flattens the protobuf wrappers: send plain values (`"visible": true`), never `{"value": …}`.
|
|
95
|
+
|
|
96
|
+
async function listMenuItems(ctx) {
|
|
97
|
+
const r = await req(ctx, "/restaurants/menus/v1/items", { method: "GET" });
|
|
98
|
+
return (r.items ?? []).map((it) => ({ id: it.id, name: it.name }));
|
|
99
|
+
}
|
|
100
|
+
async function listMenuSections(ctx) {
|
|
101
|
+
const r = await req(ctx, "/restaurants/menus/v1/sections", { method: "GET" });
|
|
102
|
+
return (r.sections ?? []).map((s) => ({ id: s.id, name: s.name }));
|
|
103
|
+
}
|
|
104
|
+
async function listMenus(ctx) {
|
|
105
|
+
const r = await req(ctx, "/restaurants/menus/v1/menus", { method: "GET" });
|
|
106
|
+
return (r.menus ?? []).map((m) => ({ id: m.id, name: m.name }));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Build one menu BOTTOM-UP (items → sections → menu) in three bulk phases.
|
|
111
|
+
* @param menu {
|
|
112
|
+
* name, description?,
|
|
113
|
+
* sections: [{ name, description?, items: [{ name, description?, price }] }]
|
|
114
|
+
* }
|
|
115
|
+
* price -> priceInfo.price as a decimal STRING; currency is the site's (send none).
|
|
116
|
+
* description is a plain string (NOT rich-text nodes); omit for a name-only item/section.
|
|
117
|
+
* visible:true is baked in at every level (item, section, menu) — required to render on the live site.
|
|
118
|
+
* @returns { menuId, sectionIds:[…], itemIds:[…] } (revisions available via listMenuItems for image pass)
|
|
119
|
+
*/
|
|
120
|
+
async function createMenu(ctx, menu) {
|
|
121
|
+
// STEP 1 — bulk-create every item across all sections in ONE request; track which section each belongs to.
|
|
122
|
+
const flat = [];
|
|
123
|
+
menu.sections.forEach((sec, si) => (sec.items || []).forEach((it) => flat.push({ ...it, _section: si })));
|
|
124
|
+
const itemRes = await req(ctx, "/restaurants/menus/v1/bulk/items/create", {
|
|
125
|
+
body: {
|
|
126
|
+
items: flat.map((it) => ({
|
|
127
|
+
name: it.name,
|
|
128
|
+
...(it.description ? { description: it.description } : {}),
|
|
129
|
+
priceInfo: { price: String(it.price) },
|
|
130
|
+
visible: true,
|
|
131
|
+
})),
|
|
132
|
+
returnEntity: true,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
// created items are under results[].item (results[].itemMetadata.success is the per-item flag)
|
|
136
|
+
const createdItems = (itemRes.results ?? []).map((r) => r.item);
|
|
137
|
+
const itemIdsBySection = menu.sections.map(() => []);
|
|
138
|
+
flat.forEach((it, i) => {
|
|
139
|
+
const id = createdItems[i]?.id;
|
|
140
|
+
if (id) itemIdsBySection[it._section].push(id);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// STEP 2 — bulk-create sections, each carrying the itemIds of its items (real ids from STEP 1).
|
|
144
|
+
const secRes = await req(ctx, "/restaurants/menus/v1/bulk/sections/create", {
|
|
145
|
+
body: {
|
|
146
|
+
sections: menu.sections.map((sec, si) => ({
|
|
147
|
+
name: sec.name,
|
|
148
|
+
...(sec.description ? { description: sec.description } : {}),
|
|
149
|
+
visible: true,
|
|
150
|
+
itemIds: itemIdsBySection[si],
|
|
151
|
+
})),
|
|
152
|
+
returnEntity: true,
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
const sectionIds = (secRes.results ?? []).map((r) => r.item?.id);
|
|
156
|
+
|
|
157
|
+
// STEP 3 — create the menu (single create wraps in `menu`), carrying its sectionIds.
|
|
158
|
+
// businessLocationId omitted -> binds to the site's default (main) location.
|
|
159
|
+
const menuRes = await req(ctx, "/restaurants/menus/v1/menus", {
|
|
160
|
+
body: {
|
|
161
|
+
menu: {
|
|
162
|
+
name: menu.name,
|
|
163
|
+
...(menu.description ? { description: menu.description } : {}),
|
|
164
|
+
visible: true,
|
|
165
|
+
sectionIds,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
return { menuId: menuRes.menu?.id, sectionIds, itemIds: createdItems.map((it) => it?.id) };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Import an external image URL into Wix Media → { id, url }. Restaurants binds a menu-item image by
|
|
173
|
+
// the Wix Media file **id**, NOT a url — an external url (e.g. a base44 generate_image result) MUST
|
|
174
|
+
// be imported first; the raw url as the id stores (200) but renders nothing. id = wixstatic file id,
|
|
175
|
+
// url = the permanent wixstatic url.
|
|
176
|
+
async function importImage(ctx, url, displayName = "image.png") {
|
|
177
|
+
const r = await req(ctx, "/site-media/v1/files/import", { body: { url, mimeType: "image/png", displayName } });
|
|
178
|
+
const f = r.file || r;
|
|
179
|
+
if (!f?.id) throw new Error(`import-file returned no file id: ${JSON.stringify(r).slice(0, 200)}`);
|
|
180
|
+
return { id: f.id, url: f.url };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Optional (pass-2). The ITEM is the image-bearing entity. Update Item is a FULL-ENTITY REPLACE
|
|
184
|
+
// with NO field mask — you MUST echo each item's current `revision` AND `priceInfo`, or it fails
|
|
185
|
+
// `428 MISSING_ITEM_PRICING` and the image does NOT apply. `image` is an OBJECT { id, url, height, width }
|
|
186
|
+
// (never a bare string); the binding field is the Wix Media file `id` (from importImage). Never block on image failure.
|
|
187
|
+
// items: [{ id, revision, price, image: { id, url, height, width } }]
|
|
188
|
+
async function attachItemImages(ctx, items) {
|
|
189
|
+
return req(ctx, "/restaurants/menus/v1/bulk/items/update", {
|
|
190
|
+
body: {
|
|
191
|
+
items: items.map((it) => ({
|
|
192
|
+
item: {
|
|
193
|
+
id: it.id,
|
|
194
|
+
revision: it.revision,
|
|
195
|
+
priceInfo: { price: String(it.price) },
|
|
196
|
+
image: it.image,
|
|
197
|
+
},
|
|
198
|
+
})),
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ══ BUSINESS LOCATION (shared STEP 0 for ordering + reservations) ══════════════════════════════════
|
|
204
|
+
// Update Location is a FULL OVERRIDE — send the WHOLE `location` object (omitted fields are wiped),
|
|
205
|
+
// echo `default:true` (omitting it 400s CHANGE_DEFAULT_FORBIDDEN) and the current `revision`.
|
|
206
|
+
// address.country is a 2-letter ISO-3166 code. The address propagates to Site Properties.
|
|
207
|
+
// `location`: { name, timeZone, email?, phone?, address:{ country, subdivision, city, postalCode,
|
|
208
|
+
// streetAddress:{ number, name }, formattedAddress } }
|
|
209
|
+
async function setBusinessLocation(ctx, location) {
|
|
210
|
+
const list = await req(ctx, "/locations/v1/locations", { method: "GET" });
|
|
211
|
+
const def = (list.locations ?? []).find((l) => l.default);
|
|
212
|
+
// No default location at all (a bare Orders-only site can have none) -> CREATE one; operations
|
|
213
|
+
// auto-bind on first-location-add. Otherwise overwrite the existing default (full override).
|
|
214
|
+
if (!def) {
|
|
215
|
+
const r = await req(ctx, "/locations/v1/locations", { body: { location: { ...location, default: true } } });
|
|
216
|
+
return r.location;
|
|
217
|
+
}
|
|
218
|
+
const r = await req(ctx, `/locations/v1/locations/${def.id}`, {
|
|
219
|
+
method: "PUT",
|
|
220
|
+
body: { location: { ...location, id: def.id, revision: def.revision, default: true } },
|
|
221
|
+
});
|
|
222
|
+
return r.location;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ══ ONLINE ORDERING (setup-restaurant-orders.md) ═══════════════════════════════════════════════════
|
|
226
|
+
// MENU-FIRST: a menu must exist (createMenu above) before ordering; each menu binds to the operation
|
|
227
|
+
// via a menu-ordering-settings object. The Orders-app install AUTO-provisions a working setup (an
|
|
228
|
+
// ENABLED operation with Pickup + Delivery attached, every menu ordering-enabled) — these helpers
|
|
229
|
+
// VERIFY and RESHAPE it; they do NOT build ordering from scratch. Each micro-service is on its OWN
|
|
230
|
+
// host prefix (restaurants-operations / fulfillment-methods / menu-ordering-settings) — do not normalize.
|
|
231
|
+
|
|
232
|
+
// STEP 1 — verify the auto-created operation (never POST to create one). If empty, the install hasn't
|
|
233
|
+
// finished provisioning: wait briefly and retry the GET once (caller's concern), then fail loud.
|
|
234
|
+
async function listOperations(ctx) {
|
|
235
|
+
const r = await req(ctx, "/restaurants-operations/v1/operations", { method: "GET" });
|
|
236
|
+
return r.operations ?? [];
|
|
237
|
+
}
|
|
238
|
+
// Normally already "ENABLED" — only PATCH if you see DISABLED/PAUSED_UNTIL. revision mandatory + current.
|
|
239
|
+
async function enableOperation(ctx, operationId, revision) {
|
|
240
|
+
return req(ctx, `/restaurants-operations/v1/operations/${operationId}`, {
|
|
241
|
+
method: "PATCH",
|
|
242
|
+
body: { operation: { revision, onlineOrderingStatus: "ENABLED" } },
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
// A newly created fulfillment method is NOT auto-attached — PATCH the operation's fulfillmentIds with
|
|
246
|
+
// the FULL array (existing ids + the new one) or it won't be offered at checkout.
|
|
247
|
+
async function setOperationFulfillmentIds(ctx, operationId, revision, fulfillmentIds) {
|
|
248
|
+
return req(ctx, `/restaurants-operations/v1/operations/${operationId}`, {
|
|
249
|
+
method: "PATCH",
|
|
250
|
+
body: { operation: { revision, fulfillmentIds } },
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// STEP 2 — reconcile fulfillment methods to the request. Install ships three (Pickup enabled,
|
|
255
|
+
// "Delivery Area #1" enabled fee "0", "DoorDash Drive" disabled), all with a San Francisco placeholder
|
|
256
|
+
// address. Wrap bodies in camelCase `fulfillmentMethod`; fee/minOrderPrice are decimal STRINGS.
|
|
257
|
+
async function listFulfillmentMethods(ctx) {
|
|
258
|
+
const r = await req(ctx, "/fulfillment-methods/v1/fulfillment-methods", { method: "GET" });
|
|
259
|
+
return r.fulfillmentMethods ?? [];
|
|
260
|
+
}
|
|
261
|
+
// patch: partial { revision, name?, fee?, minOrderPrice?, enabled?, availability?, pickupOptions?/deliveryOptions? }
|
|
262
|
+
async function updateFulfillmentMethod(ctx, methodId, patch) {
|
|
263
|
+
return req(ctx, `/fulfillment-methods/v1/fulfillment-methods/${methodId}`, {
|
|
264
|
+
method: "PATCH",
|
|
265
|
+
body: { fulfillmentMethod: patch },
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
// Create a method beyond the defaults, THEN setOperationFulfillmentIds to attach it (create does NOT attach).
|
|
269
|
+
// pickupOptions for type PICKUP, deliveryOptions (with a deliveryArea) for DELIVERY — send the one matching type.
|
|
270
|
+
async function createFulfillmentMethod(ctx, fulfillmentMethod) {
|
|
271
|
+
const r = await req(ctx, "/fulfillment-methods/v1/fulfillment-methods", { body: { fulfillmentMethod } });
|
|
272
|
+
return r.fulfillmentMethod;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// STEP 3 — verify each menu is orderable. Auto-created + auto-enabled per menu, so normally a confirmation.
|
|
276
|
+
async function queryMenuOrderingSettings(ctx) {
|
|
277
|
+
const r = await req(ctx, "/menu-ordering-settings/v1/menu-ordering-settings/query", { body: { query: {} } });
|
|
278
|
+
return r.menuOrderingSettings ?? [];
|
|
279
|
+
}
|
|
280
|
+
// Only if an entry shows onlineOrderingEnabled:false / operationId:"none" (or a menu should be display-only).
|
|
281
|
+
// patch: { revision, operationId, onlineOrderingEnabled, availability:{ type:"ALWAYS_AVAILABLE", timeZone } }
|
|
282
|
+
async function updateMenuOrderingSettings(ctx, settingsId, patch) {
|
|
283
|
+
return req(ctx, `/menu-ordering-settings/v1/menu-ordering-settings/${settingsId}`, {
|
|
284
|
+
method: "PATCH",
|
|
285
|
+
body: { menuOrderingSettings: patch },
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ══ TABLE RESERVATIONS (setup-restaurant-reservations.md) ══════════════════════════════════════════
|
|
290
|
+
// INDEPENDENT of the menu (reservations bind to a LOCATION, not a menu — no menu-first rule) and there
|
|
291
|
+
// is NOTHING to bulk-seed (visitors create reservations at runtime). The install AUTO-provisions one
|
|
292
|
+
// default reservation location with a complete config; the one thing OFF is onlineReservationsEnabled.
|
|
293
|
+
// A reservation location CANNOT be created via this API — discover, configure, and enable it.
|
|
294
|
+
// Use the post-Jan-2026 field names: partySize (not partiesSize), approval (not manualApproval),
|
|
295
|
+
// tables.ids (not tableIds), ignoreConflicts.
|
|
296
|
+
|
|
297
|
+
// STEP 1 — discover the default location (never create one). If empty, wait + retry the GET once, else fail loud.
|
|
298
|
+
async function listReservationLocations(ctx) {
|
|
299
|
+
const r = await req(ctx, "/table-reservations/reservation-locations/v1/reservation-locations", { method: "GET" });
|
|
300
|
+
return r.reservationLocations ?? [];
|
|
301
|
+
}
|
|
302
|
+
// STEP 2 — customize config (only what the request names). Partial PATCH; revision mandatory. Works on a
|
|
303
|
+
// non-premium site. The `location` object (address/name) is IMMUTABLE here — only touch `configuration`.
|
|
304
|
+
// configuration: { onlineReservations: { partySize?:{min,max}, minimumReservationNotice?:{number,unit},
|
|
305
|
+
// defaultTurnoverTime?, businessSchedule?, approval?:{mode:"AUTOMATIC"}, ... } }
|
|
306
|
+
async function updateReservationLocation(ctx, reservationLocationId, revision, configuration) {
|
|
307
|
+
return req(ctx, `/table-reservations/reservation-locations/v1/reservation-locations/${reservationLocationId}`, {
|
|
308
|
+
method: "PATCH",
|
|
309
|
+
body: { reservationLocation: { id: reservationLocationId, revision, configuration } },
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
// STEP 3 — turn on online reservations. PREMIUM-ONLY: on a non-premium site this THROWS `428 PREMIUM_ONLY`
|
|
313
|
+
// ("Can't turn on online reservation for a non-premium website"). That is EXPECTED and non-fatal — the
|
|
314
|
+
// caller records it as a premium precondition and continues; do NOT retry-spiral or fail the seed.
|
|
315
|
+
async function enableOnlineReservations(ctx, reservationLocationId, revision) {
|
|
316
|
+
return req(ctx, `/table-reservations/reservation-locations/v1/reservation-locations/${reservationLocationId}`, {
|
|
317
|
+
method: "PATCH",
|
|
318
|
+
body: {
|
|
319
|
+
reservationLocation: {
|
|
320
|
+
id: reservationLocationId,
|
|
321
|
+
revision,
|
|
322
|
+
configuration: { onlineReservations: { onlineReservationsEnabled: true } },
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ══ EXPERIENCES (setup-restaurant-experiences.md) ══════════════════════════════════════════════════
|
|
329
|
+
// An experience is a reservation that IS a curated dining occasion (wine tasting, chef's table). Feature
|
|
330
|
+
// of the Table Reservations app — no separate install. Created against a reservationLocationId (from
|
|
331
|
+
// listReservationLocations). The full create payload lives in the live docs (fields evolve) — build each
|
|
332
|
+
// `experience` from the Create-Experience doc; this only wires the loop. Set configuration.visible:true.
|
|
333
|
+
// GOTCHAS the docs won't state:
|
|
334
|
+
// • Notice fields are FLAT under onlineReservations (minimumReservationNotice / maximumReservationNotice),
|
|
335
|
+
// NOT wrapped in `noticePeriod` (the doc example's wrapper is stale).
|
|
336
|
+
// • paymentPolicyType: PER_GUEST (needs perGuestOptions.price, a decimal string) or FREE.
|
|
337
|
+
// • businessSchedule.entries[] carries the recurrence (WEEKLY + weeklyOptions.startDaysAndTimes[{day,time}],
|
|
338
|
+
// or ONE_TIME); durationInMinutes sits on businessSchedule, not per entry.
|
|
339
|
+
// • Creating works on a free site; BOOKING is premium-gated (record, don't fail).
|
|
340
|
+
// experiences: [{ configuration: { displayInfo:{name,shortDescription}, paymentPolicy, onlineReservations, visible } }]
|
|
341
|
+
async function createExperiences(ctx, reservationLocationId, experiences) {
|
|
342
|
+
const out = [];
|
|
343
|
+
for (const exp of experiences) {
|
|
344
|
+
const r = await req(ctx, "/table-reservations/experiences/v1/experiences", {
|
|
345
|
+
body: { experience: { reservationLocationId, ...exp } },
|
|
346
|
+
});
|
|
347
|
+
out.push({ id: r.experience?.id, name: r.experience?.configuration?.displayInfo?.name });
|
|
348
|
+
}
|
|
349
|
+
return out;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// ══ ONE-CALL ORCHESTRATOR ══════════════════════════════════════════════════════════════════════════
|
|
353
|
+
/**
|
|
354
|
+
* DEFAULT one-call path — seed a whole Wix Restaurants site from a plain plan; the caller threads NO
|
|
355
|
+
* ids across exec calls. Installs the Menus app and builds the menu BOTTOM-UP (items → sections → menu):
|
|
356
|
+
* `createMenu` bulk-creates every item first, then the sections carrying their item ids, then the menu
|
|
357
|
+
* carrying its section ids — every child exists before its parent. In-memory name→id maps (item, section)
|
|
358
|
+
* wire the tree and map each plan item to its created id for the image pass (full-replace, echo revision
|
|
359
|
+
* + price; freshly created items are at revision "1"). Online ordering and table reservations are
|
|
360
|
+
* on-demand add-ons — touched ONLY when the plan asks, each installing its own app and following the
|
|
361
|
+
* module's own fns. Ordering needs a business-location address (`setBusinessLocation` STEP 0); if the
|
|
362
|
+
* plan names none the recipe's precondition applies (record + flag). `enableOnlineReservations` is
|
|
363
|
+
* premium-gated (428 on a free site) — expected and non-fatal, recorded not thrown.
|
|
364
|
+
*
|
|
365
|
+
* @param plan {
|
|
366
|
+
* menu: { name, description?, sections: [{ name, description?,
|
|
367
|
+
* items: [{ name, description?, price, imageUrl? }] }] }, // imageUrl = a plain url; imported to Wix Media here
|
|
368
|
+
* ordering?: boolean | { address? },
|
|
369
|
+
* reservations?: boolean | { address?, configuration? },
|
|
370
|
+
* }
|
|
371
|
+
* @returns { menuId, sectionIds, itemIds, orderingEnabled, reservationsEnabled, imagesAttached }
|
|
372
|
+
*/
|
|
373
|
+
async function setupRestaurants(ctx, plan) {
|
|
374
|
+
await installMenusApp(ctx);
|
|
375
|
+
|
|
376
|
+
const { menuId, sectionIds, itemIds } = await createMenu(ctx, plan.menu);
|
|
377
|
+
|
|
378
|
+
// name→id maps: createMenu flattens sections→items in order, so itemIds/sectionIds line up 1:1.
|
|
379
|
+
const flatItems = plan.menu.sections.flatMap((s) => s.items || []);
|
|
380
|
+
const itemNameToId = new Map(flatItems.map((it, i) => [it.name, itemIds[i]]));
|
|
381
|
+
|
|
382
|
+
// image pass — import each item's url to Wix Media (restaurants binds by file id), then full-replace
|
|
383
|
+
// update its created id (revision "1", fresh + priceInfo). A failed import just skips that image.
|
|
384
|
+
const imageItems = [];
|
|
385
|
+
for (const it of flatItems) {
|
|
386
|
+
if (!it.imageUrl) continue;
|
|
387
|
+
try {
|
|
388
|
+
const file = await importImage(ctx, it.imageUrl, `${it.name || "item"}.png`);
|
|
389
|
+
imageItems.push({ id: itemNameToId.get(it.name), revision: "1", price: it.price,
|
|
390
|
+
image: { id: file.id, url: file.url, height: 1024, width: 1024 } });
|
|
391
|
+
} catch { /* skip this item's image */ }
|
|
392
|
+
}
|
|
393
|
+
let imagesAttached = 0;
|
|
394
|
+
if (imageItems.length) {
|
|
395
|
+
try { await attachItemImages(ctx, imageItems); imagesAttached = imageItems.length; }
|
|
396
|
+
catch { /* never block on image failure */ }
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// shared STEP 0 address — set once across both add-ons (SEED.md: do it once if both run).
|
|
400
|
+
let locationSet = false;
|
|
401
|
+
const ensureLocation = async (address) => {
|
|
402
|
+
if (address && !locationSet) { await setBusinessLocation(ctx, address); locationSet = true; }
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
let orderingEnabled = false;
|
|
406
|
+
if (plan.ordering) {
|
|
407
|
+
const cfg = typeof plan.ordering === "object" ? plan.ordering : {};
|
|
408
|
+
await installOrdersApp(ctx); // auto-provisions operation + methods + per-menu settings
|
|
409
|
+
await ensureLocation(cfg.address);
|
|
410
|
+
await listOperations(ctx); // verify the auto-created operation
|
|
411
|
+
await queryMenuOrderingSettings(ctx); // confirm each menu is orderable
|
|
412
|
+
orderingEnabled = true;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
let reservationsEnabled = false;
|
|
416
|
+
if (plan.reservations) {
|
|
417
|
+
const cfg = typeof plan.reservations === "object" ? plan.reservations : {};
|
|
418
|
+
await installTableReservationsApp(ctx); // auto-provisions the default reservation location
|
|
419
|
+
await ensureLocation(cfg.address); // independent of menu; address optional for reservations
|
|
420
|
+
let [loc] = await listReservationLocations(ctx);
|
|
421
|
+
if (loc && cfg.configuration) {
|
|
422
|
+
await updateReservationLocation(ctx, loc.id, loc.revision, cfg.configuration);
|
|
423
|
+
[loc] = await listReservationLocations(ctx); // re-read for the bumped revision
|
|
424
|
+
}
|
|
425
|
+
if (loc) {
|
|
426
|
+
try { await enableOnlineReservations(ctx, loc.id, loc.revision); reservationsEnabled = true; }
|
|
427
|
+
catch { /* 428 PREMIUM_ONLY on a free site is expected — record, don't fail */ }
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return { menuId, sectionIds, itemIds, orderingEnabled, reservationsEnabled, imagesAttached };
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
module.exports = {
|
|
435
|
+
// DEFAULT one-call orchestrator
|
|
436
|
+
setupRestaurants,
|
|
437
|
+
// app install
|
|
438
|
+
installMenusApp, installOrdersApp, installTableReservationsApp,
|
|
439
|
+
// menu
|
|
440
|
+
listMenuItems, listMenuSections, listMenus,
|
|
441
|
+
createMenu, importImage, attachItemImages,
|
|
442
|
+
// shared business location (ordering + reservations STEP 0)
|
|
443
|
+
setBusinessLocation,
|
|
444
|
+
// ordering add-on
|
|
445
|
+
listOperations, enableOperation, setOperationFulfillmentIds,
|
|
446
|
+
listFulfillmentMethods, updateFulfillmentMethod, createFulfillmentMethod,
|
|
447
|
+
queryMenuOrderingSettings, updateMenuOrderingSettings,
|
|
448
|
+
// reservations add-on
|
|
449
|
+
listReservationLocations, updateReservationLocation, enableOnlineReservations,
|
|
450
|
+
// experiences add-on
|
|
451
|
+
createExperiences,
|
|
452
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Preview-only banner linking the running app to its Wix Business Manager (the back office).
|
|
2
|
+
// Renders while the app is previewed or run locally, never on the published site, and is
|
|
3
|
+
// dismissible (persisted per site).
|
|
4
|
+
// Mount it at the top of your Layout's fixed region, ABOVE <Header/> (see INSTRUCTIONS STEP 4) —
|
|
5
|
+
// banner + header ride together as one fixed block, so nothing drifts or gaps on scroll.
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { WIX_METASITE_ID } from "@/rest/wix-config";
|
|
8
|
+
|
|
9
|
+
const DASHBOARD_URL = `https://manage.wix.com/dashboard/${WIX_METASITE_ID}`;
|
|
10
|
+
const DISMISS_KEY = `wix-manage-banner-dismissed-${WIX_METASITE_ID}`;
|
|
11
|
+
|
|
12
|
+
// Base44 serves the preview from a dev server (DEV true) or a prebuilt bundle (DEV false) and swaps
|
|
13
|
+
// between them mid-session, so its hostname and injected marker are what hold the banner steady;
|
|
14
|
+
// DEV is the best-effort signal elsewhere. Unrecognized host on a built bundle → hidden.
|
|
15
|
+
const PREVIEW_HOST = /^(preview|preview-sandbox|checkpoint)--/;
|
|
16
|
+
const IN_PREVIEW = (() => {
|
|
17
|
+
try {
|
|
18
|
+
return Boolean(import.meta.env?.DEV)
|
|
19
|
+
|| PREVIEW_HOST.test(window.location.hostname)
|
|
20
|
+
|| Boolean(document.querySelector("script[data-preview-inject]"));
|
|
21
|
+
} catch { return false; }
|
|
22
|
+
})();
|
|
23
|
+
|
|
24
|
+
export default function WixManageBanner() {
|
|
25
|
+
const [dismissed, setDismissed] = useState(() => {
|
|
26
|
+
try { return Boolean(window.localStorage.getItem(DISMISS_KEY)); } catch { return false; }
|
|
27
|
+
});
|
|
28
|
+
// Never renders on the published site, once dismissed, or before the id is filled in.
|
|
29
|
+
if (!IN_PREVIEW || dismissed || WIX_METASITE_ID.startsWith("<")) return null;
|
|
30
|
+
|
|
31
|
+
const dismiss = () => {
|
|
32
|
+
setDismissed(true);
|
|
33
|
+
try { window.localStorage.setItem(DISMISS_KEY, "1"); } catch { /* ignore disabled storage */ }
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div style={{
|
|
38
|
+
position: "relative", display: "flex", alignItems: "center", justifyContent: "center", gap: 14,
|
|
39
|
+
width: "100%", padding: "12px 48px", boxSizing: "border-box",
|
|
40
|
+
background: "#fff", color: "#131720", fontSize: 15,
|
|
41
|
+
fontFamily: "system-ui,-apple-system,sans-serif", borderBottom: "1px solid #e2e2ea",
|
|
42
|
+
}}>
|
|
43
|
+
<span>
|
|
44
|
+
Manage your business behind this site in Wix{" "}
|
|
45
|
+
<a href={DASHBOARD_URL} target="_blank" rel="noopener" style={{ color: "inherit", textDecoration: "underline" }}>business manager</a>
|
|
46
|
+
</span>
|
|
47
|
+
<a href={DASHBOARD_URL} target="_blank" rel="noopener" style={{
|
|
48
|
+
background: "#131720", color: "#fff", borderRadius: 999, padding: "8px 18px", fontSize: 14, textDecoration: "none",
|
|
49
|
+
}}>Open</a>
|
|
50
|
+
<button type="button" aria-label="Dismiss banner" onClick={dismiss} style={{
|
|
51
|
+
position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)",
|
|
52
|
+
background: "none", border: "none", color: "#868aa5", fontSize: 16, lineHeight: 1, cursor: "pointer", padding: 6,
|
|
53
|
+
}}>✕</button>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -3,16 +3,14 @@
|
|
|
3
3
|
* `storefrontApiRequest` in src/lib/shopify.ts. Plain fetch, JSON in / JSON out.
|
|
4
4
|
* No SDK, no query builder, no Velo.
|
|
5
5
|
*
|
|
6
|
-
* WIX_CLIENT_ID is the one thing to set
|
|
7
|
-
* access token via the OAuth2 token endpoint,
|
|
6
|
+
* WIX_CLIENT_ID is the one thing to set — and you set it in `wix-config.js`, not here.
|
|
7
|
+
* The client exchanges it for a visitor access token via the OAuth2 token endpoint,
|
|
8
|
+
* then sends that token on every API call.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* value from the Wix Business Manager prompt in place of the placeholder.
|
|
14
|
-
*/
|
|
15
|
-
export const WIX_CLIENT_ID = "<YOUR-CLIENT-ID>";
|
|
11
|
+
// The public headless OAuth client id — set it in wix-config.js (do not hardcode it here).
|
|
12
|
+
export { WIX_CLIENT_ID } from "./wix-config.js";
|
|
13
|
+
import { WIX_CLIENT_ID } from "./wix-config.js";
|
|
16
14
|
|
|
17
15
|
export const WIX_API_BASE = "https://www.wixapis.com";
|
|
18
16
|
const OAUTH_TOKEN_URL = `${WIX_API_BASE}/oauth2/token`;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Wix credentials — the ONLY file you set these in. Paste both values from your prompt,
|
|
2
|
+
// replacing the placeholders. Safe to commit: WIX_CLIENT_ID is a public, buyer-facing id
|
|
3
|
+
// (it only mints anonymous visitor tokens); WIX_METASITE_ID just identifies the site.
|
|
4
|
+
// wix-client.js and wix-manage-banner.js read their ids from here.
|
|
5
|
+
export const WIX_CLIENT_ID = "<YOUR-CLIENT-ID>";
|
|
6
|
+
export const WIX_METASITE_ID = "<YOUR-METASITE-ID>";
|