@wix/agent-skills 1.20.1 → 1.22.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 +71 -113
- package/skills/wix-app/references/APP_TOOLS.md +2 -1
- package/skills/wix-app/references/BACKEND_EVENT.md +3 -3
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +41 -152
- package/skills/wix-app/references/DASHBOARD_MODAL.md +4 -4
- package/skills/wix-app/references/DASHBOARD_PAGE.md +11 -25
- package/skills/wix-app/references/DATA_COLLECTION.md +16 -219
- package/skills/wix-app/references/SDK_MODULE_MAP.md +44 -0
- package/skills/wix-app/references/SITE_PLUGIN.md +36 -190
- package/skills/wix-app/references/app-tools/TOOLS.md +3 -1
- package/skills/wix-app/references/custom-element-widget/SETTINGS_PANEL.md +21 -0
- package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +182 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +97 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md +184 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +203 -0
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_SETTINGS.md +44 -0
- package/skills/wix-app/references/dashboard-page/ECOM_NAVIGATION.md +17 -0
- package/skills/wix-app/references/dashboard-page/QUERY_AND_PAGING.md +182 -0
- package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +133 -0
- package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +10 -5
- package/skills/wix-app/references/dashboard-plugin/SLOTS.md +4 -18
- package/skills/wix-app/references/data-collection/LIFECYCLE.md +68 -0
- package/skills/wix-app/references/data-collection/PERMISSIONS.md +47 -0
- package/skills/wix-app/references/data-collection/SCHEMA.md +181 -0
- package/skills/wix-app/references/data-collection/WIX_DATA.md +38 -66
- package/skills/wix-app/references/site-plugin/EXAMPLES.md +1 -1
- package/skills/wix-headless-fast/SKILL.md +144 -221
- package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
- package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +15 -15
- package/skills/wix-headless-fast/guides/existing-site.md +76 -0
- package/skills/wix-headless-fast/guides/reference-mode.md +97 -0
- package/skills/wix-headless-fast/install/AGENTS.md +35 -0
- package/skills/wix-headless-fast/install/agents-md.mjs +39 -0
- package/skills/wix-headless-fast/install/attach.mjs +161 -86
- package/skills/wix-headless-fast/install/deploy.mjs +21 -60
- package/skills/wix-headless-fast/install/lock.mjs +55 -0
- package/skills/wix-headless-fast/install/setup.mjs +259 -0
- package/skills/wix-headless-fast/install/templates.mjs +168 -0
- package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-coupon.md +10 -19
- package/skills/wix-manage/references/events/create-wix-event.md +5 -1
- package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +27 -0
- package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +83 -37
- package/skills/wix-headless-fast/install/fast-path.mjs +0 -181
- package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -301
- package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +0 -136
- package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +0 -112
- package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +0 -42
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +0 -31
- package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +0 -22
- package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +0 -137
- package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +0 -78
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +0 -117
- package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +0 -52
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +0 -47
- package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +0 -58
- package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +0 -62
- package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +0 -97
- package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +0 -24
- package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +0 -16156
- package/skills/wix-headless-fast/references/blog/rest/posts.ts +0 -42
- package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +0 -62
- package/skills/wix-headless-fast/references/blog/seed/SEED.md +0 -81
- package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +0 -287
- package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -275
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +0 -144
- package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +0 -119
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +0 -32
- package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +0 -23
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +0 -218
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +0 -169
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +0 -121
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +0 -92
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +0 -90
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +0 -57
- package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +0 -72
- package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +0 -76
- package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +0 -22
- package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +0 -11962
- package/skills/wix-headless-fast/references/bookings/rest/booking.ts +0 -113
- package/skills/wix-headless-fast/references/bookings/rest/services.ts +0 -55
- package/skills/wix-headless-fast/references/bookings/seed/SEED.md +0 -71
- package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +0 -302
- package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -353
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +0 -50
- package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +0 -37
- package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +0 -158
- package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +0 -93
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +0 -177
- package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +0 -123
- package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +0 -75
- package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +0 -41
- package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +0 -11262
- package/skills/wix-headless-fast/references/cms/rest/items.ts +0 -125
- package/skills/wix-headless-fast/references/cms/seed/SEED.md +0 -112
- package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +0 -324
- package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -305
- package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +0 -66
- package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +0 -178
- package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +0 -118
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +0 -35
- package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +0 -24
- package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +0 -130
- package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +0 -97
- package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +0 -55
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +0 -113
- package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +0 -156
- package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +0 -97
- package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +0 -61
- package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +0 -12
- package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +0 -80
- package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +0 -21
- package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +0 -11884
- package/skills/wix-headless-fast/references/events/rest/events.ts +0 -57
- package/skills/wix-headless-fast/references/events/rest/registration.ts +0 -83
- package/skills/wix-headless-fast/references/events/seed/SEED.md +0 -95
- package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +0 -276
- package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +0 -338
- package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +0 -85
- package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +0 -332
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +0 -238
- package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +0 -54
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +0 -216
- package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +0 -59
- package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +0 -135
- package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +0 -10593
- package/skills/wix-headless-fast/references/forms/rest/forms.ts +0 -34
- package/skills/wix-headless-fast/references/forms/rest/submissions.ts +0 -56
- package/skills/wix-headless-fast/references/forms/seed/SEED.md +0 -116
- package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +0 -327
- package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -314
- package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +0 -60
- package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +0 -155
- package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +0 -78
- package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +0 -47
- package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +0 -66
- package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +0 -105
- package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +0 -59
- package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +0 -53
- package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +0 -122
- package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +0 -43
- package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +0 -29
- package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +0 -21
- package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +0 -42
- package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +0 -10
- package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +0 -11
- package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +0 -10329
- package/skills/wix-headless-fast/references/members/rest/auth.ts +0 -215
- package/skills/wix-headless-fast/references/members/rest/members.ts +0 -26
- package/skills/wix-headless-fast/references/members/seed/SEED.md +0 -39
- package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +0 -94
- package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -313
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +0 -110
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +0 -90
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +0 -35
- package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +0 -85
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +0 -32
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +0 -21
- package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +0 -31
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +0 -82
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +0 -58
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +0 -177
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +0 -78
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +0 -81
- package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +0 -55
- package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +0 -40
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +0 -30
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +0 -21
- package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +0 -29
- package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +0 -10197
- package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +0 -75
- package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +0 -86
- package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +0 -258
- package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -294
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +0 -47
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +0 -101
- package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +0 -41
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +0 -16
- package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +0 -22
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +0 -54
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +0 -106
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +0 -64
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +0 -27
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +0 -43
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +0 -22
- package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +0 -30
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +0 -41
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +0 -40
- package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +0 -21
- package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +0 -11226
- package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +0 -31
- package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +0 -20
- package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +0 -79
- package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +0 -279
- package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -358
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +0 -142
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +0 -26
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +0 -121
- package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +0 -155
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +0 -34
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +0 -43
- package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +0 -34
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +0 -155
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +0 -89
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +0 -71
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +0 -103
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +0 -124
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +0 -185
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +0 -193
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +0 -94
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +0 -74
- package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +0 -168
- package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +0 -47
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +0 -22
- package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +0 -12
- package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +0 -12560
- package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +0 -60
- package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +0 -169
- package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +0 -68
- package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +0 -89
- package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +0 -479
- package/skills/wix-headless-fast/references/shared/CONTENT.md +0 -22
- package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +0 -73
- package/skills/wix-headless-fast/references/shared/DESIGN.md +0 -26
- package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +0 -23
- package/skills/wix-headless-fast/references/shared/app/styles/global.css +0 -52
- package/skills/wix-headless-fast/references/shared/app/wix/config.ts +0 -15
- package/skills/wix-headless-fast/references/shared/app/wix/media.ts +0 -81
- package/skills/wix-headless-fast/references/shared/app/wix/money.ts +0 -24
- package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +0 -89
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +0 -46
- package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +0 -46
- package/skills/wix-headless-fast/references/shared/rest/client.ts +0 -155
- package/skills/wix-headless-fast/references/shared/rest/config.ts +0 -3
- package/skills/wix-headless-fast/references/shared/rest/media.ts +0 -65
- package/skills/wix-headless-fast/references/shared/seed/images.mjs +0 -145
- package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +0 -608
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +0 -26
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +0 -155
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +0 -266
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +0 -95
- package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +0 -136
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +0 -48
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +0 -39
- package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +0 -34
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +0 -121
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +0 -107
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +0 -138
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +0 -309
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +0 -133
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +0 -147
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +0 -289
- package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +0 -167
- package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +0 -65
- package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +0 -12247
- package/skills/wix-headless-fast/references/storefront/rest/cart.ts +0 -132
- package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +0 -123
- package/skills/wix-headless-fast/references/storefront/seed/SEED.md +0 -124
- package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -525
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
# CMS — playbook
|
|
2
|
-
|
|
3
|
-
The data machinery ships as files — typed reads/writes over ANY collection, the list and item
|
|
4
|
-
state machines, their React bindings, and the normalization layer (dates → ISO strings,
|
|
5
|
-
`wix:image://` → https URLs), correct end-to-end. CMS is schema-generic, so unlike other
|
|
6
|
-
verticals there are **no fixed pages**: the seed plan (`plan.json`) is the site's content model,
|
|
7
|
-
and **you design the pages from it** — a listing surface and an item page per content collection,
|
|
8
|
-
plus the home page and the brand. You never write data-access logic; you never skip designing.
|
|
9
|
-
|
|
10
|
-
## The file map (deployed into `src/`)
|
|
11
|
-
|
|
12
|
-
**On Astro and React the shipped files are tested and work as they are** — this table and the
|
|
13
|
-
contracts below are everything you need to use them, so don't spend the run reading their source;
|
|
14
|
-
wire them and build your surfaces. Reading them is the right move when something is off (a runtime
|
|
15
|
-
error, a field this playbook doesn't cover) or when the brief wants a behaviour they don't offer —
|
|
16
|
-
then read the file that owns it and change or extend it. On `lib`, `static`, and a port the hooks
|
|
17
|
-
don't deploy at all; the stores behind them do, and each wiring section below says how to bind
|
|
18
|
-
them. Files you edit: `SiteLayout.astro` and `styles/global.css`. Files you **create** (skeletons
|
|
19
|
-
below): the listing and item pages with their islands, plus your home page.
|
|
20
|
-
|
|
21
|
-
| file | what it is |
|
|
22
|
-
|---|---|
|
|
23
|
-
| `wix/config.ts` · `wix/sdk.ts` | shared auth seam (deploy configures it — nothing to set by hand) |
|
|
24
|
-
| `wix/media.ts` · `wix/money.ts` | `imgAttrs(url, sizes)` — every `<img>` attribute for a DTO image (`src`, `srcSet`, `sizes`, lazy): `<img {...imgAttrs(item.photo, "33vw")} alt={item.title} />`; `{}` for an absent image — render your placeholder then |
|
|
25
|
-
| `wix/cms/types.ts` | the DTOs (`CmsItem`, `CmsFilter`, `CmsSort`, `CmsQuery`, `CmsPage`) — contracts below |
|
|
26
|
-
| `wix/cms/items.ts` | `queryItems`, `getItemById`, `getItemBy`, `countItems`, `insertItem`, `updateItem`, `patchItemFields`, `removeItem` — the transport; the rules and DTO mappers are in `items-core.ts` beside it (shared with the REST layer) |
|
|
27
|
-
| `wix/cms/items-core.ts` | the normalization rules, the filter guard, the wire spelling of a query, and `formatDate(iso)` — a DATE field as copy ("" for absent/invalid, never "Invalid Date") |
|
|
28
|
-
| `wix/cms/collection-store.ts` · `item-store.ts` | the list and item state machines, framework-free (`createCollectionStore()`, `createItemStore()` — `getState`/`subscribe` + actions, one instance per surface); the hooks below bind them to React, every other stack uses them directly |
|
|
29
|
-
| `hooks/cms/useCollection.ts` | React binding of `collection-store.ts`: list state + skip paging — contract below |
|
|
30
|
-
| `hooks/cms/useItem.ts` | React binding of `item-store.ts`: one item by `_id` or slug field — contract below |
|
|
31
|
-
| `styles/global.css` | the design system: Tailwind v4 + the `@theme` token block (shared across verticals) |
|
|
32
|
-
|
|
33
|
-
There are **no shipped components** — the data layer, stores, and hooks are the machinery; every
|
|
34
|
-
component is yours.
|
|
35
|
-
|
|
36
|
-
Astro stack additionally gets:
|
|
37
|
-
|
|
38
|
-
| file | what it is |
|
|
39
|
-
|---|---|
|
|
40
|
-
| `layouts/SiteLayout.astro` | site chrome — **yours to brand** (keep the `seo-tags` slot + global.css import). If another vertical is also deployed, its layout won — add your content nav links there |
|
|
41
|
-
|
|
42
|
-
There are **no shipped pages** — you author them (below).
|
|
43
|
-
|
|
44
|
-
## What you build — the design job
|
|
45
|
-
|
|
46
|
-
Read the seed plan first: its collections, field keys, and permissions are the contract your
|
|
47
|
-
pages bind to (collection ids and field keys verbatim).
|
|
48
|
-
|
|
49
|
-
1. **A listing surface per content collection** — your card (image, title, secondary fields)
|
|
50
|
-
and rhythm, with skeletons while loading and an honest empty state — on `useCollection`
|
|
51
|
-
(or SSR via `queryItems` alone when the page needs no interactivity).
|
|
52
|
-
2. **An item page per collection with a `slug` field** — your detail layout on the DTO
|
|
53
|
-
(SSR fetch via `getItemBy`), with a real 404 on miss.
|
|
54
|
-
3. **The home page** — hero, featured items (fetch in frontmatter → your components), brand
|
|
55
|
-
story.
|
|
56
|
-
|
|
57
|
-
Plus the **theme** (`@theme` block, one edit) and the **chrome** (`SiteLayout`, one pass).
|
|
58
|
-
Style everything with Tailwind utilities on the tokens.
|
|
59
|
-
|
|
60
|
-
### What a complete content site shows (recommended defaults)
|
|
61
|
-
|
|
62
|
-
Defaults for a brief that says nothing about them; the prompt wins where it differs. Look at the
|
|
63
|
-
seeded content before designing (how many collections, which fields, whether items carry images
|
|
64
|
-
and dates) and design for this content, not for a stereotype of the business.
|
|
65
|
-
|
|
66
|
-
- **Home:** what the site is about and one path into the content in the first screen; real items
|
|
67
|
-
under truthful headings; not a repeat of a listing page.
|
|
68
|
-
- **Listing:** a real card — image, title, a secondary field — in the first screen; each item a
|
|
69
|
-
link to its item page (`/<collection>/<slug>`); loading, empty, and error states that look
|
|
70
|
-
different; "load more" when `hasNext`.
|
|
71
|
-
- **Item page:** title, image, the date formatted, the body as HTML, related items only when a
|
|
72
|
-
reference field carries them; a slug that resolves to nothing shows only the not-found state.
|
|
73
|
-
- **Copy:** nothing the owner didn't supply — no invented fields, counts, or authors; no Wix IDs or
|
|
74
|
-
technical words in visible text.
|
|
75
|
-
|
|
76
|
-
### The contracts your components consume
|
|
77
|
-
|
|
78
|
-
Everything you need — tested and working as they are; read a file when something is off or the
|
|
79
|
-
brief wants more.
|
|
80
|
-
|
|
81
|
-
```ts
|
|
82
|
-
// CmsItem — display-ready, fields FLAT on the item (never item.data.*):
|
|
83
|
-
// { _id, _createdDate?, _updatedDate?, _owner?, ...fields }
|
|
84
|
-
// TEXT/URL/EMAIL → string · NUMBER → number · BOOLEAN → boolean
|
|
85
|
-
// DATE/DATETIME → ISO string (render: formatDate(item.publishDate) from wix/cms/items-core)
|
|
86
|
-
// IMAGE → resolved https URL (<img {...imgAttrs(item.photo, "33vw")} />; {} when absent → your placeholder)
|
|
87
|
-
// RICH_TEXT → the stored HTML string (render via set:html on a wrapper you control)
|
|
88
|
-
// REFERENCE/MULTI_REFERENCE → id(s); full CmsItem(s) when queried with include
|
|
89
|
-
|
|
90
|
-
// queryItems(collectionId, { filters?, sort?, limit?, skip?, include?, withTotal? })
|
|
91
|
-
// → { items: CmsItem[], hasNext, total } // filters: [{ field, op, value }]
|
|
92
|
-
// ops: eq ne gt ge lt le contains startsWith hasSome hasAll isEmpty isNotEmpty
|
|
93
|
-
// DATE comparands must be Date objects (an ISO string matches nothing)
|
|
94
|
-
// getItemBy(collectionId, field, value) → CmsItem | null // slug routing
|
|
95
|
-
// getItemById(collectionId, id) → CmsItem | null
|
|
96
|
-
// countItems(collectionId, filters?) → number
|
|
97
|
-
|
|
98
|
-
// useCollection(collectionId, { filters?, sort?, limit?, include?, initialItems?, initialHasNext? })
|
|
99
|
-
// → { items: CmsItem[]|null /* null = loading → skeletons */,
|
|
100
|
-
// hasNext, loadMore(), loadingMore, error } // changing filters/sort refetches
|
|
101
|
-
|
|
102
|
-
// useItem(collectionId, { id } | { by: { field, value } }, { initialItem? })
|
|
103
|
-
// → { item: CmsItem|null, notFound, error } // notFound → your 404/miss state
|
|
104
|
-
|
|
105
|
-
// Writes (only when the collection's permissions allow the caller):
|
|
106
|
-
// insertItem(collectionId, data) // dates as Date objects; never set _owner
|
|
107
|
-
// patchItemFields(collectionId, id, fields) // the safe partial change
|
|
108
|
-
// updateItem(collectionId, item) // REPLACES the whole item — see hard rules
|
|
109
|
-
// removeItem(collectionId, id)
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### The pages and islands you create — skeletons
|
|
113
|
-
|
|
114
|
-
The class names in these skeletons are the Astro/React spelling of layout rules that hold on
|
|
115
|
-
every stack, and each rule is also named in words beside its classes. On a stack where the hooks
|
|
116
|
-
don't deploy (`lib`, `static`, a port), keep the rule and write it in your own CSS.
|
|
117
|
-
|
|
118
|
-
Each page is a thin SSR shell (fetch → DTO props → island, or no island when the page has no
|
|
119
|
-
interactivity); each island is a thin view over a hook. Hooks first, branches after. The islands
|
|
120
|
-
render on the server too (`client:load` SSRs), and by then the 200 and headers are already sent — a
|
|
121
|
-
render throw truncates the body mid-stream. Render every state totally; nothing in a render path may
|
|
122
|
-
throw.
|
|
123
|
-
|
|
124
|
-
```astro
|
|
125
|
-
---
|
|
126
|
-
// src/pages/recipes.astro — YOU create it (one per content collection). Items are fetched
|
|
127
|
-
// SERVER-SIDE (view-source shows titles) and handed to the island as serialized DTO props.
|
|
128
|
-
import SiteLayout from "../layouts/SiteLayout.astro";
|
|
129
|
-
import CollectionView from "../components/cms/CollectionView";
|
|
130
|
-
import { queryItems } from "../wix/cms/items";
|
|
131
|
-
import type { CmsPage } from "../wix/cms/types";
|
|
132
|
-
const SORT = [{ field: "publishDate", direction: "desc" as const }];
|
|
133
|
-
let page: CmsPage = { items: [], hasNext: false, total: null };
|
|
134
|
-
try {
|
|
135
|
-
page = await queryItems("recipes", { sort: SORT, limit: 12 });
|
|
136
|
-
} catch {
|
|
137
|
-
// Guarded: an unguarded SSR throw truncates the response mid-stream; the island renders your empty state.
|
|
138
|
-
}
|
|
139
|
-
---
|
|
140
|
-
<SiteLayout title="Recipes">
|
|
141
|
-
<!-- your page heading / intro, then: -->
|
|
142
|
-
<CollectionView client:load collectionId="recipes" sort={SORT} limit={12} initialItems={page.items} initialHasNext={page.hasNext} />
|
|
143
|
-
</SiteLayout>
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
```astro
|
|
147
|
-
---
|
|
148
|
-
// src/pages/recipes/[slug].astro — YOU create it. SEO is plain <title>/<meta name="description">
|
|
149
|
-
// from the DTO via the layout props — CMS collections have NO owner-editable SEO item type, so
|
|
150
|
-
// don't copy another vertical's wixMetadata/<SEO.Tags> wiring.
|
|
151
|
-
import SiteLayout from "../../layouts/SiteLayout.astro";
|
|
152
|
-
import { getItemBy } from "../../wix/cms/items";
|
|
153
|
-
import { formatDate } from "../../wix/cms/items-core";
|
|
154
|
-
import { imgAttrs } from "../../wix/media";
|
|
155
|
-
let item = null;
|
|
156
|
-
try {
|
|
157
|
-
item = await getItemBy("recipes", "slug", Astro.params.slug!, { include: ["categories"] });
|
|
158
|
-
} catch {
|
|
159
|
-
// Guarded: an unhandled SSR throw truncates the response mid-stream.
|
|
160
|
-
}
|
|
161
|
-
// A missing slug is a real 404 — never a fallback to another item.
|
|
162
|
-
if (!item) return new Response(null, { status: 404 });
|
|
163
|
-
---
|
|
164
|
-
<SiteLayout title={String(item.title)} description={String(item.summary ?? "")}>
|
|
165
|
-
<!-- your detail layout: title; the image through imgAttrs (a placeholder when it returns {});
|
|
166
|
-
formatDate(item.publishDate); the RICH_TEXT body with set:html on a wrapper you control;
|
|
167
|
-
included reference items by name — never an id as content -->
|
|
168
|
-
</SiteLayout>
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
```tsx
|
|
172
|
-
// src/components/cms/CollectionView.tsx — YOU build it; a listing page mounts it.
|
|
173
|
-
import { useCollection } from "../../hooks/cms/useCollection";
|
|
174
|
-
import { formatDate } from "../../wix/cms/items-core";
|
|
175
|
-
import { imgAttrs } from "../../wix/media";
|
|
176
|
-
import type { CmsFilter, CmsItem, CmsSort } from "../../wix/cms/types";
|
|
177
|
-
|
|
178
|
-
export default function CollectionView(props: {
|
|
179
|
-
collectionId: string;
|
|
180
|
-
filters?: CmsFilter[];
|
|
181
|
-
sort?: CmsSort[];
|
|
182
|
-
limit?: number;
|
|
183
|
-
initialItems?: CmsItem[]; // SSR props from your page — pass straight to useCollection;
|
|
184
|
-
initialHasNext?: boolean; // omitted in a SPA (client fetch)
|
|
185
|
-
}) {
|
|
186
|
-
const { collectionId, ...options } = props;
|
|
187
|
-
const list = useCollection(collectionId, options);
|
|
188
|
-
// …you implement the render:
|
|
189
|
-
// • error → a short inline message
|
|
190
|
-
// • items === null → skeleton cards; [] → your honest empty state (no mock items)
|
|
191
|
-
// • else YOUR grid of YOUR cards: image via <img {...imgAttrs(item.photo, "(min-width: 768px) 33vw, 100vw")} alt={String(item.title)} />
|
|
192
|
-
// — src, srcSet, sizes and lazy loading in one spread; {} when the field is absent → your
|
|
193
|
-
// placeholder; title WRAPS (`min-w-0`, `break-words`), no `truncate`; the date as
|
|
194
|
-
// formatDate(item.publishDate); the card links to `/${collectionId}/${item.slug}`
|
|
195
|
-
// • hasNext → your "load more" control calling loadMore() (disabled while loadingMore)
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### The reference files for stacks where the components don't deploy
|
|
200
|
-
|
|
201
|
-
On `lib`, `static`, and a port, nothing under `hooks/` arrives, and CMS ships no components. The
|
|
202
|
-
state machines behind the hooks do arrive — `wix/cms/collection-store.ts`, `item-store.ts` — so you
|
|
203
|
-
never rewrite them: create a store per surface, `subscribe`, render from `getState()`, call its
|
|
204
|
-
actions. Their `CollectionState` / `ItemState` interfaces are the render contract; read those. What
|
|
205
|
-
you write is the rendering — cards, the item view, the states — to the skeletons above. The two
|
|
206
|
-
hooks under `references/cms/app/hooks/cms/` are the binding pattern, ten lines each, if your
|
|
207
|
-
framework's external-store primitive is unfamiliar.
|
|
208
|
-
|
|
209
|
-
### Wiring — Astro (default)
|
|
210
|
-
|
|
211
|
-
1. Set the `@theme` tokens (one edit); brand `SiteLayout.astro` (one pass) and add one nav link
|
|
212
|
-
per content surface.
|
|
213
|
-
2. Author your pages under `src/pages/` per the skeletons above — SSR fetch in the frontmatter,
|
|
214
|
-
DTO props to your islands (`client:load`; a page with no interactivity needs no island at all).
|
|
215
|
-
3. Write `pages/index.astro` (home) on `SiteLayout`.
|
|
216
|
-
4. **Author your surfaces in as few messages as possible** — batch multiple Writes per message
|
|
217
|
-
(components and pages are independent files).
|
|
218
|
-
|
|
219
|
-
### Wiring — another JS framework (`--stack lib`: Vue, Svelte, Solid, plain Vite)
|
|
220
|
-
|
|
221
|
-
`deploy.mjs cms --stack lib` put the data layer in `src/wix/` and nothing else: `sdk.ts` (the
|
|
222
|
-
visitor client, configured with the public client id), `media.ts`, `money.ts`, and `wix/cms/` —
|
|
223
|
-
`items.ts`, `types.ts`, `items-core.ts`, and the two stores `collection-store.ts`, `item-store.ts`.
|
|
224
|
-
None of it is React. The hooks don't ship on this stack; the stores replace them, and you write the
|
|
225
|
-
components in your framework to the contracts on this page:
|
|
226
|
-
|
|
227
|
-
- bind the stores with your framework's external-store primitive (Vue: `shallowRef` updated in
|
|
228
|
-
`subscribe`; Svelte: `readable(store.getState(), (set) => store.subscribe(() => set(store.getState())))`;
|
|
229
|
-
Solid: a signal set in `subscribe`). `createCollectionStore({ collectionId, filters?, sort?, limit?, include?, initialItems? })`
|
|
230
|
-
per listing (`start()` when mounted, `stop()` when unmounted, `setQuery()` when filters change,
|
|
231
|
-
`loadMore()`), `createItemStore({ collectionId, ref: { id } | { by }, initialItem? })` per item
|
|
232
|
-
surface. State in, actions out — exactly the hooks' contracts above.
|
|
233
|
-
|
|
234
|
-
Routes `/<collection>`, `/<collection>/:slug` (via `getItemBy`, null → your 404); dev server on
|
|
235
|
-
4321; a static build goes through `npx @wix/cli@latest release` with `site.outputDirectory`
|
|
236
|
-
pointing at the build folder, an SSR build is hosted by you. Page tags from the item's own fields.
|
|
237
|
-
|
|
238
|
-
### Wiring — static site (`--stack static`, no bundler)
|
|
239
|
-
|
|
240
|
-
`deploy.mjs cms --stack static --out site` put the REST layer in `site/js/wix/` (browser ESM, the
|
|
241
|
-
`.ts` beside each `.js` for reading). Everything the visitor loads lives under `site/` — pages,
|
|
242
|
-
styles, `js/` — and `wix.config.json`'s `site.outputDirectory` is `"./site"`; the project root
|
|
243
|
-
(config, plan, seed output) is never the upload. Same function names and DTOs as the table above,
|
|
244
|
-
so the contracts on this page hold unchanged: `queryItems`, `getItemBy`, `getItemById`,
|
|
245
|
-
`countItems` (and the writes) from `./js/wix/items.js`; `formatDate` from `./js/wix/items-core.js`;
|
|
246
|
-
`imgAttrs` from `./js/wix/media.js`. The state machines ship too: `createCollectionStore` from
|
|
247
|
-
`./js/wix/collection-store.js` (the listing — `start()` once the page is up, `loadMore()`,
|
|
248
|
-
`setQuery()`), `createItemStore` from `./js/wix/item-store.js` (the item page — `notFound` is your
|
|
249
|
-
404 state). No components ship — you write the rendering in plain JS: one render function per
|
|
250
|
-
surface that reads `getState()`, called from `subscribe`, with the surface's controls calling the
|
|
251
|
-
store's actions. Pages are `<collection>.html` and `item.html?collection=…&slug=…` (Wix static
|
|
252
|
-
hosting serves files, not directories — name the file and link to it). Set `document.title` and
|
|
253
|
-
the meta description from the item's fields once it loads. The visitor token persists in
|
|
254
|
-
`localStorage` on its own; never mint per page. Reads work on any collection whose `read` is
|
|
255
|
-
`ANYONE`; a write from the page succeeds only where the seed opened that verb (403 → a permissions
|
|
256
|
-
step). `npx @wix/cli@latest release` uploads `site/`.
|
|
257
|
-
|
|
258
|
-
### Wiring — server-rendered, another language (Flask, Laravel, Rails, …)
|
|
259
|
-
|
|
260
|
-
Run `deploy.mjs cms --stack static` in the project folder anyway: `js/wix/` is both the
|
|
261
|
-
browser-side code and the readable spec. Then split by where the call runs. **Reads on the
|
|
262
|
-
server:** port `js/wix/items.ts` and `items-core.ts` to your language — `queryItems`, `getItemBy`,
|
|
263
|
-
`getItemById`, `countItems` returning the same DTO shapes as dicts (the core's `toValue` rules:
|
|
264
|
-
`{ "$date": iso }` → ISO string, `wix:image://` → the https URL form in `media.ts`), one anonymous
|
|
265
|
-
visitor token per process for these public reads (mint and refresh per `client.ts`) — and render
|
|
266
|
-
the listing and item pages in your templates to the contracts above, so titles are in the HTML;
|
|
267
|
-
page tags from the item's fields. **Visitor writes in the browser** (a collection the seed opened
|
|
268
|
-
to visitors or members): `insertItem` from `./js/wix/items.js` on the page, exactly as the static
|
|
269
|
-
wiring above — the browser owns the visitor token, so the server handles no per-visitor tokens.
|
|
270
|
-
Routes stay `/<collection>`, `/<collection>/<slug>`.
|
|
271
|
-
|
|
272
|
-
**Pre-rendered (Frozen-Flask, Pelican, any static-site generator) → Wix-hosted.** Same port for the
|
|
273
|
-
reads, run at build time with one anonymous token; the generator must emit every item page (walk
|
|
274
|
-
`queryItems` by `skip` until `hasNext` is false — never only the first page). Run
|
|
275
|
-
`deploy.mjs cms --stack static --out <build dir>` so `js/wix/` is inside the output the pages
|
|
276
|
-
import from, point `site.outputDirectory` at that folder, `wix release`. Pages sit at different
|
|
277
|
-
depths (`/`, `/<collection>/…`): give the templates one base path to `js/wix/` (a template
|
|
278
|
-
variable, or root-relative `/js/wix/…`), never a relative `./js/wix/` — it breaks one level down.
|
|
279
|
-
The frozen listing is the first paint; a filter or "load more" still runs client-side on it
|
|
280
|
-
through `createCollectionStore()` from `./js/wix/collection-store.js`, exactly as on a static
|
|
281
|
-
site. Close with the live URL, the rebuild + release command, and one line for the owner:
|
|
282
|
-
dashboard edits to the content reach the site when that command runs.
|
|
283
|
-
|
|
284
|
-
### Wiring — React SPA (Vite etc.)
|
|
285
|
-
|
|
286
|
-
Import `./styles/global.css` once at the app entry (needs `@tailwindcss/vite` in the vite
|
|
287
|
-
plugins — deploy added the dep). Routes are yours: a list route per collection on
|
|
288
|
-
`useCollection`, a detail route on `useItem` with `by: { field: "slug", value }` (components
|
|
289
|
-
fetch client-side when no `initialItems` / `initialItem` is passed). Deploy wrote the public
|
|
290
|
-
client id into `wix/config.ts`; nothing else to configure.
|
|
291
|
-
|
|
292
|
-
## Hard rules
|
|
293
|
-
|
|
294
|
-
- **Data only through the shipped exports** — never re-derive a Wix Data request, never
|
|
295
|
-
import `@wix/data` directly in your components, never hand-build a `static.wixstatic.com`
|
|
296
|
-
URL.
|
|
297
|
-
- **The id is `_id`, fields are flat** — `item.id` is undefined; `item.data.title` is the
|
|
298
|
-
REST shape and reads undefined.
|
|
299
|
-
- **Bind by the seed plan's ids and keys verbatim** — collection ids have no namespace; a
|
|
300
|
-
mistyped field key reads as a blank, not an error.
|
|
301
|
-
- **An empty read on a PUBLIC collection is a seed permissions bug** (`read` must be
|
|
302
|
-
`ANYONE`) — fix the seed, never reach for `auth.elevate` (it doesn't exist on this path).
|
|
303
|
-
On a member-scoped collection an empty anonymous read is the gate working, not a bug.
|
|
304
|
-
- **`updateItem` REPLACES the whole item** — omitted fields are wiped. Spread the full item,
|
|
305
|
-
or use `patchItemFields`. Date fields on any write are Date objects — a round-tripped ISO
|
|
306
|
-
string is silently stored as text and breaks date queries.
|
|
307
|
-
- **Writes 403 unless the collection was seeded with that verb open** — surface a 403 as a
|
|
308
|
-
permissions setup step (which permission, where in the dashboard), not a code bug. Anything
|
|
309
|
-
that needs elevated access runs server-side per `references/shared/CUSTOM_OPERATIONS.md`.
|
|
310
|
-
- **User-created content is a CMS contribution flow.** For a member or visitor submission that
|
|
311
|
-
the app must later list, use the seeded CMS collection and its intended permission preset.
|
|
312
|
-
If the operation needs elevated access — especially a browser-created file that must enter
|
|
313
|
-
Media Manager — follow `references/shared/CUSTOM_OPERATIONS.md`: validate the caller and
|
|
314
|
-
input in a narrow server endpoint before elevating one documented operation. Never call a
|
|
315
|
-
privileged Media API directly from a client island.
|
|
316
|
-
- **Use the shipped upload capability when it fits.** Declare its named policy in
|
|
317
|
-
`plan.capabilities.mediaUpload`; Fast deploys the endpoint, client helper, dependencies, and
|
|
318
|
-
generated policy module. Your CMS surface calls `uploadMedia(policyId, file)` and stores the
|
|
319
|
-
returned Wix Media reference. Do not author another upload endpoint for that flow.
|
|
320
|
-
- **RICH_TEXT is HTML, not plain text** — render it with `set:html` (Astro) /
|
|
321
|
-
`dangerouslySetInnerHTML` (React) on a wrapper; never interpolate it as text.
|
|
322
|
-
- **Dates through `formatDate`**, images through `imgAttrs` — the DTO's ISO string and https URL
|
|
323
|
-
are data, not copy.
|
|
324
|
-
- Reference fields hold ids unless the query passed `include` — don't render an id as
|
|
325
|
-
content.
|
|
326
|
-
- Guard absent IMAGE fields — `imgAttrs` returns `{}`; render a fallback, never an empty/broken `<img>`.
|
|
327
|
-
- **Page at the source, not on a loaded list.** `hasNext`/`loadMore()` fetch the next page from
|
|
328
|
-
Wix; never raise the page limit instead of paging, never filter or sort client-side a page you
|
|
329
|
-
already hold — pass `filters`/`sort` and let Wix apply them across the collection.
|
|
330
|
-
- **Call every hook before any conditional return.** An island that returns early for
|
|
331
|
-
`notFound`/loading above its hooks changes hook order between renders and React throws.
|
|
332
|
-
- Where the shipped code deploys with Tailwind (Astro, React): theme via the `@theme` tokens, your
|
|
333
|
-
markup on the same tokens; no parallel theme files, no hardcoded palettes. Where it doesn't
|
|
334
|
-
(`lib`, `static`, a port): style with whatever your stack does well, on one token set of your
|
|
335
|
-
own; the rule that survives is the token set, not Tailwind.
|
|
336
|
-
- Live data or an honest empty state — never mock items or invent fields not in the plan.
|
|
337
|
-
|
|
338
|
-
## Point the user to their dashboard
|
|
339
|
-
|
|
340
|
-
Hand the owner these links — `{siteId}` is `siteId` in `wix.config.json` (the deploy JSON prints it as
|
|
341
|
-
`dashboardUrl`); a collection id is its `_id` (the seed result lists them).
|
|
342
|
-
|
|
343
|
-
| page | `https://manage.wix.com/dashboard/{siteId}/` + |
|
|
344
|
-
|---|---|
|
|
345
|
-
| Collections | `wix-cms` |
|
|
346
|
-
| A collection's items (fields, and More Actions → Permissions & Privacy) | `wix-cms/data/{collectionId}` |
|
|
347
|
-
|
|
348
|
-
## Seeding
|
|
349
|
-
|
|
350
|
-
Per `seed/SEED.md` — plain-data `plan.json` into `seed-cms.mjs` from the project root. The
|
|
351
|
-
plan is the content model your pages bind to: design collections that exercise the UI
|
|
352
|
-
(a `slug` field per detail page, an IMAGE field with a verified `imageUrl` per item, a DATE
|
|
353
|
-
field when the content is chronological).
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// React binding of the collection store (wix/cms/collection-store.ts) — the list state machine
|
|
2
|
-
// lives there, framework-free; this hook subscribes to one instance per mounted listing. SSR-friendly:
|
|
3
|
-
// pass server-fetched items as `initialItems` (Astro frontmatter / server component) and no client
|
|
4
|
-
// fetch happens for the first page; a SPA passes nothing. Changing filters/sort (by value) refetches;
|
|
5
|
-
// loadMore() appends the next page (skip paging). Astro islands and React SPAs use this; a static
|
|
6
|
-
// page, Vue, or Svelte uses the store directly.
|
|
7
|
-
import { useEffect, useRef, useSyncExternalStore } from "react";
|
|
8
|
-
import { createCollectionStore, type CollectionStore } from "../../wix/cms/collection-store";
|
|
9
|
-
import type { CmsFilter, CmsItem, CmsSort } from "../../wix/cms/types";
|
|
10
|
-
|
|
11
|
-
export interface UseCollectionOptions {
|
|
12
|
-
filters?: CmsFilter[];
|
|
13
|
-
sort?: CmsSort[];
|
|
14
|
-
/** Page size (default 20). */
|
|
15
|
-
limit?: number;
|
|
16
|
-
/** Reference field keys to inline as full items. */
|
|
17
|
-
include?: string[];
|
|
18
|
-
/** Server-fetched first page — must come from the SAME query (filters/sort/limit/include). */
|
|
19
|
-
initialItems?: CmsItem[];
|
|
20
|
-
/** The server fetch's hasNext. Omitted → inferred (a full first page ⇒ assume more). */
|
|
21
|
-
initialHasNext?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface UseCollection {
|
|
25
|
-
/** null while the first load is in flight — render skeletons, not an empty state. */
|
|
26
|
-
items: CmsItem[] | null;
|
|
27
|
-
hasNext: boolean;
|
|
28
|
-
loadMore: () => void;
|
|
29
|
-
loadingMore: boolean;
|
|
30
|
-
error: string | null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function useCollection(collectionId: string, options: UseCollectionOptions = {}): UseCollection {
|
|
34
|
-
const { filters, sort, limit = 20, include, initialItems, initialHasNext } = options;
|
|
35
|
-
const ref = useRef<CollectionStore | null>(null);
|
|
36
|
-
if (!ref.current) ref.current = createCollectionStore({ collectionId, filters, sort, limit, include, initialItems, initialHasNext });
|
|
37
|
-
const store = ref.current;
|
|
38
|
-
// Query identity by value — Dates in filters serialize to ISO, so this is stable.
|
|
39
|
-
const key = JSON.stringify([collectionId, filters ?? null, sort ?? null, limit, include ?? null]);
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
store.setQuery({ collectionId, filters, sort, limit, include });
|
|
42
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
|
-
}, [store, key]);
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
store.start();
|
|
46
|
-
return () => store.stop();
|
|
47
|
-
}, [store]);
|
|
48
|
-
const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);
|
|
49
|
-
return { items: state.items, hasNext: state.hasNext, loadMore: store.loadMore, loadingMore: state.loadingMore, error: state.error };
|
|
50
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// React binding of the item store (wix/cms/item-store.ts) — one item by `_id` or by a field match
|
|
2
|
-
// (slug routing), the loader lives there, framework-free. SSR-friendly: pass the server-fetched
|
|
3
|
-
// item as `initialItem` and no client fetch happens; a SPA passes nothing.
|
|
4
|
-
import { useEffect, useRef, useSyncExternalStore } from "react";
|
|
5
|
-
import { createItemStore, type ItemRef, type ItemStore } from "../../wix/cms/item-store";
|
|
6
|
-
import type { CmsItem } from "../../wix/cms/types";
|
|
7
|
-
|
|
8
|
-
/** Exactly one of `id` / `by`. */
|
|
9
|
-
export type UseItemRef = ItemRef;
|
|
10
|
-
|
|
11
|
-
export interface UseItemOptions {
|
|
12
|
-
initialItem?: CmsItem;
|
|
13
|
-
/** Reference field keys to inline as full items. */
|
|
14
|
-
include?: string[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface UseItem {
|
|
18
|
-
/** null while loading OR when not found — branch on notFound for the miss state. */
|
|
19
|
-
item: CmsItem | null;
|
|
20
|
-
notFound: boolean;
|
|
21
|
-
error: string | null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function useItem(collectionId: string, ref: UseItemRef, options: UseItemOptions = {}): UseItem {
|
|
25
|
-
const { initialItem, include } = options;
|
|
26
|
-
// A new ref (another id or slug) is another item — a fresh store, as useProductDetail does per slug.
|
|
27
|
-
const key = JSON.stringify([collectionId, ref.id ?? null, ref.by?.field ?? null, ref.by?.value ?? null]);
|
|
28
|
-
const holder = useRef<{ key: string; store: ItemStore } | null>(null);
|
|
29
|
-
if (!holder.current || holder.current.key !== key) holder.current = { key, store: createItemStore({ collectionId, ref, initialItem, include }) };
|
|
30
|
-
const store = holder.current.store;
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
store.start();
|
|
33
|
-
return () => store.stop();
|
|
34
|
-
}, [store]);
|
|
35
|
-
const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);
|
|
36
|
-
return { item: state.item, notFound: state.notFound, error: state.error };
|
|
37
|
-
}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
// One collection as list state, framework-free — the logic behind useCollection, usable from React
|
|
2
|
-
// (useCollection wraps it with useSyncExternalStore), from a static page or Vue/Svelte (subscribe
|
|
3
|
-
// and render), or as the specification for a port. Same shape as the storefront stores: state,
|
|
4
|
-
// actions, subscribe/getState, emit after every change.
|
|
5
|
-
//
|
|
6
|
-
// The query (collection, filters, sort, page size, includes) is identified BY VALUE; a changed
|
|
7
|
-
// query refetches from the first page, a late response from a superseded query is dropped.
|
|
8
|
-
// loadMore() appends the next page (skip paging: skip = items shown so far).
|
|
9
|
-
//
|
|
10
|
-
// SSR-friendly: seed with `initialItems` from the SAME query and no client fetch happens for the
|
|
11
|
-
// first page. One store per mounted listing (a page can hold two collections): createCollectionStore(),
|
|
12
|
-
// not a singleton.
|
|
13
|
-
import { queryItems } from "./items";
|
|
14
|
-
import type { CmsFilter, CmsItem, CmsSort } from "./types";
|
|
15
|
-
|
|
16
|
-
export interface CollectionQuery {
|
|
17
|
-
collectionId?: string;
|
|
18
|
-
filters?: CmsFilter[];
|
|
19
|
-
sort?: CmsSort[];
|
|
20
|
-
/** Page size (default 20). */
|
|
21
|
-
limit?: number;
|
|
22
|
-
/** Reference field keys to inline as full items. */
|
|
23
|
-
include?: string[];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface CollectionStoreOptions extends CollectionQuery {
|
|
27
|
-
collectionId: string;
|
|
28
|
-
/** Server-fetched first page — must come from the SAME query (filters/sort/limit/include). */
|
|
29
|
-
initialItems?: CmsItem[];
|
|
30
|
-
/** The server fetch's hasNext. Omitted → inferred (a full first page ⇒ assume more). */
|
|
31
|
-
initialHasNext?: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Everything a listing surface renders from. Read it with getState() or through a subscription. */
|
|
35
|
-
export interface CollectionState {
|
|
36
|
-
/** null while the first load is in flight — render skeletons, not an empty state. */
|
|
37
|
-
items: CmsItem[] | null;
|
|
38
|
-
hasNext: boolean;
|
|
39
|
-
loadingMore: boolean;
|
|
40
|
-
error: string | null;
|
|
41
|
-
/** True while items is null and a load is running (the same condition, named). */
|
|
42
|
-
loading: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface CollectionStore {
|
|
46
|
-
getState(): CollectionState;
|
|
47
|
-
subscribe(listener: () => void): () => void;
|
|
48
|
-
/** Run the first query unless the seed already answered it. Call once when mounted (a browser). */
|
|
49
|
-
start(): void;
|
|
50
|
-
/** Stop reacting; drop late responses. */
|
|
51
|
-
stop(): void;
|
|
52
|
-
/** Change the query by value — same values keep the page, a change refetches from the first page. */
|
|
53
|
-
setQuery(query: CollectionQuery): void;
|
|
54
|
-
/** Append the next page (skip = items shown so far). No-op while loading or when there is none. */
|
|
55
|
-
loadMore(): Promise<void>;
|
|
56
|
-
/** Re-run the current query after an error. */
|
|
57
|
-
retry(): void;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const queryKey = (q: Required<Pick<CollectionQuery, "collectionId" | "limit">> & CollectionQuery): string =>
|
|
61
|
-
// Dates in filters serialize to ISO, so this is stable.
|
|
62
|
-
JSON.stringify([q.collectionId, q.filters ?? null, q.sort ?? null, q.limit, q.include ?? null]);
|
|
63
|
-
|
|
64
|
-
export function createCollectionStore(options: CollectionStoreOptions): CollectionStore {
|
|
65
|
-
let collectionId = options.collectionId;
|
|
66
|
-
let filters = options.filters;
|
|
67
|
-
let sort = options.sort;
|
|
68
|
-
let limit = options.limit ?? 20;
|
|
69
|
-
let include = options.include;
|
|
70
|
-
const key = () => queryKey({ collectionId, filters, sort, limit, include });
|
|
71
|
-
|
|
72
|
-
let items: CmsItem[] | null = options.initialItems ?? null;
|
|
73
|
-
let hasNext = options.initialHasNext ?? (options.initialItems ? options.initialItems.length >= limit : false);
|
|
74
|
-
let loadingMore = false;
|
|
75
|
-
let error: string | null = null;
|
|
76
|
-
// The query the current items answer (null = nothing answered yet).
|
|
77
|
-
let pageKey: string | null = options.initialItems ? key() : null;
|
|
78
|
-
let inflight = false;
|
|
79
|
-
let started = false;
|
|
80
|
-
let generation = 0;
|
|
81
|
-
const listeners = new Set<() => void>();
|
|
82
|
-
let snapshot: CollectionState | null = null;
|
|
83
|
-
const emit = () => { snapshot = null; for (const fn of listeners) fn(); };
|
|
84
|
-
|
|
85
|
-
function getState(): CollectionState {
|
|
86
|
-
if (snapshot) return snapshot;
|
|
87
|
-
snapshot = { items, hasNext, loadingMore, error, loading: items === null };
|
|
88
|
-
return snapshot;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function run(): void {
|
|
92
|
-
if (!started) return;
|
|
93
|
-
const k = key();
|
|
94
|
-
const id = ++generation;
|
|
95
|
-
pageKey = k; inflight = true;
|
|
96
|
-
items = null; error = null; loadingMore = false;
|
|
97
|
-
emit();
|
|
98
|
-
queryItems(collectionId, { filters, sort, limit, include })
|
|
99
|
-
.then((page) => {
|
|
100
|
-
if (generation !== id) return; // superseded — drop it
|
|
101
|
-
items = page.items; hasNext = page.hasNext; inflight = false;
|
|
102
|
-
emit();
|
|
103
|
-
})
|
|
104
|
-
.catch((e) => {
|
|
105
|
-
if (generation !== id) return;
|
|
106
|
-
items = []; hasNext = false; inflight = false;
|
|
107
|
-
error = e instanceof Error ? e.message : String(e);
|
|
108
|
-
emit();
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
getState,
|
|
114
|
-
subscribe(fn) {
|
|
115
|
-
listeners.add(fn);
|
|
116
|
-
return () => listeners.delete(fn);
|
|
117
|
-
},
|
|
118
|
-
start() {
|
|
119
|
-
if (started) return;
|
|
120
|
-
started = true;
|
|
121
|
-
// The SSR seed answered this exact query — no fetch; a dropped first load reruns.
|
|
122
|
-
if (pageKey !== key() || (items === null && !inflight)) run();
|
|
123
|
-
},
|
|
124
|
-
stop() {
|
|
125
|
-
started = false;
|
|
126
|
-
generation++;
|
|
127
|
-
inflight = false;
|
|
128
|
-
},
|
|
129
|
-
setQuery(q) {
|
|
130
|
-
if (q.collectionId !== undefined) collectionId = q.collectionId;
|
|
131
|
-
filters = q.filters; sort = q.sort; include = q.include;
|
|
132
|
-
if (q.limit !== undefined) limit = q.limit;
|
|
133
|
-
if (key() === pageKey) return; // same values — same page
|
|
134
|
-
if (started) run();
|
|
135
|
-
},
|
|
136
|
-
async loadMore() {
|
|
137
|
-
const current = items;
|
|
138
|
-
if (!current || loadingMore) return;
|
|
139
|
-
const id = generation;
|
|
140
|
-
loadingMore = true; emit();
|
|
141
|
-
try {
|
|
142
|
-
const page = await queryItems(collectionId, { filters, sort, limit, include, skip: current.length });
|
|
143
|
-
if (generation !== id) return;
|
|
144
|
-
items = [...(items ?? []), ...page.items];
|
|
145
|
-
hasNext = page.hasNext;
|
|
146
|
-
} catch (e) {
|
|
147
|
-
if (generation !== id) return;
|
|
148
|
-
error = e instanceof Error ? e.message : String(e);
|
|
149
|
-
} finally {
|
|
150
|
-
if (generation === id) { loadingMore = false; emit(); }
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
retry() {
|
|
154
|
-
pageKey = null;
|
|
155
|
-
run();
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
}
|