@thorprovider/storefront 0.3.1 → 0.4.0-mvp.2
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 +321 -152
- package/VENDOR.md +69 -0
- package/assets/openspec/config.yaml +38 -0
- package/assets/templates/AGENTS.md +76 -0
- package/assets/templates/app/app/[[...slug]]/page.tsx +54 -2
- package/assets/templates/app/app/[[...slug]]/renderer.tsx +13 -2
- package/assets/templates/app/app/globals.css +5 -8
- package/assets/templates/app/app/layout.tsx +17 -7
- package/assets/templates/app/app/robots.ts +19 -0
- package/assets/templates/app/app/sitemap.ts +71 -0
- package/assets/templates/app/lib/__STOREFRONT__/actions.ts +612 -0
- package/assets/templates/app/lib/__STOREFRONT__/cart-state.ts +66 -0
- package/assets/templates/app/lib/__STOREFRONT__/catalog.ts +50 -57
- package/assets/templates/app/lib/__STOREFRONT__/commerce.ts +679 -0
- package/assets/templates/app/lib/__STOREFRONT__/composition.ts +26 -0
- package/assets/templates/app/lib/__STOREFRONT__/handlers.core.ts +197 -0
- package/assets/templates/app/lib/__STOREFRONT__/handlers.ts +5 -36
- package/assets/templates/app/lib/__STOREFRONT__/icon-map.ts +27 -0
- package/assets/templates/app/lib/__STOREFRONT__/mappers.ts +13 -11
- package/assets/templates/app/lib/__STOREFRONT__/registry.tsx +264 -51
- package/assets/templates/app/lib/__STOREFRONT__/runtime.ts +6 -3
- package/assets/templates/app/lib/__STOREFRONT__/schema.ts +136 -0
- package/assets/templates/app/lib/__STOREFRONT__/section-observation.ts +182 -0
- package/assets/templates/app/lib/__STOREFRONT__/section-sources.ts +130 -0
- package/assets/templates/app/lib/__STOREFRONT__/session.core.ts +470 -0
- package/assets/templates/app/lib/__STOREFRONT__/session.ts +169 -0
- package/assets/templates/app/lib/__STOREFRONT__/shell/content.ts +120 -0
- package/assets/templates/app/lib/__STOREFRONT__/shell/props.ts +38 -0
- package/assets/templates/app/lib/__STOREFRONT__/spec/index.ts +129 -10
- package/assets/templates/app/lib/__STOREFRONT__/spec/page-root.ts +5 -1
- package/assets/templates/app/lib/__STOREFRONT__/spec/seo.ts +191 -0
- package/assets/templates/app/lib/__STOREFRONT__/state.core.ts +257 -0
- package/assets/templates/app/lib/__STOREFRONT__/state.ts +7 -31
- package/assets/templates/app/lib/__STOREFRONT__/store-context.ts +161 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/cta.client.tsx +25 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/cta.tsx +16 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/faq.client.tsx +24 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/faq.tsx +5 -18
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/index.ts +18 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/logoCloud.tsx +26 -14
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/pricing.tsx +36 -18
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/products.client.tsx +100 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/products.tsx +19 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/schema.cta.ts +19 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/schema.faq.ts +18 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/schema.products.ts +39 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/statistics.tsx +35 -14
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/testimonials.tsx +31 -13
- package/assets/templates/app/lib/__STOREFRONT__/views/types.ts +5 -3
- package/assets/templates/features/checkout/handlers.ts +159 -0
- package/assets/templates/features/checkout/state.ts +61 -0
- package/assets/templates/features/customer-auth/handlers.ts +59 -0
- package/assets/templates/features/customer-auth/state.ts +45 -0
- package/assets/templates/features/recommendations/state.ts +11 -0
- package/assets/templates/views/account/content.ts +35 -0
- package/assets/templates/views/account/index.tsx +114 -0
- package/assets/templates/views/account/registry.tsx +439 -0
- package/assets/templates/views/account/schema.ts +53 -0
- package/assets/templates/views/cart/content.ts +11 -0
- package/assets/templates/views/cart/data.ts +23 -0
- package/assets/templates/views/cart/index.tsx +53 -0
- package/assets/templates/views/cart/props.ts +12 -0
- package/assets/templates/views/cart/registry.tsx +81 -0
- package/assets/templates/views/cart/schema.ts +52 -0
- package/assets/templates/views/category/assembly/assembly.json +29 -0
- package/assets/templates/views/category/assembly/index.skeleton.tsx +251 -0
- package/assets/templates/views/category/assembly/registry.skeleton.tsx +34 -0
- package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/binding.json +5 -0
- package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/catalog.part +4 -0
- package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/element.part +7 -0
- package/assets/templates/views/category/assembly/slots/breadcrumb/Breadcrumb/registry.part +18 -0
- package/assets/templates/views/category/assembly/slots/filter/CategoryFilter2/catalog.part +5 -0
- package/assets/templates/views/category/assembly/slots/filter/CategoryFilter2/element.part +34 -0
- package/assets/templates/views/category/assembly/slots/filter/CategoryFilter2/registry.part +71 -0
- package/assets/templates/views/category/content.ts +30 -0
- package/assets/templates/views/category/data.ts +12 -0
- package/assets/templates/views/category/index.tsx +299 -0
- package/assets/templates/views/category/props.ts +23 -0
- package/assets/templates/views/category/registry.tsx +122 -0
- package/assets/templates/views/category/schema.ts +91 -0
- package/assets/templates/views/checkout/content.ts +105 -0
- package/assets/templates/views/checkout/data.ts +23 -0
- package/assets/templates/views/checkout/index.tsx +111 -0
- package/assets/templates/views/checkout/props.ts +49 -0
- package/assets/templates/views/checkout/registry.tsx +217 -0
- package/assets/templates/views/checkout/schema.ts +229 -0
- package/assets/templates/views/home/assembly/assembly.json +33 -0
- package/assets/templates/views/home/assembly/index.skeleton.tsx +90 -0
- package/assets/templates/views/home/assembly/registry.skeleton.tsx +25 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature1/binding.json +5 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature1/catalog.part +4 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature1/element.part +4 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature1/registry.part +11 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature2/binding.json +5 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature2/catalog.part +4 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature2/element.part +4 -0
- package/assets/templates/views/home/assembly/slots/benefits/Feature2/registry.part +10 -0
- package/assets/templates/views/home/assembly/slots/categories/ProductCategory2/binding.json +5 -0
- package/assets/templates/views/home/assembly/slots/categories/ProductCategory2/catalog.part +4 -0
- package/assets/templates/views/home/assembly/slots/categories/ProductCategory2/element.part +5 -0
- package/assets/templates/views/home/assembly/slots/categories/ProductCategory2/registry.part +16 -0
- package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/binding.json +5 -0
- package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/catalog.part +4 -0
- package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/element.part +5 -0
- package/assets/templates/views/home/assembly/slots/hero/StorefrontHero1/registry.part +26 -0
- package/assets/templates/views/home/content.ts +70 -0
- package/assets/templates/views/home/data.ts +24 -0
- package/assets/templates/views/home/index.tsx +57 -85
- package/assets/templates/views/home/props.ts +22 -0
- package/assets/templates/views/home/registry.tsx +38 -22
- package/assets/templates/views/home/schema.ts +93 -0
- package/assets/templates/views/product/content.ts +25 -0
- package/assets/templates/views/product/data.ts +50 -0
- package/assets/templates/views/product/index.tsx +148 -0
- package/assets/templates/views/product/props.ts +27 -0
- package/assets/templates/views/product/registry.tsx +103 -0
- package/assets/templates/views/product/schema.ts +121 -0
- package/assets/templates/views/static/content.ts +99 -0
- package/assets/templates/views/static/index.tsx +60 -0
- package/assets/templates/views/static/registry.tsx +66 -0
- package/assets/templates/views/static/schema.ts +45 -0
- package/bin/storefront.js +2424 -148
- package/examples/merchandising/category-led.json +37 -0
- package/examples/merchandising/collection-led.json +37 -0
- package/package.json +15 -9
- package/recipes/archetypes.json +28 -14
- package/recipes/catalog.json +400 -0
- package/recipes/catalog.mjs +128 -0
- package/recipes/catalog.schema.json +64 -0
- package/recipes/feature.schema.json +89 -0
- package/recipes/features.json +162 -0
- package/recipes/manifest.schema.json +69 -0
- package/recipes/operations.schema.json +43 -0
- package/recipes/recipe.schema.json +11 -2
- package/recipes/recipes.json +76 -19
- package/recipes/sections.json +34 -5
- package/recipes/validate.mjs +838 -32
- package/scripts/candidate.mjs +236 -0
- package/scripts/composers.mjs +160 -0
- package/scripts/env-file.mjs +86 -0
- package/scripts/file-classes.mjs +121 -0
- package/scripts/logical-controls.mjs +61 -0
- package/scripts/manifest.mjs +298 -0
- package/scripts/migrate-english-routes.mjs +276 -0
- package/scripts/operation-registry.mjs +256 -0
- package/scripts/operations.mjs +720 -0
- package/scripts/ownership-conflict.mjs +356 -0
- package/scripts/pinning.mjs +573 -0
- package/scripts/plan-apply.mjs +987 -0
- package/scripts/preflight.mjs +51 -0
- package/scripts/reconcile.mjs +549 -0
- package/scripts/render-templates.mjs +338 -68
- package/scripts/schema-validate.mjs +132 -0
- package/scripts/section-compat.mjs +300 -0
- package/scripts/section-config.mjs +253 -0
- package/scripts/section-operations.mjs +508 -0
- package/scripts/starter.mjs +17 -0
- package/scripts/sync-assets.mjs +22 -15
- package/scripts/theme/color.mjs +185 -0
- package/scripts/theme/css-theme.mjs +233 -0
- package/scripts/theme/fonts.mjs +123 -0
- package/scripts/theme/import-export.mjs +125 -0
- package/scripts/theme/preset.mjs +93 -0
- package/scripts/theme/theme-plan.mjs +292 -0
- package/scripts/theme/tokens.mjs +137 -0
- package/scripts/view-assembly.mjs +337 -0
- package/scripts/view-selection.mjs +211 -0
- package/skills/sf-feature/SKILL.md +80 -0
- package/skills/sf-setup/SKILL.md +79 -0
- package/skills/sf-theme-gen/SKILL.md +100 -30
- package/skills/sf-theme-gen/references/shadcn-theming.md +87 -0
- package/skills/{shadcn-theming/references/templates → sf-theme-gen/references}/theme-setup.md +15 -19
- package/skills/{shadcn-theming → sf-theme-gen}/references/theming-guide.md +6 -11
- package/skills/sf-view-gen/SKILL.md +146 -93
- package/skills/sf-view-gen/assets/recipes/archetypes.json +28 -14
- package/skills/sf-view-gen/assets/recipes/catalog.json +400 -0
- package/skills/sf-view-gen/assets/recipes/catalog.schema.json +64 -0
- package/skills/sf-view-gen/assets/recipes/features.json +162 -0
- package/skills/sf-view-gen/assets/recipes/recipes.json +76 -19
- package/skills/sf-view-gen/assets/recipes/sections.json +34 -5
- package/skills/sf-view-gen/assets/templates/views/sections/cta.client.tsx +25 -0
- package/skills/sf-view-gen/assets/templates/views/sections/cta.tsx +16 -0
- package/skills/sf-view-gen/assets/templates/views/sections/faq.client.tsx +13 -9
- package/skills/sf-view-gen/assets/templates/views/sections/faq.tsx +2 -7
- package/skills/sf-view-gen/assets/templates/views/sections/logoCloud.client.tsx +12 -8
- package/skills/sf-view-gen/assets/templates/views/sections/logoCloud.tsx +2 -7
- package/skills/sf-view-gen/assets/templates/views/sections/pricing.client.tsx +14 -10
- package/skills/sf-view-gen/assets/templates/views/sections/pricing.tsx +2 -9
- package/skills/sf-view-gen/assets/templates/views/sections/products.client.tsx +100 -0
- package/skills/sf-view-gen/assets/templates/views/sections/products.tsx +19 -0
- package/skills/sf-view-gen/assets/templates/views/sections/schema.cta.ts +19 -0
- package/skills/sf-view-gen/assets/templates/views/sections/schema.faq.ts +18 -0
- package/skills/sf-view-gen/assets/templates/views/sections/schema.logoCloud.ts +19 -0
- package/skills/sf-view-gen/assets/templates/views/sections/schema.pricing.ts +26 -0
- package/skills/sf-view-gen/assets/templates/views/sections/schema.products.ts +39 -0
- package/skills/sf-view-gen/assets/templates/views/sections/schema.statistics.ts +25 -0
- package/skills/sf-view-gen/assets/templates/views/sections/schema.testimonials.ts +23 -0
- package/skills/sf-view-gen/assets/templates/views/sections/statistics.client.tsx +16 -8
- package/skills/sf-view-gen/assets/templates/views/sections/statistics.tsx +2 -7
- package/skills/sf-view-gen/assets/templates/views/sections/testimonials.client.tsx +13 -9
- package/skills/sf-view-gen/assets/templates/views/sections/testimonials.tsx +2 -5
- package/skills/{json-render-core/SKILL.md → sf-view-gen/references/json-render-core.md} +4 -27
- package/skills/{json-render-next/SKILL.md → sf-view-gen/references/json-render-next.md} +5 -8
- package/skills/{json-render-react/SKILL.md → sf-view-gen/references/json-render-react.md} +3 -5
- package/skills/{json-render-shadcn/SKILL.md → sf-view-gen/references/json-render-shadcn.md} +3 -5
- package/skills/sf-view-gen/references/views.md +58 -33
- package/skills/sf-view-gen/scripts/catalog.mjs +128 -0
- package/skills/sf-view-gen/scripts/schema-validate.mjs +132 -0
- package/skills/sf-view-gen/scripts/validate.mjs +838 -32
- package/skills/storefront-workflow/SKILL.md +179 -0
- package/skills/{storefront-best-practices/reference/design.md → storefront-workflow/references/design-consistency.md} +13 -29
- package/CHANGELOG.md +0 -61
- package/commands/sf-add-view.md +0 -26
- package/commands/sf-theme.md +0 -20
- package/commands/sf-view.md +0 -25
- package/skills/building-storefronts/SKILL.md +0 -178
- package/skills/building-storefronts/references/frontend-integration.md +0 -229
- package/skills/json-render-remotion/SKILL.md +0 -111
- package/skills/json-render-solid/SKILL.md +0 -204
- package/skills/nextjs-shadcn/SKILL.md +0 -367
- package/skills/nextjs-shadcn/references/architecture.md +0 -499
- package/skills/nextjs-shadcn/references/project-setup.md +0 -162
- package/skills/nextjs-shadcn/references/shadcn-platform.md +0 -261
- package/skills/nextjs-shadcn/references/sidebar.md +0 -274
- package/skills/nextjs-shadcn/references/styling.md +0 -555
- package/skills/sf-view-gen/assets/templates/views/category/index.tsx +0 -86
- package/skills/sf-view-gen/assets/templates/views/category/registry.tsx +0 -48
- package/skills/sf-view-gen/assets/templates/views/checkout/index.tsx +0 -192
- package/skills/sf-view-gen/assets/templates/views/checkout/registry.tsx +0 -45
- package/skills/sf-view-gen/assets/templates/views/product/index.tsx +0 -122
- package/skills/sf-view-gen/assets/templates/views/product/registry.tsx +0 -49
- package/skills/sf-view-gen/assets/templates/views/user-panel/index.tsx +0 -168
- package/skills/sf-view-gen/assets/templates/views/user-panel/registry.tsx +0 -49
- package/skills/shadcn-component-discovery/SKILL.md +0 -273
- package/skills/shadcn-component-discovery/references/registries.md +0 -226
- package/skills/shadcn-theming/SKILL.md +0 -104
- package/skills/storefront-best-practices/SKILL.md +0 -421
- package/skills/storefront-best-practices/reference/components/breadcrumbs.md +0 -123
- package/skills/storefront-best-practices/reference/components/cart-popup.md +0 -189
- package/skills/storefront-best-practices/reference/components/country-selector.md +0 -298
- package/skills/storefront-best-practices/reference/components/footer.md +0 -112
- package/skills/storefront-best-practices/reference/components/hero.md +0 -241
- package/skills/storefront-best-practices/reference/components/megamenu.md +0 -239
- package/skills/storefront-best-practices/reference/components/navbar.md +0 -397
- package/skills/storefront-best-practices/reference/components/popups.md +0 -221
- package/skills/storefront-best-practices/reference/components/product-card.md +0 -125
- package/skills/storefront-best-practices/reference/components/product-reviews.md +0 -217
- package/skills/storefront-best-practices/reference/components/product-slider.md +0 -174
- package/skills/storefront-best-practices/reference/components/search.md +0 -101
- package/skills/storefront-best-practices/reference/connecting-to-backend.md +0 -391
- package/skills/storefront-best-practices/reference/features/promotions.md +0 -307
- package/skills/storefront-best-practices/reference/features/wishlist.md +0 -230
- package/skills/storefront-best-practices/reference/layouts/account.md +0 -380
- package/skills/storefront-best-practices/reference/layouts/cart.md +0 -316
- package/skills/storefront-best-practices/reference/layouts/checkout.md +0 -486
- package/skills/storefront-best-practices/reference/layouts/home-page.md +0 -264
- package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +0 -231
- package/skills/storefront-best-practices/reference/layouts/product-details.md +0 -527
- package/skills/storefront-best-practices/reference/layouts/product-listing.md +0 -520
- package/skills/storefront-best-practices/reference/layouts/static-pages.md +0 -356
- package/skills/storefront-best-practices/reference/medusa.md +0 -307
- /package/skills/{storefront-best-practices/reference → storefront-workflow/references}/mobile-responsiveness.md +0 -0
- /package/skills/{storefront-best-practices/reference → storefront-workflow/references}/seo.md +0 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./catalog.schema.json",
|
|
3
|
+
"catalogVersion": 1,
|
|
4
|
+
"description": "Initial semantic executable catalog (E1 tasks 1.2-1.3), classified by source-shape inspection of the @thorprovider/blocks prop contracts and the view templates. Scope: every slot the curated MVP views (home, product, category, checkout, account) render by default, covering both the selectable archetype slots declared by recipes/archetypes.json and the nested default slots that have no archetype (category.productCard, checkout.confirmation) so no legacy default support is dropped. The account view (change: storefront-customer-auth) declares the login/register slots: LoginPage1/SignUpPage1 are executable while LoginPage2 is held for its divergent callback contract. A variant is `executable` only when the slot's canonical data shape can feed its block props without a prop bridge and without inventing data; every other non-default variant is `held` with the specific reason. The one executable non-default swap is home.benefits Feature1 -> Feature2 (identical item contract, no bridge). E2 task 6.1 declares the base listing slot category.filter CategoryFilter2 as the single controlled listing (dataShape `CatalogQuery & CatalogResults`, state controlled) with the search/filter controls contributed by the logical mounts category.search / category.filters (no second block). Source-shape compatibility is not end-to-end backend behavior proof: the render is executable, but the category.search.apply / category.filter.apply actions remain held under the capability catalog (owner: storefront-catalog-search-filters, E2) until a real runtime proof. The `capabilities` map declares those operational capabilities with their requirements and verification state; E1 declares the held category.filter.apply action, E2 adds the held category.search.apply action and the held category.price.range capability that gates the category-filters showPrice option; no capability is claimed verified.",
|
|
5
|
+
"slots": {
|
|
6
|
+
"home.hero": {
|
|
7
|
+
"default": "StorefrontHero1",
|
|
8
|
+
"variants": {
|
|
9
|
+
"StorefrontHero1": {
|
|
10
|
+
"status": "executable",
|
|
11
|
+
"block": "StorefrontHero",
|
|
12
|
+
"dataShape": "FeaturedProduct[]",
|
|
13
|
+
"events": ["addToCart", "buyNow", "selectColor"],
|
|
14
|
+
"state": "uncontrolled",
|
|
15
|
+
"requirements": ["heroProducts"]
|
|
16
|
+
},
|
|
17
|
+
"StorefrontHero2": {
|
|
18
|
+
"status": "held",
|
|
19
|
+
"reason": "block requires a product with reviews/trending/tag and emits a search event; the canonical FeaturedProduct shape carries rating/reviewCount but not trending/tag, and no verified prop bridge exists",
|
|
20
|
+
"block": "StorefrontHero",
|
|
21
|
+
"dataShape": "StorefrontHero2FeaturedProduct[]",
|
|
22
|
+
"events": ["search", "productClick"],
|
|
23
|
+
"state": "uncontrolled",
|
|
24
|
+
"requirements": ["heroProducts"]
|
|
25
|
+
},
|
|
26
|
+
"StorefrontHero5": {
|
|
27
|
+
"status": "held",
|
|
28
|
+
"reason": "featuredDeals[].description is absent from the canonical product shape and Department.count would require inventing counts; no truthful prop bridge can be derived from source",
|
|
29
|
+
"block": "StorefrontHero",
|
|
30
|
+
"dataShape": "FeaturedDeal[] & Department[]",
|
|
31
|
+
"events": ["departmentClick", "shopNow", "locateStores"],
|
|
32
|
+
"state": "uncontrolled",
|
|
33
|
+
"requirements": ["featuredDeals", "departments"]
|
|
34
|
+
},
|
|
35
|
+
"StorefrontHero6": {
|
|
36
|
+
"status": "held",
|
|
37
|
+
"reason": "block requires deals with discount/endTime and categories with a required count; the canonical shape supplies neither without invention and no verified prop bridge exists",
|
|
38
|
+
"block": "StorefrontHero",
|
|
39
|
+
"dataShape": "HeroDeal[] & HeroCategory[]",
|
|
40
|
+
"events": ["shopNow", "categoryClick"],
|
|
41
|
+
"state": "uncontrolled",
|
|
42
|
+
"requirements": ["deals", "categories"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"home.benefits": {
|
|
47
|
+
"default": "Feature1",
|
|
48
|
+
"variants": {
|
|
49
|
+
"Feature1": {
|
|
50
|
+
"status": "executable",
|
|
51
|
+
"block": "Feature",
|
|
52
|
+
"dataShape": "BenefitsItem[]",
|
|
53
|
+
"events": ["ctaClick", "learnMore"],
|
|
54
|
+
"state": "uncontrolled",
|
|
55
|
+
"requirements": []
|
|
56
|
+
},
|
|
57
|
+
"Feature2": {
|
|
58
|
+
"status": "executable",
|
|
59
|
+
"block": "Feature",
|
|
60
|
+
"dataShape": "BenefitsItem[]",
|
|
61
|
+
"events": [],
|
|
62
|
+
"state": "uncontrolled",
|
|
63
|
+
"requirements": []
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"home.categories": {
|
|
68
|
+
"default": "ProductCategory2",
|
|
69
|
+
"variants": {
|
|
70
|
+
"ProductCategory2": {
|
|
71
|
+
"status": "executable",
|
|
72
|
+
"block": "CategoryCards",
|
|
73
|
+
"dataShape": "CategoryCard[]",
|
|
74
|
+
"events": ["browse"],
|
|
75
|
+
"state": "uncontrolled",
|
|
76
|
+
"requirements": ["categories"]
|
|
77
|
+
},
|
|
78
|
+
"ProductCategory1": {
|
|
79
|
+
"status": "held",
|
|
80
|
+
"reason": "block requires categories with a subtitle and a named icon, which the canonical CategoryCard shape does not supply; no verified prop bridge exists",
|
|
81
|
+
"block": "CategoryCards",
|
|
82
|
+
"dataShape": "ProductCategory1Category[]",
|
|
83
|
+
"events": [],
|
|
84
|
+
"state": "uncontrolled",
|
|
85
|
+
"requirements": ["categories"]
|
|
86
|
+
},
|
|
87
|
+
"ProductCategory4": {
|
|
88
|
+
"status": "held",
|
|
89
|
+
"reason": "block requires categories with title/icon/customers/products/avatarImages, which the canonical CategoryCard shape does not supply; no verified prop bridge exists",
|
|
90
|
+
"block": "CategoryCards",
|
|
91
|
+
"dataShape": "ProductCategory4Category[]",
|
|
92
|
+
"events": ["categoryClick"],
|
|
93
|
+
"state": "uncontrolled",
|
|
94
|
+
"requirements": ["categories"]
|
|
95
|
+
},
|
|
96
|
+
"ProductCategory5": {
|
|
97
|
+
"status": "held",
|
|
98
|
+
"reason": "block requires categories with subcategories and a required itemCount plus a search control, which the canonical CategoryCard shape does not supply; no verified prop bridge exists",
|
|
99
|
+
"block": "CategoryCards",
|
|
100
|
+
"dataShape": "ProductCategory5Category[]",
|
|
101
|
+
"events": ["browse", "viewAll"],
|
|
102
|
+
"state": "uncontrolled",
|
|
103
|
+
"requirements": ["categories"]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"product.overview": {
|
|
108
|
+
"default": "ProductOverview1",
|
|
109
|
+
"variants": {
|
|
110
|
+
"ProductOverview1": {
|
|
111
|
+
"status": "executable",
|
|
112
|
+
"block": "ProductOverview",
|
|
113
|
+
"dataShape": "ProductDetailProduct",
|
|
114
|
+
"events": ["selectVariant", "quantityChange", "addToCart", "toggleWishlist"],
|
|
115
|
+
"state": "controlled",
|
|
116
|
+
"requirements": ["selectedProduct", "selectedVariantId"]
|
|
117
|
+
},
|
|
118
|
+
"ProductOverview2": {
|
|
119
|
+
"status": "held",
|
|
120
|
+
"reason": "block requires a product with brand/sku/sizes/colors and wishlist events, a shape the canonical ProductDetailProduct does not supply; no verified prop bridge exists",
|
|
121
|
+
"block": "ProductOverview",
|
|
122
|
+
"dataShape": "ProductOverview2Product",
|
|
123
|
+
"events": ["addToCart", "toggleWishlist"],
|
|
124
|
+
"state": "uncontrolled",
|
|
125
|
+
"requirements": ["selectedProduct"]
|
|
126
|
+
},
|
|
127
|
+
"ProductOverview5": {
|
|
128
|
+
"status": "held",
|
|
129
|
+
"reason": "block requires specifications/features/mainImages/galleryImages/userReviews, a shape the canonical ProductDetailProduct does not supply; no verified prop bridge exists",
|
|
130
|
+
"block": "ProductOverview",
|
|
131
|
+
"dataShape": "ProductOverview5Product",
|
|
132
|
+
"events": ["addToCart", "toggleWishlist"],
|
|
133
|
+
"state": "uncontrolled",
|
|
134
|
+
"requirements": ["selectedProduct"]
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"product.reviews": {
|
|
139
|
+
"default": "ReviewRating1",
|
|
140
|
+
"variants": {
|
|
141
|
+
"ReviewRating1": {
|
|
142
|
+
"status": "executable",
|
|
143
|
+
"block": "Reviews",
|
|
144
|
+
"dataShape": "Review[]",
|
|
145
|
+
"events": ["toggleReviewLike", "submitReview"],
|
|
146
|
+
"state": "uncontrolled",
|
|
147
|
+
"requirements": ["productReviews"]
|
|
148
|
+
},
|
|
149
|
+
"ReviewRating2": {
|
|
150
|
+
"status": "held",
|
|
151
|
+
"reason": "block requires an aggregate averageRating/ratingDistribution and carousel controls the canonical Review[] shape does not supply; no verified prop bridge exists",
|
|
152
|
+
"block": "Reviews",
|
|
153
|
+
"dataShape": "Review[] & RatingSummary",
|
|
154
|
+
"events": ["like", "comment"],
|
|
155
|
+
"state": "uncontrolled",
|
|
156
|
+
"requirements": ["productReviews"]
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"product.breadcrumb": {
|
|
161
|
+
"default": "Breadcrumb",
|
|
162
|
+
"variants": {
|
|
163
|
+
"Breadcrumb": {
|
|
164
|
+
"status": "executable",
|
|
165
|
+
"block": "Breadcrumb",
|
|
166
|
+
"dataShape": "BreadcrumbItemData[]",
|
|
167
|
+
"events": [],
|
|
168
|
+
"state": "uncontrolled",
|
|
169
|
+
"requirements": ["productBreadcrumb"]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"cart.view": {
|
|
174
|
+
"default": "ShoppingCart4",
|
|
175
|
+
"variants": {
|
|
176
|
+
"ShoppingCart4": {
|
|
177
|
+
"status": "executable",
|
|
178
|
+
"block": "ShoppingCart4",
|
|
179
|
+
"dataShape": "CartLineState[] & CartTotalsState",
|
|
180
|
+
"events": ["refreshCart", "updateQuantity", "removeFromCart", "checkout", "continueShopping"],
|
|
181
|
+
"state": "controlled",
|
|
182
|
+
"requirements": ["cart", "cartTotals"]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"category.filter": {
|
|
187
|
+
"default": "CategoryFilter2",
|
|
188
|
+
"variants": {
|
|
189
|
+
"CategoryFilter2": {
|
|
190
|
+
"status": "executable",
|
|
191
|
+
"block": "CategoryFilter",
|
|
192
|
+
"dataShape": "CatalogQuery & CatalogResults",
|
|
193
|
+
"events": [
|
|
194
|
+
"productClick",
|
|
195
|
+
"pageChange",
|
|
196
|
+
"pageSizeChange",
|
|
197
|
+
"sortChange",
|
|
198
|
+
"filterChange",
|
|
199
|
+
"searchChange",
|
|
200
|
+
"clearFilters",
|
|
201
|
+
"repair",
|
|
202
|
+
"retry",
|
|
203
|
+
"removeFilter"
|
|
204
|
+
],
|
|
205
|
+
"state": "controlled",
|
|
206
|
+
"requirements": ["categoryProducts", "categoryQuery", "facetSupport"]
|
|
207
|
+
},
|
|
208
|
+
"CategoryFilter1": {
|
|
209
|
+
"status": "held",
|
|
210
|
+
"reason": "block requires categories/priceRanges/sortOptions with counts the canonical CardProduct[] listing does not supply; no verified prop bridge exists",
|
|
211
|
+
"block": "CategoryFilter",
|
|
212
|
+
"dataShape": "CategoryFilter1Filters",
|
|
213
|
+
"events": ["filterChange"],
|
|
214
|
+
"state": "uncontrolled",
|
|
215
|
+
"requirements": ["categoryProducts"]
|
|
216
|
+
},
|
|
217
|
+
"CategoryFilter4": {
|
|
218
|
+
"status": "held",
|
|
219
|
+
"reason": "block requires an advanced facets contract (modelTypes/rangeBands/frameSizes/colourways/features) the canonical listing does not supply; no verified prop bridge exists",
|
|
220
|
+
"block": "CategoryFilter",
|
|
221
|
+
"dataShape": "CategoryFilter4Facets",
|
|
222
|
+
"events": ["filterChange"],
|
|
223
|
+
"state": "uncontrolled",
|
|
224
|
+
"requirements": ["categoryProducts"]
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
"category.productCard": {
|
|
229
|
+
"default": "ProductCard1",
|
|
230
|
+
"variants": {
|
|
231
|
+
"ProductCard1": {
|
|
232
|
+
"status": "executable",
|
|
233
|
+
"block": "ProductCard",
|
|
234
|
+
"dataShape": "CardProduct[]",
|
|
235
|
+
"events": ["addToCart", "openProduct"],
|
|
236
|
+
"state": "uncontrolled",
|
|
237
|
+
"requirements": ["categoryProducts"]
|
|
238
|
+
},
|
|
239
|
+
"ProductCard2": {
|
|
240
|
+
"status": "held",
|
|
241
|
+
"reason": "block requires a product with a required rating, a shape the canonical CardProduct listing does not supply; no verified prop bridge exists",
|
|
242
|
+
"block": "ProductCard",
|
|
243
|
+
"dataShape": "ProductCard2Product[]",
|
|
244
|
+
"events": [],
|
|
245
|
+
"state": "uncontrolled",
|
|
246
|
+
"requirements": ["categoryProducts"]
|
|
247
|
+
},
|
|
248
|
+
"ProductCard3": {
|
|
249
|
+
"status": "held",
|
|
250
|
+
"reason": "block requires a product with subtitle/originalPrice/reviewCount/discountPercentage and a badge, a shape the canonical CardProduct listing does not supply; no verified prop bridge exists",
|
|
251
|
+
"block": "ProductCard",
|
|
252
|
+
"dataShape": "ProductCard3Product[]",
|
|
253
|
+
"events": ["toggleWishlist", "viewSimilar", "productClick"],
|
|
254
|
+
"state": "controlled",
|
|
255
|
+
"requirements": ["categoryProducts"]
|
|
256
|
+
},
|
|
257
|
+
"ProductCard5": {
|
|
258
|
+
"status": "held",
|
|
259
|
+
"reason": "block requires a product with name/category/stock/specifications/brand, a shape the canonical CardProduct listing does not supply; no verified prop bridge exists",
|
|
260
|
+
"block": "ProductCard",
|
|
261
|
+
"dataShape": "ProductCard5Product[]",
|
|
262
|
+
"events": ["toggleWishlist", "addToCart", "quickView", "compare", "export"],
|
|
263
|
+
"state": "controlled",
|
|
264
|
+
"requirements": ["categoryProducts"]
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
"checkout.checkout": {
|
|
269
|
+
"default": "CheckoutForm1",
|
|
270
|
+
"variants": {
|
|
271
|
+
"CheckoutForm1": {
|
|
272
|
+
"status": "executable",
|
|
273
|
+
"block": "Checkout",
|
|
274
|
+
"dataShape": "CheckoutForm1FormData",
|
|
275
|
+
"events": ["retryTotals", "selectShippingOption", "applyPromo", "submit"],
|
|
276
|
+
"state": "controlled",
|
|
277
|
+
"requirements": ["checkoutCountries", "checkoutPaymentMethods"]
|
|
278
|
+
},
|
|
279
|
+
"CheckoutForm2": {
|
|
280
|
+
"status": "held",
|
|
281
|
+
"reason": "unproven checkout variant: E1 keeps only the default CheckoutForm1, whose behavior is unchanged; no verified prop bridge exists",
|
|
282
|
+
"block": "Checkout",
|
|
283
|
+
"dataShape": "CheckoutForm2Data",
|
|
284
|
+
"events": ["submit"],
|
|
285
|
+
"state": "controlled",
|
|
286
|
+
"requirements": ["checkoutCountries", "checkoutPaymentMethods"]
|
|
287
|
+
},
|
|
288
|
+
"CheckoutForm3": {
|
|
289
|
+
"status": "held",
|
|
290
|
+
"reason": "unproven checkout variant: E1 keeps only the default CheckoutForm1, whose behavior is unchanged; no verified prop bridge exists",
|
|
291
|
+
"block": "Checkout",
|
|
292
|
+
"dataShape": "CheckoutForm3FormData",
|
|
293
|
+
"events": ["submit"],
|
|
294
|
+
"state": "controlled",
|
|
295
|
+
"requirements": ["checkoutCountries", "checkoutPaymentMethods"]
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
"checkout.confirmation": {
|
|
300
|
+
"default": "CheckoutConfirmation",
|
|
301
|
+
"variants": {
|
|
302
|
+
"CheckoutConfirmation": {
|
|
303
|
+
"status": "executable",
|
|
304
|
+
"block": "CheckoutConfirmation",
|
|
305
|
+
"dataShape": "Receipt",
|
|
306
|
+
"events": ["continueShopping"],
|
|
307
|
+
"state": "uncontrolled",
|
|
308
|
+
"requirements": ["lastReceipt"]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
"account.login": {
|
|
313
|
+
"default": "LoginPage1",
|
|
314
|
+
"variants": {
|
|
315
|
+
"LoginPage1": {
|
|
316
|
+
"status": "executable",
|
|
317
|
+
"block": "LoginPage1",
|
|
318
|
+
"dataShape": "LoginPage1FormData & AccountAuthResult",
|
|
319
|
+
"events": ["submit", "createAccount"],
|
|
320
|
+
"state": "controlled",
|
|
321
|
+
"requirements": ["accountCustomer", "accountAuthenticated"]
|
|
322
|
+
},
|
|
323
|
+
"LoginPage2": {
|
|
324
|
+
"status": "held",
|
|
325
|
+
"reason": "block's onSubmit takes positional (email, password) with no remember-me field and renders a 2-column social grid; no verified prop bridge from the account element contract exists",
|
|
326
|
+
"block": "LoginPage2",
|
|
327
|
+
"dataShape": "LoginPage2Credentials & AccountAuthResult",
|
|
328
|
+
"events": ["submit", "forgotPassword", "signUp"],
|
|
329
|
+
"state": "controlled",
|
|
330
|
+
"requirements": ["accountCustomer", "accountAuthenticated"]
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
"account.register": {
|
|
335
|
+
"default": "SignUpPage1",
|
|
336
|
+
"variants": {
|
|
337
|
+
"SignUpPage1": {
|
|
338
|
+
"status": "executable",
|
|
339
|
+
"block": "SignUpPage1",
|
|
340
|
+
"dataShape": "SignUpPage1Data & AccountAuthResult",
|
|
341
|
+
"events": ["submit", "signIn"],
|
|
342
|
+
"state": "controlled",
|
|
343
|
+
"requirements": ["accountCustomer", "accountAuthenticated"]
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"account.orders": {
|
|
348
|
+
"default": "OrderHistory2",
|
|
349
|
+
"variants": {
|
|
350
|
+
"OrderHistory2": {
|
|
351
|
+
"status": "executable",
|
|
352
|
+
"block": "OrderHistory2",
|
|
353
|
+
"dataShape": "AccountOrderView[] & OrderHistory2Labels",
|
|
354
|
+
"events": ["viewDetails"],
|
|
355
|
+
"state": "controlled",
|
|
356
|
+
"requirements": ["accountCustomer", "accountAuthenticated"]
|
|
357
|
+
},
|
|
358
|
+
"OrderHistory1": {
|
|
359
|
+
"status": "held",
|
|
360
|
+
"reason": "block models one row per order item (an item-row list), the wrong shape for an order-level history; the canonical order list cannot feed it without inventing an aggregate row",
|
|
361
|
+
"block": "OrderHistory1",
|
|
362
|
+
"dataShape": "OrderHistory1Order[]",
|
|
363
|
+
"events": [],
|
|
364
|
+
"state": "controlled",
|
|
365
|
+
"requirements": ["accountCustomer", "accountAuthenticated"]
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
"category.breadcrumb": {
|
|
370
|
+
"default": "Breadcrumb",
|
|
371
|
+
"variants": {
|
|
372
|
+
"Breadcrumb": {
|
|
373
|
+
"status": "executable",
|
|
374
|
+
"block": "Breadcrumb",
|
|
375
|
+
"dataShape": "BreadcrumbItemData[]",
|
|
376
|
+
"events": [],
|
|
377
|
+
"state": "uncontrolled",
|
|
378
|
+
"requirements": ["categoryBreadcrumb"]
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
"capabilities": {
|
|
384
|
+
"category.search.apply": {
|
|
385
|
+
"requirements": ["adapter.getCatalogProducts(query).text"],
|
|
386
|
+
"verification": "unverified",
|
|
387
|
+
"owner": "storefront-catalog-search-filters"
|
|
388
|
+
},
|
|
389
|
+
"category.filter.apply": {
|
|
390
|
+
"requirements": ["adapter.getProducts(query)"],
|
|
391
|
+
"verification": "unverified",
|
|
392
|
+
"owner": "storefront-catalog-search-filters"
|
|
393
|
+
},
|
|
394
|
+
"category.price.range": {
|
|
395
|
+
"requirements": ["adapter.getAvailableFilters(query).priceRange"],
|
|
396
|
+
"verification": "unverified",
|
|
397
|
+
"owner": "storefront-catalog-search-filters"
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://thorcommerce.dev/storefront/catalog.schema.json",
|
|
4
|
+
"title": "Thor Commerce Storefront Semantic Catalog",
|
|
5
|
+
"description": "The semantic executable catalog: per view slot and candidate variant, its execution status (executable | held), the block it renders, its canonical data shape, emitted events, controlled/uncontrolled state, requirements, and an optional prop bridge. Held entries carry a reason. Also declares operational capabilities with their backend/data requirements and a verification state (verified | unverified); an unverified capability names its owning change in `owner`. Versioned by catalogVersion.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["catalogVersion", "slots"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": { "type": "string" },
|
|
11
|
+
"catalogVersion": { "type": "number", "enum": [1] },
|
|
12
|
+
"description": { "type": "string" },
|
|
13
|
+
"slots": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"additionalProperties": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"required": ["default", "variants"],
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"properties": {
|
|
20
|
+
"default": { "type": "string", "minLength": 1 },
|
|
21
|
+
"variants": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"additionalProperties": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"required": ["status", "block", "dataShape", "events", "state", "requirements"],
|
|
26
|
+
"additionalProperties": false,
|
|
27
|
+
"properties": {
|
|
28
|
+
"status": { "type": "string", "enum": ["executable", "held"] },
|
|
29
|
+
"reason": { "type": "string", "minLength": 1 },
|
|
30
|
+
"block": { "type": "string", "minLength": 1 },
|
|
31
|
+
"dataShape": { "type": "string", "minLength": 1 },
|
|
32
|
+
"events": { "type": "array", "items": { "type": "string" } },
|
|
33
|
+
"state": { "type": "string", "enum": ["controlled", "uncontrolled"] },
|
|
34
|
+
"requirements": { "type": "array", "items": { "type": "string" } },
|
|
35
|
+
"bridge": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"required": ["from", "to"],
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"properties": {
|
|
40
|
+
"from": { "type": "string", "minLength": 1 },
|
|
41
|
+
"to": { "type": "string", "minLength": 1 }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"capabilities": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"additionalProperties": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"required": ["requirements", "verification"],
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"properties": {
|
|
57
|
+
"requirements": { "type": "array", "items": { "type": "string" } },
|
|
58
|
+
"verification": { "type": "string", "enum": ["verified", "unverified"] },
|
|
59
|
+
"owner": { "type": "string", "minLength": 1 }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"features": [
|
|
4
|
+
{
|
|
5
|
+
"name": "checkout",
|
|
6
|
+
"mvp": true,
|
|
7
|
+
"description": "Multi-step checkout: cart validation, shipping, payment, and order placement.",
|
|
8
|
+
"route": "/checkout",
|
|
9
|
+
"views": ["checkout"],
|
|
10
|
+
"state": [
|
|
11
|
+
"checkout",
|
|
12
|
+
"checkoutCountries",
|
|
13
|
+
"checkoutPaymentMethods",
|
|
14
|
+
"checkoutPending",
|
|
15
|
+
"checkoutError",
|
|
16
|
+
"lastOrder",
|
|
17
|
+
"lastOrderLines",
|
|
18
|
+
"orderPlaced"
|
|
19
|
+
],
|
|
20
|
+
"handlers": ["placeOrder", "goToCheckout", "continueShopping"],
|
|
21
|
+
"adapter": { "needs": ["createCart", "completeCheckout"] },
|
|
22
|
+
"config": { "type": "object", "additionalProperties": false, "properties": {} },
|
|
23
|
+
"configRejection": {
|
|
24
|
+
"code": "E_UNPROVEN_CHECKOUT_OPTION",
|
|
25
|
+
"message": "checkout variants and route options are not proven; the checkout feature accepts an empty config only"
|
|
26
|
+
},
|
|
27
|
+
"surfaces": []
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "customer-auth",
|
|
31
|
+
"mvp": true,
|
|
32
|
+
"description": "Customer authentication: registration, login, logout, and a minimal signed-in state. Owns the account view.",
|
|
33
|
+
"route": "/account",
|
|
34
|
+
"views": ["account"],
|
|
35
|
+
"state": [
|
|
36
|
+
"accountCustomer",
|
|
37
|
+
"accountAuthenticated",
|
|
38
|
+
"accountMode",
|
|
39
|
+
"accountPending",
|
|
40
|
+
"accountError"
|
|
41
|
+
],
|
|
42
|
+
"handlers": ["logout", "showRegister", "showLogin"],
|
|
43
|
+
"adapter": { "needs": [] },
|
|
44
|
+
"config": { "type": "object", "additionalProperties": false, "properties": {} },
|
|
45
|
+
"surfaces": []
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "static-pages",
|
|
49
|
+
"mvp": true,
|
|
50
|
+
"description": "Content-driven static pages (contact, legal, about) served with per-page metadata. Owns the static view.",
|
|
51
|
+
"route": "/contact",
|
|
52
|
+
"views": ["static"],
|
|
53
|
+
"state": [],
|
|
54
|
+
"handlers": [],
|
|
55
|
+
"adapter": { "needs": [] },
|
|
56
|
+
"config": { "type": "object", "additionalProperties": false, "properties": {} },
|
|
57
|
+
"surfaces": []
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "benefits",
|
|
61
|
+
"mvp": true,
|
|
62
|
+
"description": "Bounded editorial benefits feature that mounts at the home benefits slot; config selects the Feature1/Feature2 presentation while the item content stays user-owned.",
|
|
63
|
+
"views": [],
|
|
64
|
+
"state": [],
|
|
65
|
+
"handlers": [],
|
|
66
|
+
"adapter": { "needs": [] },
|
|
67
|
+
"config": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"additionalProperties": false,
|
|
70
|
+
"properties": {
|
|
71
|
+
"presentation": { "type": "string", "enum": ["compact", "detailed"], "default": "compact" }
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"presentations": { "compact": "Feature1", "detailed": "Feature2" },
|
|
75
|
+
"mounts": [{ "id": "home-benefits", "host": "home", "slot": "benefits" }],
|
|
76
|
+
"surfaces": []
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "catalog-search",
|
|
80
|
+
"mvp": true,
|
|
81
|
+
"description": "Optional category-listing search control (E2). Installation is presence, not an enabled flag; the config only supplies an optional placeholder. The search input contributes to the single controlled CategoryFilter2 at the category.search logical slot and never adds a block.",
|
|
82
|
+
"views": [],
|
|
83
|
+
"state": [],
|
|
84
|
+
"handlers": [],
|
|
85
|
+
"adapter": { "needs": [] },
|
|
86
|
+
"config": {
|
|
87
|
+
"type": "object",
|
|
88
|
+
"additionalProperties": false,
|
|
89
|
+
"properties": {
|
|
90
|
+
"placeholder": { "type": "string" }
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"mounts": [{ "id": "category-search", "host": "category", "slot": "search" }],
|
|
94
|
+
"surfaces": []
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"name": "category-filters",
|
|
98
|
+
"mvp": true,
|
|
99
|
+
"description": "Optional category-listing filter controls (E2). Installation is presence, not an enabled flag; the config selects which demonstrated basic filters show (filterSet) and whether the price control is shown (showPrice). The controls contribute to the single controlled CategoryFilter2 at the category.filters logical slot and never add a block.",
|
|
100
|
+
"views": [],
|
|
101
|
+
"state": [],
|
|
102
|
+
"handlers": [],
|
|
103
|
+
"adapter": { "needs": [] },
|
|
104
|
+
"config": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"additionalProperties": false,
|
|
107
|
+
"properties": {
|
|
108
|
+
"filterSet": {
|
|
109
|
+
"type": "array",
|
|
110
|
+
"items": { "type": "string", "enum": ["categories", "collections"] },
|
|
111
|
+
"default": ["categories", "collections"]
|
|
112
|
+
},
|
|
113
|
+
"showPrice": { "type": "boolean", "default": false }
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"configRejection": {
|
|
117
|
+
"code": "E_UNVERIFIED_PRICE_RANGE",
|
|
118
|
+
"message": "showPrice: true requires a verified price range for the listing scope; capability \"category.price.range\" is unverified (held), so configure showPrice: false until a real range is demonstrated",
|
|
119
|
+
"when": { "field": "showPrice", "equals": true },
|
|
120
|
+
"capability": "category.price.range"
|
|
121
|
+
},
|
|
122
|
+
"mounts": [{ "id": "category-filters", "host": "category", "slot": "filters" }],
|
|
123
|
+
"surfaces": []
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "navigability",
|
|
127
|
+
"mvp": true,
|
|
128
|
+
"description": "Cross-cutting navigability feature: entity-derived breadcrumbs with BreadcrumbList structured data on the product and category surfaces, plus skip-to-content, current-page indication, back-to-top, and a mobile bottom navigation in the shared shell.",
|
|
129
|
+
"views": [],
|
|
130
|
+
"state": [],
|
|
131
|
+
"handlers": [],
|
|
132
|
+
"adapter": { "needs": [] },
|
|
133
|
+
"config": {
|
|
134
|
+
"type": "object",
|
|
135
|
+
"additionalProperties": false,
|
|
136
|
+
"properties": {
|
|
137
|
+
"presentation": { "type": "string", "enum": ["default"], "default": "default" },
|
|
138
|
+
"showBackToTop": { "type": "boolean", "default": true }
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"presentations": { "default": "Breadcrumb" },
|
|
142
|
+
"mounts": [
|
|
143
|
+
{ "id": "category-breadcrumb", "host": "category", "slot": "breadcrumb" },
|
|
144
|
+
{ "id": "product-breadcrumb", "host": "product", "slot": "breadcrumb" }
|
|
145
|
+
],
|
|
146
|
+
"surfaces": []
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "recommendations",
|
|
150
|
+
"mvp": false,
|
|
151
|
+
"description": "Related-products surface injected into the product view.",
|
|
152
|
+
"views": [],
|
|
153
|
+
"state": ["recommendedProducts"],
|
|
154
|
+
"handlers": [],
|
|
155
|
+
"adapter": { "needs": ["getRelatedProducts"], "fallback": "catalog" },
|
|
156
|
+
"config": { "type": "object", "additionalProperties": false, "properties": {} },
|
|
157
|
+
"surfaces": [
|
|
158
|
+
{ "host": "product", "slot": "product.related", "element": "ProductCard" }
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|