SSK-101 - Missing <storesynk-store> wrapper
Section titled “SSK-101 - Missing <storesynk-store> wrapper”- Severity: Error
- Applies to: any storesynk tag on the page. A few tags need a
storesynk-storeon the page but not as an ancestor -open-cart,search-input, and the customer verbslog-in/log-out(they drive the store’s single module-level session and consume no context). - Detect: a storesynk tag with no
storesynk-storeancestor anywhere above it (or, for the page-scoped tags above, nostoresynk-storeanywhere on the page). - Why it breaks: with no
storeContextthere is no storefront client and no cart, so nothing fetches and nothing renders - silently. - Known symptoms: the whole storefront region is blank; no network requests fire.
- Fix: wrap the tree in
<storesynk-store domain="…" token="…">.
SSK-102 - Product component outside <storesynk-product>
Section titled “SSK-102 - Product component outside <storesynk-product>”- Severity: Error
- Applies to: the product displayers,
change-option,change-selling-plan,change-purchase-option,change-quantity,input-quantity,add-to-cart,buy-now,product-link,show-sale-badge,klaviyo-back-in-stock, the option displayersshow-option-label/show-active-option-title, the metafield displayersshow-metafield/metafield-wrapper, the media tags,storesynk-bundle(it reads the current product’s id to query its bundles),storesynk-volume-discount(it reads the product’s id to query its volume discounts),storesynk-customer-pricing(it reads the product’s id to find the customer-pricing rule targeting it),storesynk-addons(it reads the product’s id to query the add-ons offers targeting it), andstoresynk-mix-match- with one exemption: astoresynk-mix-matchthat carries ahandle="…"looks its bundle up directly as a metaobject (a standalone build-your-own-box page with no host product) and is never flagged. - Detect: any product-context tag with no
storesynk-productancestor; forstoresynk-mix-match, only when it also has nohandleattribute. - Why it breaks: it consumes
productContext, which has no provider, so it renders nothing. - Known symptoms: a blank price/title/button where content was expected, while the rest of the page renders.
- Fix: move the tag inside a
<storesynk-product>- or, for a standalone mix & match builder page, give the widgethandle="…". Special case: achange-purchase-option/change-selling-planauthored inside a<cart-line>is the wrong tag for that surface - the finding’s fix names the cart counterpart (change-line-purchase-option/change-line-selling-plan), which reads the LINE instead of a product.
SSK-103 - Nested <storesynk-product>
Section titled “SSK-103 - Nested <storesynk-product>”- Severity: Error
- Detect: a
storesynk-productthat has astoresynk-productancestor - unless it also has abundle-member-list, amix-match-item-list, or anaddon-listancestor. Those are the three sanctioned nestings: a bundle member card, a mix & match pool card, and a product-addons row card are each astoresynk-productinside the page’s product by design (fed viaprovideProduct()), so they are never flagged. - Why it breaks: the inner product overrides the outer context; bindings become ambiguous and doubled.
- Known symptoms: duplicate renders, wrong product data.
- Fix: do not nest. List and search item templates hold exactly one product; the only
sanctioned nestings are the member-card template inside
<bundle-member-list>, the pool-card template inside<mix-match-item-list>, and the row-card template inside<addon-list>.
SSK-104 - Nested <storesynk-store>
Section titled “SSK-104 - Nested <storesynk-store>”- Severity: Error
- Detect: a
storesynk-storethat has astoresynk-storeancestor. - Why it breaks: two cart runtimes and two store contexts collide.
- Known symptoms: cart actions hit the wrong runtime; inconsistent counts/totals.
- Fix: use one store per page/tree.
SSK-105 - Item-scoped part outside its context provider
Section titled “SSK-105 - Item-scoped part outside its context provider”-
Severity: Error
-
Applies to:
show-line-*,increase-line-quantity,decrease-line-quantity,remove-cart-line, and the in-cart subscription controlschange-line-purchase-option/change-line-selling-plan(needcart-line);show-discount-amount(needscart-discount); the bundle-context tagsshow-bundle-title/show-bundle-total/show-bundle-original-total/show-bundle-savings/show-bundle-percentage/add-bundle-to-cart/bundle-member-list(needbundle-offer); the member-context displayersshow-member-quantity/show-member-subtotal(needbundle-member-list); the volume-discount-context tagsshow-volume-discount-title/volume-tier-list/add-volume-to-cart(needstoresynk-volume-discount); and the tier-context displayersshow-tier-title/show-tier-label/show-tier-badge/show-tier-price/show-tier-original-price/show-tier-each-price(needvolume-tier-list); the customer-pricing displayersshow-pricing-prompt/show-pricing-title/show-pricing-percentage/show-pricing-price/show-pricing-original-price/show-pricing-note(needstoresynk-customer-pricing); and the four mix & match context families:- offer context -
show-mix-match-title/show-mix-match-total/show-mix-match-original-total/show-mix-match-savings/show-mix-match-tier-hint/show-mix-match-free-shipping/add-mix-match-to-cart/mix-match-section-list/mix-match-selection-list(needmix-match-offer); - section context -
show-section-title/show-section-image/show-section-requirement/show-section-count/show-section-progress/toggle-section/mix-match-item-list(needmix-match-section, i.e. the section template); - item context -
add-mix-match-item/increase-mix-match-item/decrease-mix-match-item/remove-mix-match-item/show-item-quantity(needmix-match-item-list, i.e. the pool-card template); - pick context -
show-pick-image/show-pick-quantity/show-selection-overflow(needmix-match-selection-list);
and the two product-addons context families:
- offer context -
show-addons-title/show-addons-subtitle/addon-list(needstoresynk-addons); - row context -
select-addon/show-addon-price/show-addon-original-price(needaddon-list, i.e. the row-card template).
- offer context -
-
Detect: any of those tags with no
cart-lineancestor;show-discount-amountwith nocart-discountancestor; a bundle-context tag with nobundle-offerancestor; a member displayer with nobundle-member-listancestor; a volume-discount-context tag with nostoresynk-volume-discountancestor; a tier displayer with novolume-tier-listancestor; a pricing displayer with nostoresynk-customer-pricingancestor; a mix & match tag with nomix-match-offer/mix-match-section/mix-match-item-list/mix-match-selection-listancestor per the four families above; or a product-addons tag with nostoresynk-addons/addon-listancestor per its two families. -
Why it breaks: no item context (
cartLineContext/discountContext/bundleContext/ the per-clone member context /volumeDiscountContext/ the per-row tier context /customerPricingContext/mixMatchContextand its per-clone section / item / pick contexts /addonsContextand its per-clone row context), so it has nothing to read or act on. For the mix & match and product-addons families this is especially quiet: the per-clone contexts are attached to the clones, so a tag authored one level too high (e.g. ashow-section-countoutside<mix-match-section>, a stepper outside the pool card, or aselect-addonoutside the row card) is on the detached template forever and stays literally untouched. -
Known symptoms: blank line/bundle/member/tier/pricing/section/pick/add-on fields; quantity/remove controls, the in-cart subscribe toggle / frequency picker, the bundle/volume/mix-match add buttons, and the add-ons checkboxes do nothing.
-
Fix: place the tag inside its provider’s template -
<cart-line>,<cart-discount>,<bundle-offer>, the member card inside<bundle-member-list>,<storesynk-volume-discount>, the tier row inside<volume-tier-list>,<storesynk-customer-pricing>,<mix-match-offer>, the<mix-match-section>section template, the pool card inside<mix-match-item-list>,<mix-match-selection-list>,<storesynk-addons>, or the row card inside<addon-list>.
SSK-106 - Cloned item template outside its cloning container
Section titled “SSK-106 - Cloned item template outside its cloning container”- Severity: Error
- Detect: a
cart-linewith nocart-line-listancestor; acart-discountwith nocart-discount-list/cart-order-discount-listancestor; abundle-offerwith nostoresynk-bundleancestor; avolume-tierwith novolume-tier-listancestor; amix-match-offerwith nostoresynk-mix-matchancestor; or amix-match-sectionwith nomix-match-section-listancestor. - Why it breaks: only the container clones and populates the item (the discount lists via
provideDiscount(), the bundle widget viaprovideBundle(), the tier list per tier, the mix-match widget viaprovideLive(), the section list per section), so a straycart-line/cart-discount/bundle-offer/volume-tier/mix-match-offer/mix-match-sectionis never driven - and amix-match-sectionoutside its list also never receives thess-open/ss-metstamps the accordion CSS keys on. - Known symptoms: a single empty/static row, offer, or section; lines/discounts/bundles/ tiers/bundle sections never appear.
- Fix: nest the
cart-lineinside a<cart-line-list>, thecart-discountinside a<cart-discount-list>/<cart-order-discount-list>, thebundle-offerinside a<storesynk-bundle>, thevolume-tierinside a<volume-tier-list>, themix-match-offerinside a<storesynk-mix-match>, or themix-match-sectioninside a<mix-match-section-list>(as, or inside, its first-child template).
SSK-107 - Clone container missing its first-child template
Section titled “SSK-107 - Clone container missing its first-child template”- Severity: Error
- Applies to:
storesynk-list,search-result-list,cart-line-list,cart-discount-list,cart-order-discount-list,change-selling-plan,change-line-selling-plan,predictive-search,product-list,filter-list,change-filter,active-filter-list,storesynk-bundle,bundle-member-list,storesynk-volume-discount,volume-tier-list,storesynk-customer-pricing,storesynk-mix-match,mix-match-section-list,mix-match-item-list,mix-match-selection-list,storesynk-addons,addon-list. - Detect:
storesynk-list/search-result-list/product-listwhose first element child is not, and does not contain, astoresynk-product;cart-line-listwith nocart-line; a discount list with nocart-discount;change-selling-planorchange-line-selling-planwith noselling-plan-option;predictive-searchmissing an<input>or an item template;filter-listwith nofilter-group/filter-value;change-filterwith nofilter-value;active-filter-listwith no first-child chip template;storesynk-bundlewhose first element child is not, and does not contain, abundle-offer;bundle-member-listwhose first element child is not, and does not contain, astoresynk-productmember card;storesynk-volume-discountwhose first element child does not contain avolume-tier-list;volume-tier-listwhose first element child is not, and does not contain, avolume-tier;storesynk-customer-pricingwith no first element child (its per-rule template is free-form - only its presence is required);storesynk-mix-matchwhose first element child is not, and does not contain, amix-match-offer;mix-match-section-listwhose first element child is not, and does not contain, amix-match-section;mix-match-item-listwhose first element child is not, and does not contain, astoresynk-productpool card;mix-match-selection-listwith no first element child (the pick template is free-form - only its presence is required);storesynk-addonswith no first element child (its per-offer template is free-form - only its presence is required);addon-listwhose first element child is not, and does not contain, astoresynk-productrow card. - Why it breaks: the container captures its first child as the clone template; with no template there is nothing to clone, so it renders nothing.
- Known symptoms: an empty grid/list/dropdown even when data loads (
[ss-loading]clears but no items appear). - Fix: add the required template as the first child (a
storesynk-productitem, acart-line, acart-discount, aselling-plan-option, afilter-group/filter-value, a chip, an<input>plus result-item template for predictive search, abundle-offerfor the bundle widget, astoresynk-productmember card forbundle-member-list, avolume-tier-listinside thestoresynk-volume-discounttemplate, avolume-tierrow forvolume-tier-list, amix-match-offerforstoresynk-mix-match, amix-match-sectionformix-match-section-list, astoresynk-productpool card formix-match-item-list, astoresynk-productrow card foraddon-list, or any template child forstoresynk-customer-pricing/mix-match-selection-list/storesynk-addons).
SSK-108 - Quantity/option/selling-plan/purchase/metafield/filter control outside its container
Section titled “SSK-108 - Quantity/option/selling-plan/purchase/metafield/filter control outside its container”- Severity: Warning
- Applies to:
increase-quantity,decrease-quantity,input-quantity,option-value,show-option-title,show-option-swatch,selling-plan-option,show-selling-plan-name,show-selling-plan-price,purchase-option,metafield-item,locale-value,show-locale-name,show-locale-currency,filter-group,filter-value,active-filter-item,show-filter-label,show-filter-title,show-filter-count,show-filter-swatch. - Detect:
increase-quantity/decrease-quantity/input-quantityoutside achange-quantity;option-value/show-option-title/show-option-swatchoutside achange-option;selling-plan-option/show-selling-plan-name/show-selling-plan-priceoutside achange-selling-planorchange-line-selling-plan;purchase-optionoutside achange-purchase-optionorchange-line-purchase-option;metafield-itemoutside ashow-metafield;locale-value/show-locale-name/show-locale-currencyoutside achange-countryorchange-language;filter-groupoutside afilter-list;active-filter-itemoutside anactive-filter-list;filter-value/show-filter-label/show-filter-count/show-filter-swatchoutside afilter-listorchange-filter;show-filter-titleoutside afilter-list/change-filter/active-filter-list. - Why it breaks: the control has no stepper/selector/displayer/facet container to register with, so it cannot read or write the relevant state (or be cloned per value).
- Known symptoms: steppers, option pills, plan rows, purchase-mode toggles, list metafield rows, and facet rows/chips that are inert or never populated.
- Fix: nest the control inside
change-quantity(steppers),change-option(option-value parts),change-selling-plan/change-line-selling-plan(selling-plan parts),change-purchase-option/change-line-purchase-option(purchase-option) - thechange-line-*pair when the control lives in a<cart-line>, the PDP pair inside a<storesynk-product>-show-metafield(metafield-item), a Markets picker (change-country/change-language-show-locale-*go within alocale-value), or a filter container (filter-list/change-filter/active-filter-list), as appropriate.
SSK-109 - close-cart outside <storesynk-cart>
Section titled “SSK-109 - close-cart outside <storesynk-cart>”- Severity: Warning
- Applies to:
close-cart. - Detect: a
close-cartwith nostoresynk-cartancestor. - Why it breaks: it closes the nearest drawer; with no drawer ancestor there is nothing to close.
- Known symptoms: a close button that does nothing.
- Fix: place it inside the drawer, or use
open-cart, which works anywhere.
SSK-110 - Collection control outside <storesynk-collection>
Section titled “SSK-110 - Collection control outside <storesynk-collection>”- Severity: Error
- Applies to:
product-list,change-sort,change-price,change-filter,filter-list,active-filter-list,clear-filters,load-more,show-result-count. - Detect: any of these with no
storesynk-collectionancestor. - Why it breaks: they consume
collectionContext(products, facets, filter/sort/paging state + methods); with nostoresynk-collectionprovider above them there is no context, so they render nothing - silently, the same failure mode as SSK-101/102/105. - Known symptoms: an empty product grid, filters/sort/chips that never populate, a dead “Load more”.
- Fix: move the control inside a
<storesynk-collection handle="…">. (The facet leaf parts -filter-group,filter-value,show-filter-*,active-filter-item- don’t consume the context directly; their nesting is governed by SSK-108.)
SSK-111 - Regular price displayer inside <storesynk-customer-pricing>
Section titled “SSK-111 - Regular price displayer inside <storesynk-customer-pricing>”- Severity: Warning
- Applies to:
show-price,show-compare-price,show-unit-price(the regular variant-price displayers). - Detect: any of these with a
storesynk-customer-pricingancestor (anywhere inside the widget’s template). - Why it breaks: the widget clones its first-child template only when a live rule targets
the product - a product with no matching rule renders no clone, so a regular price authored
inside the widget disappears with it and the shopper sees no price at all. Regular price
displayers must be siblings of the widget; only the
show-pricing-*leaves belong in the template. - Known symptoms: the price shows on products that have a customer-pricing rule but vanishes on every product without one.
- Fix: move the displayer out to a sibling of the widget (inside the same price row) and
swap the halves in CSS on the reflected member state:
.price-row:has(storesynk-customer-pricing[ss-member]) .price-anon { display: none }- see build-patterns §2.12, the inline recipe.
Imported from the Storesynk skill v0.1.0 (references/structure-rules.md). To change this page, change it there.