# Variant-safe Shopify product section

Original ThemeCare integration asset, checked against current official documentation on 2026-10-02. It has not been installed or accepted in a real merchant store. No Shopify account, store, customer record, real variant ID or payment was accessed.

## Scope and behavior

- A product selected in the section settings, or the current product when the optional setting is empty.
- At most 100 variants; one unit per addition; one-time purchases. Products requiring a selling plan are excluded. Variants requiring a plan, nonstandard minimum/increment, or quantity-break pricing are not orderable through this component.
- The native `<select name="id">` contains real IDs from `variant.id`, rather than copied demo IDs or a product ID. There is no second hidden `name="id"` field to drift out of sync.
- Without JavaScript, selecting an available option submits that ID through Shopify's product form. Unavailable options are disabled, and the submit button is disabled when no supported variant is available. Each option displays its own server-formatted price. A sold-out deep link falls back to an available variant without JavaScript; the selected option tells the buyer what will be submitted.
- JavaScript updates price, image, stock control and the variant URL. It checks the selected option again before submission, while leaving valid submission to the native form. A sold-out deep link is displayed as sold out with JavaScript, and submission is blocked until an available option is chosen.
- Variant URL updates run only on the selected product's actual product page and can be switched off. Featured products elsewhere do not overwrite another product's URL. Query parameters and anchors are preserved; stale `option_values` are removed when a specific variant is chosen.
- A custom element handles attach/detach, including theme-editor section reloads, without duplicate event listeners. It does not implement AJAX cart drawers, subscriptions, variant-option grids, videos, 3D media, personalization, bundles or volume-pricing checkout.

`variant.available` follows Shopify's availability policy. Inventory set to “continue selling” may remain available at quantity zero. Stock data can change after page rendering; the Shopify cart server remains responsible for current inventory and purchasing rules. Client-side disablement is not inventory enforcement.

## Files to install in a duplicated unpublished theme

| This package | Destination |
|---|---|
| `sections/variant-safe-product.liquid` | `sections/variant-safe-product.liquid` |
| `assets/variant-safe-product.js` | `assets/variant-safe-product.js` |
| `assets/variant-safe-product.css` | `assets/variant-safe-product.css` |

1. Duplicate/export the theme and record the existing product template before changing anything.
2. Copy the three files into the duplicated theme. Do not paste the section into an existing product `<form>`; nested forms are invalid. The component is a standalone scoped product form, not a global replacement for existing pickers.
3. Add **Variant-safe product** through the theme editor to a test product template, or a section-capable page. Select a product if using a featured-product page. Avoid duplicate primary forms that confuse the storefront.
4. In the duplicated theme, check whether existing theme/app cart listeners intercept the native form. Confirm their behavior or exclude this component from those listeners before deployment. Do not claim compatibility with an untested cart drawer.
5. Translate the configurable labels, test the acceptance cases below, and compare changed files. Only publish after the merchant's acceptance of the actual theme behavior.

## Acceptance checklist in the real duplicated theme

- Use a product with at least two available variants with different prices and one unavailable variant. Confirm title, price, image and selected ID agree.
- Disable JavaScript: select each available option and add one item to the cart. Inspect the actual cart's selected variant and quantity. A sold-out option must not be selectable; an entirely sold-out product must disable submission.
- Enable JavaScript: test available and sold-out `?variant=` links, a change between variants, reload and browser history, all sold out, and products without images.
- Confirm formatting in the store's real currency/locale, query/hash preservation, no variant URL mutation for a featured product on unrelated pages, and labels in the intended language.
- Verify keyboard selection, mobile display, theme editor section removal/re-addition, and existing theme/app cart behavior. Verify a changed inventory state is rejected appropriately by Shopify; no client snapshot can establish that.
- Required selling plans, quantity restrictions, high-variant products and other excluded configurations must use their original supported product flow.

## Rollback

Remove this section from the duplicated template and restore the recorded original section order/configuration. If it was published after acceptance, restore the previous accepted theme/template first. Remove only these three newly added files once no template references the section. No product records, inventory, customers or payment settings are changed by installing or removing this package.

## Verification performed here

Run `node --test test.mjs` from this folder. The test harness executes the actual browser asset against a minimal event/DOM fixture and validates the Liquid schema and structural safety properties. It is a local JavaScript/static check, not Shopify's Liquid renderer, official Theme Check, a browser checkout test, or merchant acceptance.

Official Shopify CLI 4.8.4 Theme Check was run on 2026-10-02 against these exact three source files in a minimal standalone theme fixture. The recommended configuration enabled 83 checks, with `--fail-level warning`; the diagnostic output was `[]` and the exit code was 0. The CLI's separate Theme Check version command returned `unknown`, so no independent checker version is claimed. The fixture supplied a theme layout, product template, configuration and locale scaffolding; it did not alter the three delivered source files.

The package README was updated on 2026-10-03 to record that completed check; the Liquid, JavaScript and CSS are unchanged. This is static evidence, not real-store installation, rendering, cart, payment or app-compatibility acceptance. Before merchant publication, run `shopify theme check --path <duplicated-theme-directory> --config theme-check:recommended --fail-level warning` and perform the real-theme acceptance checklist above on the entire duplicated theme.

## Official implementation references

- [Product form tag](https://shopify.dev/docs/api/liquid/tags/form#form-product): generates Shopify's native product cart form.
- [Variant support](https://shopify.dev/docs/storefronts/themes/product-merchandising/variants): variant deep links, native selectors, price and media synchronization.
- [Product object](https://shopify.dev/docs/api/liquid/objects/product): selected/available variants, product settings data and total variant count. Unpaginated variant collections are limited, which this bounded asset avoids.
- [Variant object](https://shopify.dev/docs/api/liquid/objects/variant): availability, presentment prices, selling-plan requirement and quantity rules.
- [Product picker setting](https://shopify.dev/docs/storefronts/themes/architecture/settings/input-settings#product) and [section schema](https://shopify.dev/docs/storefronts/themes/architecture/sections/section-schema): optional product selection and addable section.
- [Theme editor integration](https://shopify.dev/docs/storefronts/themes/best-practices/editor/integrate-sections-and-blocks): editor sections change without a full-page reload.
- [Official Theme Check command](https://shopify.dev/docs/api/shopify-cli/theme/theme-check): the documented CLI validation command.
