Skip to content

SSK-1xx - structure & nesting

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-store on the page but not as an ancestor - open-cart, search-input, and the customer verbs log-in / log-out (they drive the store’s single module-level session and consume no context).
  • Detect: a storesynk tag with no storesynk-store ancestor anywhere above it (or, for the page-scoped tags above, no storesynk-store anywhere on the page).
  • Why it breaks: with no storeContext there 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 displayers show-option-label / show-active-option-title, the metafield displayers show-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), and storesynk-mix-match - with one exemption: a storesynk-mix-match that carries a handle="…" 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-product ancestor; for storesynk-mix-match, only when it also has no handle attribute.
  • 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 widget handle="…". Special case: a change-purchase-option / change-selling-plan authored 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.
  • Severity: Error
  • Detect: a storesynk-product that has a storesynk-product ancestor - unless it also has a bundle-member-list, a mix-match-item-list, or an addon-list ancestor. Those are the three sanctioned nestings: a bundle member card, a mix & match pool card, and a product-addons row card are each a storesynk-product inside the page’s product by design (fed via provideProduct()), 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>.
  • Severity: Error
  • Detect: a storesynk-store that has a storesynk-store ancestor.
  • 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 controls change-line-purchase-option / change-line-selling-plan (need cart-line); show-discount-amount (needs cart-discount); the bundle-context tags show-bundle-title / show-bundle-total / show-bundle-original-total / show-bundle-savings / show-bundle-percentage / add-bundle-to-cart / bundle-member-list (need bundle-offer); the member-context displayers show-member-quantity / show-member-subtotal (need bundle-member-list); the volume-discount-context tags show-volume-discount-title / volume-tier-list / add-volume-to-cart (need storesynk-volume-discount); and the tier-context displayers show-tier-title / show-tier-label / show-tier-badge / show-tier-price / show-tier-original-price / show-tier-each-price (need volume-tier-list); the customer-pricing displayers show-pricing-prompt / show-pricing-title / show-pricing-percentage / show-pricing-price / show-pricing-original-price / show-pricing-note (need storesynk-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 (need mix-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 (need mix-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 (need mix-match-item-list, i.e. the pool-card template);
    • pick context - show-pick-image / show-pick-quantity / show-selection-overflow (need mix-match-selection-list);

    and the two product-addons context families:

    • offer context - show-addons-title / show-addons-subtitle / addon-list (need storesynk-addons);
    • row context - select-addon / show-addon-price / show-addon-original-price (need addon-list, i.e. the row-card template).
  • Detect: any of those tags with no cart-line ancestor; show-discount-amount with no cart-discount ancestor; a bundle-context tag with no bundle-offer ancestor; a member displayer with no bundle-member-list ancestor; a volume-discount-context tag with no storesynk-volume-discount ancestor; a tier displayer with no volume-tier-list ancestor; a pricing displayer with no storesynk-customer-pricing ancestor; a mix & match tag with no mix-match-offer / mix-match-section / mix-match-item-list / mix-match-selection-list ancestor per the four families above; or a product-addons tag with no storesynk-addons / addon-list ancestor 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 / mixMatchContext and its per-clone section / item / pick contexts / addonsContext and 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. a show-section-count outside <mix-match-section>, a stepper outside the pool card, or a select-addon outside 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-line with no cart-line-list ancestor; a cart-discount with no cart-discount-list / cart-order-discount-list ancestor; a bundle-offer with no storesynk-bundle ancestor; a volume-tier with no volume-tier-list ancestor; a mix-match-offer with no storesynk-mix-match ancestor; or a mix-match-section with no mix-match-section-list ancestor.
  • Why it breaks: only the container clones and populates the item (the discount lists via provideDiscount(), the bundle widget via provideBundle(), the tier list per tier, the mix-match widget via provideLive(), the section list per section), so a stray cart-line / cart-discount / bundle-offer / volume-tier / mix-match-offer / mix-match-section is never driven - and a mix-match-section outside its list also never receives the ss-open/ss-met stamps 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-line inside a <cart-line-list>, the cart-discount inside a <cart-discount-list> / <cart-order-discount-list>, the bundle-offer inside a <storesynk-bundle>, the volume-tier inside a <volume-tier-list>, the mix-match-offer inside a <storesynk-mix-match>, or the mix-match-section inside 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-list whose first element child is not, and does not contain, a storesynk-product; cart-line-list with no cart-line; a discount list with no cart-discount; change-selling-plan or change-line-selling-plan with no selling-plan-option; predictive-search missing an <input> or an item template; filter-list with no filter-group/filter-value; change-filter with no filter-value; active-filter-list with no first-child chip template; storesynk-bundle whose first element child is not, and does not contain, a bundle-offer; bundle-member-list whose first element child is not, and does not contain, a storesynk-product member card; storesynk-volume-discount whose first element child does not contain a volume-tier-list; volume-tier-list whose first element child is not, and does not contain, a volume-tier; storesynk-customer-pricing with no first element child (its per-rule template is free-form - only its presence is required); storesynk-mix-match whose first element child is not, and does not contain, a mix-match-offer; mix-match-section-list whose first element child is not, and does not contain, a mix-match-section; mix-match-item-list whose first element child is not, and does not contain, a storesynk-product pool card; mix-match-selection-list with no first element child (the pick template is free-form - only its presence is required); storesynk-addons with no first element child (its per-offer template is free-form - only its presence is required); addon-list whose first element child is not, and does not contain, a storesynk-product row 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-product item, a cart-line, a cart-discount, a selling-plan-option, a filter-group/filter-value, a chip, an <input> plus result-item template for predictive search, a bundle-offer for the bundle widget, a storesynk-product member card for bundle-member-list, a volume-tier-list inside the storesynk-volume-discount template, a volume-tier row for volume-tier-list, a mix-match-offer for storesynk-mix-match, a mix-match-section for mix-match-section-list, a storesynk-product pool card for mix-match-item-list, a storesynk-product row card for addon-list, or any template child for storesynk-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-quantity outside a change-quantity; option-value / show-option-title / show-option-swatch outside a change-option; selling-plan-option / show-selling-plan-name / show-selling-plan-price outside a change-selling-plan or change-line-selling-plan; purchase-option outside a change-purchase-option or change-line-purchase-option; metafield-item outside a show-metafield; locale-value / show-locale-name / show-locale-currency outside a change-country or change-language; filter-group outside a filter-list; active-filter-item outside an active-filter-list; filter-value / show-filter-label / show-filter-count / show-filter-swatch outside a filter-list or change-filter; show-filter-title outside a filter-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) - the change-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 a locale-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-cart with no storesynk-cart ancestor.
  • 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-collection ancestor.
  • Why it breaks: they consume collectionContext (products, facets, filter/sort/paging state + methods); with no storesynk-collection provider 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-pricing ancestor (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.