@shopify/hydrogen 2026.10.0 → 2026.10.1
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/dist/core/cart/queries.d.mts +57 -57
- package/dist/core/predictive-search/queries.d.mts +2 -2
- package/dist/core/request-context.mjs +1 -1
- package/dist/customer-account/client.mjs +1 -1
- package/dist/customer-account/session.mjs +1 -1
- package/dist/development/core/request-context.mjs +1 -1
- package/package.json +1 -1
- package/skills/migrate-to-hydrogen-2026-10/SKILL.md +332 -0
- package/skills/migrate-to-hydrogen-2026-10/references/analytics.md +24 -0
- package/skills/migrate-to-hydrogen-2026-10/references/cart.md +9 -0
- package/skills/migrate-to-hydrogen-2026-10/references/customer-account.md +10 -0
- package/skills/migrate-to-hydrogen-2026-10/references/dependencies-and-tooling.md +10 -0
- package/skills/migrate-to-hydrogen-2026-10/references/optional-subsystems.md +25 -0
- package/skills/migrate-to-hydrogen-2026-10/references/routing-and-loaders.md +10 -0
- package/skills/migrate-to-hydrogen-2026-10/references/sitemap-and-seo.md +5 -0
- package/skills/migrate-to-hydrogen-2026-10/references/typescript-and-gql-tada.md +7 -0
- package/skills/migrate-to-hydrogen-2026-10/references/ui-and-components.md +9 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# TypeScript & gql traps
|
|
2
|
+
|
|
3
|
+
These surface when you run `react-router typegen && tsc` and `hydrogen gql check`. Read before wiring typed queries or re-pointing imports.
|
|
4
|
+
|
|
5
|
+
- **Typed GraphQL runs through the library's ts-plugin, not app-owned gql.tada config.** `@shopify/hydrogen` ships the schemas and a TypeScript plugin: add `{"name": "@shopify/hydrogen/ts-plugin"}` to `compilerOptions.plugins` in `tsconfig.json` and delete any classic-era gql.tada `schema`/`schemas` tsconfig block pointing at generated schema files. The plugin writes its schema environments (`*-graphql-env.d.ts`) at the **project root**; gitignore them. Add `hydrogen gql check --fail-on-warn` to the `typecheck` script — a wrong setup fails silently otherwise: typing just stops working, and nothing errors until you run the check. Type results with the `StorefrontApi` namespace / `ResultOf`; the library's `gql()` returns a **branded query string**, not a gql.tada document, so `FragmentOf` does **not** apply — to type a fragment's data, compose a throwaway query that spreads the fragment and take `ResultOf` of that (see the `hydrogen-storefront-client` packaged skill).
|
|
6
|
+
- **Framework types dropped from core are gone — but check the installed exports before shimming.** Types the app imported from `@shopify/hydrogen` in classic Hydrogen (e.g. `I18nBase`) may no longer be exported, so a bare type import fails with "no exported member". `I18nBase` → the library's `I18nConfig`. API object types → `@shopify/hydrogen/storefront-api-types` and `.../customer-account-api-types`. Several classic helpers **returned to core** (`flattenConnection`, `getSelectedProductOptions`, `formatMoney`, the `MoneyV2` type) — grep the installed package's `.d.mts` exports first. Only what is genuinely absent (component prop shapes, other helpers' types) gets a small local structural type for the fields the app actually uses; there is no classic package to fall back to.
|
|
7
|
+
- **gql result types are *partial and union-shaped*, unlike the old generated types.** Two distinct traps: (1) A query on a union/interface field (storefront `search`, metaobject `references`) is typed as the **full union** — the `types:`/`unavailableProducts:` argument and a single `...on X` inline fragment do **not** narrow it at the type level, so non-`X` members appear with only `__typename` and field access fails. Narrow with `Extract<…nodes[number], {__typename: 'X'}>` (a cast is honest here since the arg guarantees the runtime type). (2) A selection-derived type is **not** assignable to the full `storefront-api-types` type a component prop declares (e.g. `ProductVariant` requires `metafields` via `HasMetafields`, which the query didn't select). Either loosen the prop to the fields actually read (structural type) or bridge with a cast at the one boundary. Make `<Money>`/price components accept a structural `{amount, currencyCode}` and tolerate `null`/`undefined` — this also resolves the storefront-vs-customer-account `MoneyV2` **brand clash** that otherwise fails at every account money render.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# UI & component traps
|
|
2
|
+
|
|
3
|
+
Read while migrating the product variant form, product/collection lists, and re-owned root/layout. These render fine but are slow, a UX regression, or inaccessible.
|
|
4
|
+
|
|
5
|
+
- **Variant pickers are progressively-enhanced links, not `<button>`s and not plain navigation.** Two ways to get this wrong. Carried over verbatim, a classic form's `<Link>` per option value makes every variant change a full route navigation — laggy, selected state waits on the loader round-trip. But replacing the links with bare `<button>`s breaks the no-JS path and loses the crawlable URLs. The library's pattern (follow the `hydrogen-variant-form` packaged skill): render every same-product option value as a **real `<a href>` GET link**, then spread the product-form store's `register(…)` props on it so JS intercepts the click and `selectOption(name, value)` updates the selection client-side without navigating; the return value of `selectOption` tells you when a genuine navigation (different product `handle`) is still needed. A disabled `<button>` is only for values with `exists: false` (no variant combination at all). The store side is `createProductFormStore`/`createProductFormRegister` + `getSelectedVariant`; React apps get `createProductComponents()`/`useProductForm` from `@shopify/hydrogen/react`.
|
|
6
|
+
- **Some presentational primitives left core — but check before shimming.** `<Image>` and `<MediaFile>` component re-exports are no longer exported from `@shopify/hydrogen` — the `hydrogen-image` packaged skill gives the local reference implementation. `<Money>` needs no local shim anymore: core exports `formatMoney()` and the `hydrogen-money` packaged skill builds on it. Helpers such as `flattenConnection` and `getSelectedProductOptions` (and the `MoneyV2` type) are exported from core again — verify against the installed package's exports before writing a local copy. Typecheck flags the broken imports; resolve them up front rather than one failing route at a time.
|
|
7
|
+
- **List pagination: use the collection store, do not hand-roll.** Classic `<Pagination>` and `getPaginationVariables` are gone, but the library now ships a collection-browse suite: `createCollectionStore`/`createCollectionReconciler` plus filter/sort helpers (`parseCollectionParams`, `serializeCollectionParams`, `getFilterRemovalUrl`, `getSortByValue`) and React `CollectionProvider`/`useCollection*`. The `hydrogen-collection-browser` packaged skill gives the pattern: a GET-degradable browse form, and "Load more" as a real GET cursor link that JS upgrades to append-in-place. Hand-rolling accumulate + `IntersectionObserver` (or downgrading to bare Next/Previous links) is now a divergence from the library, not the faithful option.
|
|
8
|
+
- **Accessibility affordances you now own.** Classic-Hydrogen layouts often shipped a working skip-to-content link and route-change focus handling. After you re-own the root/layout, re-verify them: a skip link that is `sr-only` without a `focus:` reveal is permanently unusable; focus should move to the main landmark on navigation (give it `tabIndex={-1}`); and controls that were icon-only need an accessible name. Easy to carry over broken because it renders fine.
|
|
9
|
+
- **Prune classic-era client glue.** Swapping to the library primitives (`useCartForm`/`useCart`, the customer-account client, etc.) orphans the hand-rolled hooks and helpers that wrapped the old fetcher/route patterns. They keep compiling, so grep for now-unused ones and delete them rather than leaving dead code that implies a mechanism no longer in use.
|