@shopify/cli-hydrogen 12.0.0 → 12.0.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.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/dist/assets/hydrogen/routes/locale-check.ts +3 -3
  3. package/dist/assets/hydrogen/starter/.graphqlrc.ts +4 -2
  4. package/dist/assets/hydrogen/starter/CHANGELOG.md +271 -0
  5. package/dist/assets/hydrogen/starter/app/components/Aside.tsx +4 -2
  6. package/dist/assets/hydrogen/starter/app/components/CartLineItem.tsx +67 -38
  7. package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +49 -8
  8. package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +133 -57
  9. package/dist/assets/hydrogen/starter/app/components/Header.tsx +3 -3
  10. package/dist/assets/hydrogen/starter/app/components/MockShopNotice.tsx +20 -0
  11. package/dist/assets/hydrogen/starter/app/components/PaginatedResourceSection.tsx +24 -4
  12. package/dist/assets/hydrogen/starter/app/components/ProductPrice.tsx +1 -1
  13. package/dist/assets/hydrogen/starter/app/entry.client.tsx +2 -3
  14. package/dist/assets/hydrogen/starter/app/lib/context.ts +5 -0
  15. package/dist/assets/hydrogen/starter/app/lib/fragments.ts +8 -0
  16. package/dist/assets/hydrogen/starter/app/routes/[robots.txt].tsx +14 -53
  17. package/dist/assets/hydrogen/starter/app/routes/_index.tsx +15 -9
  18. package/dist/assets/hydrogen/starter/app/routes/account.$.tsx +1 -1
  19. package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +14 -14
  20. package/dist/assets/hydrogen/starter/app/routes/account.profile.tsx +1 -1
  21. package/dist/assets/hydrogen/starter/app/routes/account.tsx +4 -7
  22. package/dist/assets/hydrogen/starter/app/routes/account_.login.tsx +10 -0
  23. package/dist/assets/hydrogen/starter/app/routes/blogs.$blogHandle._index.tsx +2 -9
  24. package/dist/assets/hydrogen/starter/app/routes/blogs._index.tsx +1 -4
  25. package/dist/assets/hydrogen/starter/app/routes/cart.tsx +3 -11
  26. package/dist/assets/hydrogen/starter/app/routes/collections.all.tsx +1 -3
  27. package/dist/assets/hydrogen/starter/app/routes/pages.$handle.tsx +2 -8
  28. package/dist/assets/hydrogen/starter/app/routes/policies.$handle.tsx +1 -4
  29. package/dist/assets/hydrogen/starter/app/routes/policies._index.tsx +1 -1
  30. package/dist/assets/hydrogen/starter/app/routes/products.$handle.tsx +2 -9
  31. package/dist/assets/hydrogen/starter/app/routes/search.tsx +18 -12
  32. package/dist/assets/hydrogen/starter/app/styles/app.css +72 -1
  33. package/dist/assets/hydrogen/starter/eslint.config.js +1 -0
  34. package/dist/assets/hydrogen/starter/guides/predictiveSearch/predictiveSearch.md +3 -3
  35. package/dist/assets/hydrogen/starter/guides/search/search.md +1 -1
  36. package/dist/assets/hydrogen/starter/package.json +16 -16
  37. package/dist/assets/hydrogen/starter/server.ts +5 -7
  38. package/dist/assets/hydrogen/starter/storefrontapi.generated.d.ts +89 -11
  39. package/dist/assets/hydrogen/starter/vite.config.ts +10 -4
  40. package/dist/assets/hydrogen/vite/package.json +1 -2
  41. package/dist/assets/hydrogen/vite/vite.config.js +4 -3
  42. package/dist/commands/hydrogen/deploy.js +19 -13
  43. package/dist/commands/hydrogen/dev.js +6 -6
  44. package/dist/commands/hydrogen/generate/route.js +1 -1
  45. package/dist/commands/hydrogen/init.d.ts +2 -4
  46. package/dist/commands/hydrogen/init.js +2 -8
  47. package/dist/commands/hydrogen/preview.js +1 -1
  48. package/dist/commands/hydrogen/setup/css.js +1 -1
  49. package/dist/commands/hydrogen/setup/markets.js +1 -1
  50. package/dist/commands/hydrogen/setup/vite.js +1 -1
  51. package/dist/commands/hydrogen/setup.js +31 -33
  52. package/dist/commands/hydrogen/upgrade.js +173 -39
  53. package/dist/lib/build.js +4 -5
  54. package/dist/lib/bundle/vite-plugin.js +7 -21
  55. package/dist/lib/check-lockfile.js +16 -7
  56. package/dist/lib/codegen.js +2 -2
  57. package/dist/lib/format-code.js +3 -3
  58. package/dist/lib/graphql/admin/client.js +48 -23
  59. package/dist/lib/mini-oxygen/workerd.js +3 -5
  60. package/dist/lib/onboarding/common.js +21 -26
  61. package/dist/lib/onboarding/local.js +46 -59
  62. package/dist/lib/package-managers.js +2 -0
  63. package/dist/lib/patch-cli.js +198 -0
  64. package/dist/lib/setups/routes/generate.js +5 -3
  65. package/dist/lib/template-pack.js +93 -0
  66. package/dist/lib/transpile/morph/functions.js +1 -1
  67. package/dist/lib/transpile/morph/typedefs.js +2 -3
  68. package/dist/lib/upgrade-e2e-utils.js +50 -0
  69. package/oclif.manifest.json +7 -15
  70. package/package.json +22 -19
  71. package/dist/assets/hydrogen/starter/app/routes/api.$version.[graphql.json].tsx +0 -14
  72. package/dist/lib/react-router-version-check.js +0 -82
package/README.md CHANGED
@@ -8,7 +8,7 @@ The Hydrogen extension for the [Shopify CLI](https://shopify.dev/apps/tools/cli)
8
8
 
9
9
  The most common way to test the cli changes locally is to do the following:
10
10
 
11
- - Run `npm run build` in this directory (`packages/cli` from the root of the repo).
11
+ - Run `pnpm run build` in this directory (`packages/cli` from the root of the repo).
12
12
  - Run `npx shopify hydrogen` anywhere else in the monorepo, for example `npx shopify hydrogen init`.
13
13
  - If you want to test a command inside of a template, run the command from within that template or use the `--path` flag to point to another template or any Hydrogen app.
14
14
  - If you want to make changes to a file that is generated when running `npx shopify hydrogen generate`, make changes to that file from inside of the `templates/skeleton` directory.
@@ -1,4 +1,4 @@
1
- import type {LoaderFunctionArgs} from '@shopify/remix-oxygen';
1
+ import type {LoaderFunctionArgs} from 'react-router';
2
2
 
3
3
  export async function loader({params, context}: LoaderFunctionArgs) {
4
4
  const {language, country} = context.storefront.i18n;
@@ -7,8 +7,8 @@ export async function loader({params, context}: LoaderFunctionArgs) {
7
7
  params.locale &&
8
8
  params.locale.toLowerCase() !== `${language}-${country}`.toLowerCase()
9
9
  ) {
10
- // If the locale URL param is defined, yet we still are still at the default locale
11
- // then the the locale param must be invalid, send to the 404 page
10
+ // If the locale URL param is defined, yet we are still at the default locale
11
+ // then the locale param must be invalid, send to the 404 page
12
12
  throw new Response(null, {status: 404});
13
13
  }
14
14
 
@@ -6,7 +6,7 @@ import {getSchema} from '@shopify/hydrogen-codegen';
6
6
  * @see https://the-guild.dev/graphql/config/docs/user/usage
7
7
  * @type {IGraphQLConfig}
8
8
  */
9
- export default {
9
+ const graphqlConfig: IGraphQLConfig = {
10
10
  projects: {
11
11
  default: {
12
12
  schema: getSchema('storefront'),
@@ -24,4 +24,6 @@ export default {
24
24
 
25
25
  // Add your own GraphQL projects here for CMS, Shopify Admin API, etc.
26
26
  },
27
- } as IGraphQLConfig;
27
+ };
28
+
29
+ export default graphqlConfig;
@@ -1,5 +1,276 @@
1
1
  # skeleton
2
2
 
3
+ ## 2026.4.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Include line item children recursively in cart. ([#3753](https://github.com/Shopify/hydrogen/pull/3753)) by [@martin-pettersson](https://github.com/martin-pettersson)
8
+
9
+ - Add generic cart result typing to `createCartHandler` so custom cart fragments can use their generated fragment types. ([#3767](https://github.com/Shopify/hydrogen/pull/3767)) by [@andguy95](https://github.com/andguy95)
10
+
11
+ - Widen React Router peer dependency ranges so Hydrogen packages accept compatible React Router 7.16 patch versions without npm peer dependency conflicts. New Hydrogen projects now default to React Router 7.16.0. ([#3771](https://github.com/Shopify/hydrogen/pull/3771)) by [@fredericoo](https://github.com/fredericoo)
12
+
13
+ - Updated dependencies [[`3ccc22e0a3407298e835104e29adfb036f261474`](https://github.com/Shopify/hydrogen/commit/3ccc22e0a3407298e835104e29adfb036f261474), [`a810db483c108ac8bbeaac45595b130ed95a2ec7`](https://github.com/Shopify/hydrogen/commit/a810db483c108ac8bbeaac45595b130ed95a2ec7), [`d17057eb4630710743e81b83573973100ec56d23`](https://github.com/Shopify/hydrogen/commit/d17057eb4630710743e81b83573973100ec56d23), [`995190036d99e02ba6fb559b8e3c406c90043599`](https://github.com/Shopify/hydrogen/commit/995190036d99e02ba6fb559b8e3c406c90043599), [`39f2b326e9fddda36b1d12149794bf4ffcc0d4b8`](https://github.com/Shopify/hydrogen/commit/39f2b326e9fddda36b1d12149794bf4ffcc0d4b8)]:
14
+ - @shopify/hydrogen@2026.4.3
15
+
16
+ ## 2026.4.2
17
+
18
+ ### Patch Changes
19
+
20
+ - Add support for Vite 7 and Vite 8. Hydrogen remains backwards-compatible with Vite 5+. ([#3617](https://github.com/Shopify/hydrogen/pull/3617)) by [@frandiox](https://github.com/frandiox)
21
+
22
+ Mini Oxygen's dev server has been refactored to use the [Vite Environment API](https://vite.dev/guide/api-environment), which is the standard way to run non-browser runtimes in Vite. This replaces the previous custom middleware approach with a first-class `FetchableDevEnvironment`, improving compatibility with Vite's built-in HMR and module invalidation.
23
+
24
+ New Hydrogen projects created with `npm create @shopify/hydrogen` will default to Vite 8. The `vite-tsconfig-paths` plugin is no longer needed in the skeleton template since Vite 8 supports `resolve.tsconfigPaths` natively.
25
+
26
+ - Updated dependencies [[`dc49699c799997d5893bc06e444f888e86a3bc29`](https://github.com/Shopify/hydrogen/commit/dc49699c799997d5893bc06e444f888e86a3bc29), [`50df825c57159757529f5f9f62c258d4de2a4b97`](https://github.com/Shopify/hydrogen/commit/50df825c57159757529f5f9f62c258d4de2a4b97), [`51f1e77fe63be5e5ded4ef0c91942bc304f1abc4`](https://github.com/Shopify/hydrogen/commit/51f1e77fe63be5e5ded4ef0c91942bc304f1abc4)]:
27
+ - @shopify/hydrogen@2026.4.2
28
+
29
+ ## 2026.4.1
30
+
31
+ ### Patch Changes
32
+
33
+ - Fix `set-cookie-parser` and `cookie` resolution warnings during `dev` by using Vite's nested dependency syntax (`react-router > dep`). These are CJS transitive dependencies of `react-router` that weren't resolvable by bare name with strict package managers like pnpm. ([#3698](https://github.com/Shopify/hydrogen/pull/3698)) by [@fredericoo](https://github.com/fredericoo)
34
+
35
+ - Updated dependencies [[`f84ab400c62d89827574d0fa65ba310a2e75f36f`](https://github.com/Shopify/hydrogen/commit/f84ab400c62d89827574d0fa65ba310a2e75f36f)]:
36
+ - @shopify/hydrogen@2026.4.1
37
+
38
+ ## 2026.4.0
39
+
40
+ ### Major Changes
41
+
42
+ - Update Storefront API and Customer Account API from 2026-01 to 2026-04. ([#3651](https://github.com/Shopify/hydrogen/pull/3651)) by [@itsjustriley](https://github.com/itsjustriley)
43
+
44
+ ## Breaking changes
45
+
46
+ **JSON metafield values limited to 128KB**: When using API version 2026-04 or later, the Storefront API limits JSON type metafield writes to 128KB. This limit applies at the API level - Hydrogen passes through to the Storefront API without additional restriction. Apps that used JSON metafields before April 1, 2026 are grandfathered at the existing 2MB limit. Large metafield values continue to be readable by all API versions.
47
+
48
+ ## New features
49
+
50
+ **New `MERCHANDISE_LINE_TRANSFORMERS_RUN_ERROR` cart error code**: Cart operations (`cartCreate`, `cartLinesAdd`, etc.) now return a specific `MERCHANDISE_LINE_TRANSFORMERS_RUN_ERROR` error code when a Cart Transform Function fails at runtime, instead of the previous generic `INVALID` error code. If you handle cart errors in your storefront code, you may want to add handling for this new code.
51
+
52
+ ## Changelog links
53
+ - [Storefront API 2026-04 changelog](https://shopify.dev/changelog?filter=api&api_version=2026-04&api_type=storefront-graphql)
54
+ - [Customer Account API 2026-04 changelog](https://shopify.dev/changelog?filter=api&api_version=2026-04&api_type=customer-account-graphql)
55
+
56
+ ### Patch Changes
57
+
58
+ - Updated dependencies [[`e7215ed0d7a74cacfa8c935f414c1cf32fc2ccd0`](https://github.com/Shopify/hydrogen/commit/e7215ed0d7a74cacfa8c935f414c1cf32fc2ccd0), [`92ab8e8b59807bbdb5dbecaa18629292d5566135`](https://github.com/Shopify/hydrogen/commit/92ab8e8b59807bbdb5dbecaa18629292d5566135), [`b0caa5c013380c7837f049f48da089a1671e2c6d`](https://github.com/Shopify/hydrogen/commit/b0caa5c013380c7837f049f48da089a1671e2c6d)]:
59
+ - @shopify/hydrogen@2026.4.0
60
+
61
+ ## 2026.1.4
62
+
63
+ ### Patch Changes
64
+
65
+ - Remove redundant Storefront API proxy route from skeleton template. The server now automatically proxies requests to `/api/:version/graphql.json` via `createRequestHandler` with `proxyStandardRoutes: true` (enabled by default since December 2025). ([#3572](https://github.com/Shopify/hydrogen/pull/3572)) by [@itsjustriley](https://github.com/itsjustriley)
66
+
67
+ Developers no longer need a manual route file for the tokenless Storefront API. Existing apps with this route can safely delete it - the server-level proxy provides the same functionality with better cookie forwarding and analytics integration.
68
+
69
+ - Updated dependencies [[`b0a75c1d759706931876f056662de2497cb3e688`](https://github.com/Shopify/hydrogen/commit/b0a75c1d759706931876f056662de2497cb3e688), [`a44ee3566b9bb9a7f43f05dfaae6f1f2ab1d548f`](https://github.com/Shopify/hydrogen/commit/a44ee3566b9bb9a7f43f05dfaae6f1f2ab1d548f)]:
70
+ - @shopify/hydrogen@2026.1.4
71
+
72
+ ## 2026.1.3
73
+
74
+ ### Patch Changes
75
+
76
+ - Improve screen reader experience for paginated product grids by hiding decorative arrow characters from assistive technology. ([#3557](https://github.com/Shopify/hydrogen/pull/3557)) by [@itsjustriley](https://github.com/itsjustriley)
77
+
78
+ - Fix broken `aria-label` on territory code input in address form. The label was the raw developer string `"territoryCode"` instead of a human-readable `"Country code"`. ([#3607](https://github.com/Shopify/hydrogen/pull/3607)) by [@itsjustriley](https://github.com/itsjustriley)
79
+
80
+ - Add aria-label to ProductPrice for improved screen reader accessibility ([#3558](https://github.com/Shopify/hydrogen/pull/3558)) by [@itsjustriley](https://github.com/itsjustriley)
81
+
82
+ - Updated dependencies [[`108243003a7f36349a446478f4e8ab0cade3e13a`](https://github.com/Shopify/hydrogen/commit/108243003a7f36349a446478f4e8ab0cade3e13a)]:
83
+ - @shopify/hydrogen@2026.1.3
84
+
85
+ ## 2026.1.2
86
+
87
+ ### Patch Changes
88
+
89
+ - Improve gift card accessibility in Skeleton template ([#3518](https://github.com/Shopify/hydrogen/pull/3518)) by [@itsjustriley](https://github.com/itsjustriley)
90
+
91
+ - Updated shopify/cli dependencies for cli-hydrogen ([#3553](https://github.com/Shopify/hydrogen/pull/3553)) by [@andguy95](https://github.com/andguy95)
92
+
93
+ - Updated loaders that used `customerAccount.handleAuthStatus()` to now await it. ([#3523](https://github.com/Shopify/hydrogen/pull/3523)) by [@fredericoo](https://github.com/fredericoo)
94
+
95
+ ### Migration
96
+
97
+ If you call `handleAuthStatus()` in your own loaders, update those callsites to use `await`.
98
+
99
+ - Updated dependencies [[`16b0e7baca0dfd1fb330d12dac924c7593d169a8`](https://github.com/Shopify/hydrogen/commit/16b0e7baca0dfd1fb330d12dac924c7593d169a8), [`1c19b87782818dbdb4252754d2d44eb9a44fe50f`](https://github.com/Shopify/hydrogen/commit/1c19b87782818dbdb4252754d2d44eb9a44fe50f), [`029fa2d0e2297f67b37c650ba8e875ee5dee81b3`](https://github.com/Shopify/hydrogen/commit/029fa2d0e2297f67b37c650ba8e875ee5dee81b3)]:
100
+ - @shopify/hydrogen@2026.1.2
101
+
102
+ ## 2026.1.1
103
+
104
+ ### Patch Changes
105
+
106
+ - Added a notice with relevant information on how to link a store in case there is no store linked yet ([#3448](https://github.com/Shopify/hydrogen/pull/3448)) by [@fredericoo](https://github.com/fredericoo)
107
+
108
+ - Fixed an issue where users without addresses could not add the first one ([#3456](https://github.com/Shopify/hydrogen/pull/3456)) by [@fredericoo](https://github.com/fredericoo)
109
+
110
+ - Updated dependencies [[`ff93a1daf2207e52e1f8331f9ff2ccd1f9b7fed6`](https://github.com/Shopify/hydrogen/commit/ff93a1daf2207e52e1f8331f9ff2ccd1f9b7fed6)]:
111
+ - @shopify/hydrogen@2026.1.1
112
+
113
+ ## 2026.1.0
114
+
115
+ ### Major Changes
116
+
117
+ - Updated to Storefront API 2026-01 and Customer Account API 2026-01. ([#3434](https://github.com/Shopify/hydrogen/pull/3434)) by [@kdaviduik](https://github.com/kdaviduik)
118
+
119
+ This is a quarterly API version update aligned with Shopify's API release schedule.
120
+
121
+ **Action Required**: The `cartDiscountCodesUpdate` mutation now requires the `discountCodes` argument. If you have custom cart discount code logic, verify your mutations include this field.
122
+
123
+ Review the changelogs for other changes that may affect your storefront:
124
+ - [Storefront API 2026-01 changelog](https://shopify.dev/changelog?filter=api&api_version=2026-01&api_type=storefront-graphql)
125
+ - [Customer Account API 2026-01 changelog](https://shopify.dev/changelog?filter=api&api_version=2026-01&api_type=customer-account-graphql)
126
+
127
+ ### Patch Changes
128
+
129
+ - Updated dependencies [[`d46c8864aea059cac7dda4871a565f76a04b1495`](https://github.com/Shopify/hydrogen/commit/d46c8864aea059cac7dda4871a565f76a04b1495)]:
130
+ - @shopify/hydrogen@2026.0.0
131
+
132
+ ## 2025.10.1
133
+
134
+ ### Major Changes
135
+
136
+ - Update Storefront API and Customer Account API to version 2025-10 ([#3430](https://github.com/Shopify/hydrogen/pull/3430)) by [@kdaviduik](https://github.com/kdaviduik)
137
+
138
+ ### Patch Changes
139
+
140
+ - Add support for Bun's text-based lockfile (`bun.lock`) introduced in Bun 1.2, and npm's shrinkwrap lockfile (`npm-shrinkwrap.json`), as alternatives to their respective primary lockfiles (`bun.lockb` and `package-lock.json`). ([#3430](https://github.com/Shopify/hydrogen/pull/3430)) by [@kdaviduik](https://github.com/kdaviduik)
141
+
142
+ - Add `cartGiftCardCodesAdd` mutation ([#3430](https://github.com/Shopify/hydrogen/pull/3430)) by [@kdaviduik](https://github.com/kdaviduik)
143
+
144
+ ## New Feature: cartGiftCardCodesAdd
145
+
146
+ The skeleton template has been updated to use the new `cartGiftCardCodesAdd` mutation:
147
+ - Removed `UpdateGiftCardForm` component from `CartSummary.tsx`
148
+ - Added `AddGiftCardForm` component using `CartForm.ACTIONS.GiftCardCodesAdd`
149
+
150
+ If you customized the gift card form in your project, you may want to migrate to the new `Add` action for simpler code.
151
+
152
+ ## Usage
153
+
154
+ ```typescript
155
+ import {CartForm} from '@shopify/hydrogen';
156
+
157
+ <CartForm action={CartForm.ACTIONS.GiftCardCodesAdd} inputs={{giftCardCodes: ['CODE1', 'CODE2']}}>
158
+ <button>Add Gift Cards</button>
159
+ </CartForm>
160
+ ```
161
+
162
+ Or with createCartHandler:
163
+
164
+ ```typescript
165
+ const cart = createCartHandler({storefront, getCartId, setCartId});
166
+ await cart.addGiftCardCodes(['SUMMER2025', 'WELCOME10']);
167
+ ```
168
+
169
+ - Add support for nested cart line items (warranties, gift wrapping, etc.) ([#3430](https://github.com/Shopify/hydrogen/pull/3430)) by [@kdaviduik](https://github.com/kdaviduik)
170
+
171
+ Storefront API 2025-10 introduces `parentRelationship` on cart line items, enabling parent-child relationships for add-ons. This update displays nested line items in the cart.
172
+
173
+ ### Changes
174
+ - Updates GraphQL fragments to include `parentRelationship` and `lineComponents` fields
175
+ - Updates `CartMain` and `CartLineItem` to render child line items with visual hierarchy
176
+
177
+ ### Note
178
+
179
+ This update focuses on **displaying** nested line items. To add both a product and its child (e.g., warranty) in a single action:
180
+
181
+ ```tsx
182
+ <AddToCartButton
183
+ lines={[
184
+ {merchandiseId: 'gid://shopify/ProductVariant/laptop-456', quantity: 1},
185
+ {
186
+ merchandiseId: 'gid://shopify/ProductVariant/warranty-123',
187
+ quantity: 1,
188
+ parent: {merchandiseId: 'gid://shopify/ProductVariant/laptop-456'},
189
+ },
190
+ ]}
191
+ >
192
+ Add to Cart with Warranty
193
+ </AddToCartButton>
194
+ ```
195
+
196
+ - Updated dependencies [[`722915130410086bc7af22215ba57ee77aa14156`](https://github.com/Shopify/hydrogen/commit/722915130410086bc7af22215ba57ee77aa14156)]:
197
+ - @shopify/hydrogen@2025.10.1
198
+
199
+ ## 2025.10.0
200
+
201
+ ### Patch Changes
202
+
203
+ - Updated dependencies [[`cd653456fbd1e7e1ab1f6fecff04c89a74b6cad9`](https://github.com/Shopify/hydrogen/commit/cd653456fbd1e7e1ab1f6fecff04c89a74b6cad9), [`24d26ad94e90ab0a859c274838f7f31e75a7808c`](https://github.com/Shopify/hydrogen/commit/24d26ad94e90ab0a859c274838f7f31e75a7808c), [`13a6f8987ea20d33a30a9c0329d7c11528b892ea`](https://github.com/Shopify/hydrogen/commit/13a6f8987ea20d33a30a9c0329d7c11528b892ea), [`403c1f5b6e266c3dfad30f7cfed229e3304570b0`](https://github.com/Shopify/hydrogen/commit/403c1f5b6e266c3dfad30f7cfed229e3304570b0), [`38f8a79625838a9cd4520b20c0db2e5d331f7d26`](https://github.com/Shopify/hydrogen/commit/38f8a79625838a9cd4520b20c0db2e5d331f7d26)]:
204
+ - @shopify/hydrogen@2026.0.0
205
+
206
+ ## 2025.7.3
207
+
208
+ ### Patch Changes
209
+
210
+ - Support OAuth parameters via URL query strings in skeleton login route ([#3391](https://github.com/Shopify/hydrogen/pull/3391)) by [@kdaviduik](https://github.com/kdaviduik)
211
+
212
+ The skeleton template's login route (`account_.login.tsx`) now reads OAuth parameters from the URL and forwards them to `customerAccount.login()`. This enables deep linking to the login page with pre-configured authentication options.
213
+
214
+ ### Supported Query Parameters
215
+
216
+ | Query Parameter | Description |
217
+ | ----------------- | ---------------------------------------------------------------------------------- |
218
+ | `acr_values` | Direct users to a specific login method (e.g., `provider:google` for social login) |
219
+ | `login_hint` | Pre-fill the email address field |
220
+ | `login_hint_mode` | When set to `submit` with `login_hint`, auto-submits the login form |
221
+ | `locale` | Display the login page in a specific language (e.g., `fr`, `zh-CN`) |
222
+
223
+ ### Usage Examples
224
+
225
+ ```
226
+ /account/login?login_hint=user@example.com
227
+ /account/login?login_hint=user@example.com&login_hint_mode=submit
228
+ /account/login?acr_values=provider:google
229
+ /account/login?locale=fr
230
+ ```
231
+
232
+ - Updated dependencies [[`7c077f5f21a595c0355873ac8073b716dfeaf4d0`](https://github.com/Shopify/hydrogen/commit/7c077f5f21a595c0355873ac8073b716dfeaf4d0), [`7c077f5f21a595c0355873ac8073b716dfeaf4d0`](https://github.com/Shopify/hydrogen/commit/7c077f5f21a595c0355873ac8073b716dfeaf4d0), [`7c077f5f21a595c0355873ac8073b716dfeaf4d0`](https://github.com/Shopify/hydrogen/commit/7c077f5f21a595c0355873ac8073b716dfeaf4d0)]:
233
+ - @shopify/hydrogen@2025.8.0
234
+
235
+ ## 2025.7.2
236
+
237
+ ### Patch Changes
238
+
239
+ - Updated dependencies [[`6d22e45d29e89a7a8dddfe3c06459d89e4590483`](https://github.com/Shopify/hydrogen/commit/6d22e45d29e89a7a8dddfe3c06459d89e4590483), [`702f966c8e60eba7434363c9012f12bed92a8e4d`](https://github.com/Shopify/hydrogen/commit/702f966c8e60eba7434363c9012f12bed92a8e4d)]:
240
+ - @shopify/hydrogen@2025.7.2
241
+
242
+ ## 2025.7.1
243
+
244
+ ### Patch Changes
245
+
246
+ - Update React Router to 7.12.0 with stabilized future flags ([#3346](https://github.com/Shopify/hydrogen/pull/3346)) by [@kdaviduik](https://github.com/kdaviduik)
247
+
248
+ This release uses React Router's newly stabilized future flags (`v8_splitRouteModules`, `v8_middleware`) instead of their unstable counterparts
249
+
250
+ - Moved server build in `server.ts` from a dynamic import to a static import to speed up first rendering during local development (2s => 200ms). ([#3331](https://github.com/Shopify/hydrogen/pull/3331)) by [@frandiox](https://github.com/frandiox)
251
+
252
+ ```diff
253
+ // server.ts
254
+
255
+ +import * as serverBuild from 'virtual:react-router/server-build';
256
+
257
+ const handleRequest = createRequestHandler({
258
+ - build: await import('virtual:react-router/server-build'),
259
+ + build: serverBuild,
260
+ ```
261
+
262
+ Updated ESLint config to allow `virtual:` imports:
263
+
264
+ ```diff
265
+ // eslint.config.js
266
+
267
+ rules: {
268
+ + 'import/no-unresolved': ['error', {ignore: ['^virtual:']}],
269
+ ```
270
+
271
+ - Updated dependencies [[`264e13349168f17cc1f096c84135d13d38cfc8df`](https://github.com/Shopify/hydrogen/commit/264e13349168f17cc1f096c84135d13d38cfc8df), [`6d5e3d371e7e02e15be17029a0f34daae53a978e`](https://github.com/Shopify/hydrogen/commit/6d5e3d371e7e02e15be17029a0f34daae53a978e), [`ee00f1025867c40d5f67fa89d4ffb215bf280e8f`](https://github.com/Shopify/hydrogen/commit/ee00f1025867c40d5f67fa89d4ffb215bf280e8f), [`5a38948133766e358c5f357f52562f6fdcfe7969`](https://github.com/Shopify/hydrogen/commit/5a38948133766e358c5f357f52562f6fdcfe7969), [`264e13349168f17cc1f096c84135d13d38cfc8df`](https://github.com/Shopify/hydrogen/commit/264e13349168f17cc1f096c84135d13d38cfc8df)]:
272
+ - @shopify/hydrogen@2025.7.1
273
+
3
274
  ## 2025.7.0
4
275
 
5
276
  ### Major Changes
@@ -5,6 +5,7 @@ import {
5
5
  useEffect,
6
6
  useState,
7
7
  } from 'react';
8
+ import {useId} from 'react';
8
9
 
9
10
  type AsideType = 'search' | 'cart' | 'mobile' | 'closed';
10
11
  type AsideContextValue = {
@@ -34,7 +35,7 @@ export function Aside({
34
35
  }) {
35
36
  const {type: activeType, close} = useAside();
36
37
  const expanded = type === activeType;
37
-
38
+ const id = useId();
38
39
  useEffect(() => {
39
40
  const abortController = new AbortController();
40
41
 
@@ -57,11 +58,12 @@ export function Aside({
57
58
  aria-modal
58
59
  className={`overlay ${expanded ? 'expanded' : ''}`}
59
60
  role="dialog"
61
+ aria-labelledby={id}
60
62
  >
61
63
  <button className="close-outside" onClick={close} />
62
64
  <aside>
63
65
  <header>
64
- <h3>{heading}</h3>
66
+ <h3 id={id}>{heading}</h3>
65
67
  <button className="close reset" onClick={close} aria-label="Close">
66
68
  &times;
67
69
  </button>
@@ -1,69 +1,98 @@
1
1
  import type {CartLineUpdateInput} from '@shopify/hydrogen/storefront-api-types';
2
- import type {CartLayout} from '~/components/CartMain';
2
+ import type {CartLayout, LineItemChildrenMap} from '~/components/CartMain';
3
3
  import {CartForm, Image, type OptimisticCartLine} from '@shopify/hydrogen';
4
4
  import {useVariantUrl} from '~/lib/variants';
5
5
  import {Link} from 'react-router';
6
6
  import {ProductPrice} from './ProductPrice';
7
7
  import {useAside} from './Aside';
8
- import type {CartApiQueryFragment} from 'storefrontapi.generated';
8
+ import type {
9
+ CartApiQueryFragment,
10
+ CartLineFragment,
11
+ } from 'storefrontapi.generated';
9
12
 
10
- type CartLine = OptimisticCartLine<CartApiQueryFragment>;
13
+ export type CartLine = OptimisticCartLine<CartApiQueryFragment>;
11
14
 
12
15
  /**
13
16
  * A single line item in the cart. It displays the product image, title, price.
14
17
  * It also provides controls to update the quantity or remove the line item.
18
+ * If the line is a parent line that has child components (like warranties or gift wrapping), they are
19
+ * rendered nested below the parent line.
15
20
  */
16
21
  export function CartLineItem({
17
22
  layout,
18
23
  line,
24
+ childrenMap,
19
25
  }: {
20
26
  layout: CartLayout;
21
27
  line: CartLine;
28
+ childrenMap: LineItemChildrenMap;
22
29
  }) {
23
30
  const {id, merchandise} = line;
24
31
  const {product, title, image, selectedOptions} = merchandise;
25
32
  const lineItemUrl = useVariantUrl(product.handle, selectedOptions);
26
33
  const {close} = useAside();
34
+ const lineItemChildren = childrenMap[id];
35
+ const childrenLabelId = `cart-line-children-${id}`;
27
36
 
28
37
  return (
29
38
  <li key={id} className="cart-line">
30
- {image && (
31
- <Image
32
- alt={title}
33
- aspectRatio="1/1"
34
- data={image}
35
- height={100}
36
- loading="lazy"
37
- width={100}
38
- />
39
- )}
39
+ <div className="cart-line-inner">
40
+ {image && (
41
+ <Image
42
+ alt={title}
43
+ aspectRatio="1/1"
44
+ data={image}
45
+ height={100}
46
+ loading="lazy"
47
+ width={100}
48
+ />
49
+ )}
40
50
 
41
- <div>
42
- <Link
43
- prefetch="intent"
44
- to={lineItemUrl}
45
- onClick={() => {
46
- if (layout === 'aside') {
47
- close();
48
- }
49
- }}
50
- >
51
- <p>
52
- <strong>{product.title}</strong>
53
- </p>
54
- </Link>
55
- <ProductPrice price={line?.cost?.totalAmount} />
56
- <ul>
57
- {selectedOptions.map((option) => (
58
- <li key={option.name}>
59
- <small>
60
- {option.name}: {option.value}
61
- </small>
62
- </li>
63
- ))}
64
- </ul>
65
- <CartLineQuantity line={line} />
51
+ <div>
52
+ <Link
53
+ prefetch="intent"
54
+ to={lineItemUrl}
55
+ onClick={() => {
56
+ if (layout === 'aside') {
57
+ close();
58
+ }
59
+ }}
60
+ >
61
+ <p>
62
+ <strong>{product.title}</strong>
63
+ </p>
64
+ </Link>
65
+ <ProductPrice price={line?.cost?.totalAmount} />
66
+ <ul>
67
+ {selectedOptions.map((option) => (
68
+ <li key={option.name}>
69
+ <small>
70
+ {option.name}: {option.value}
71
+ </small>
72
+ </li>
73
+ ))}
74
+ </ul>
75
+ <CartLineQuantity line={line} />
76
+ </div>
66
77
  </div>
78
+
79
+ {lineItemChildren ? (
80
+ <div>
81
+ <p id={childrenLabelId} className="sr-only">
82
+ Line items with {product.title}
83
+ </p>
84
+ <ul aria-labelledby={childrenLabelId} className="cart-line-children">
85
+ {lineItemChildren.map((childLine) => (
86
+ <CartLineItem
87
+ childrenMap={childrenMap}
88
+ key={childLine.id}
89
+ line={childLine}
90
+ layout={layout}
91
+ />
92
+ ))}
93
+ </ul>
94
+ </div>
95
+ ) : null}
67
96
  </li>
68
97
  );
69
98
  }
@@ -2,7 +2,7 @@ import {useOptimisticCart} from '@shopify/hydrogen';
2
2
  import {Link} from 'react-router';
3
3
  import type {CartApiQueryFragment} from 'storefrontapi.generated';
4
4
  import {useAside} from '~/components/Aside';
5
- import {CartLineItem} from '~/components/CartLineItem';
5
+ import {CartLineItem, type CartLine} from '~/components/CartLineItem';
6
6
  import {CartSummary} from './CartSummary';
7
7
 
8
8
  export type CartLayout = 'page' | 'aside';
@@ -12,6 +12,26 @@ export type CartMainProps = {
12
12
  layout: CartLayout;
13
13
  };
14
14
 
15
+ export type LineItemChildrenMap = {[parentId: string]: CartLine[]};
16
+ /** Returns a map of all line items and their children. */
17
+ function getLineItemChildrenMap(lines: CartLine[]): LineItemChildrenMap {
18
+ const children: LineItemChildrenMap = {};
19
+ for (const line of lines) {
20
+ if ('parentRelationship' in line && line.parentRelationship?.parent) {
21
+ const parentId = line.parentRelationship.parent.id;
22
+ if (!children[parentId]) children[parentId] = [];
23
+ children[parentId].push(line);
24
+ }
25
+ if ('lineComponents' in line) {
26
+ const lineChildren = getLineItemChildrenMap(line.lineComponents);
27
+ for (const [parentId, childIds] of Object.entries(lineChildren)) {
28
+ if (!children[parentId]) children[parentId] = [];
29
+ children[parentId].push(...childIds);
30
+ }
31
+ }
32
+ }
33
+ return children;
34
+ }
15
35
  /**
16
36
  * The main cart component that displays the cart items and summary.
17
37
  * It is used by both the /cart route and the cart aside dialog.
@@ -27,21 +47,42 @@ export function CartMain({layout, cart: originalCart}: CartMainProps) {
27
47
  Boolean(cart?.discountCodes?.filter((code) => code.applicable)?.length);
28
48
  const className = `cart-main ${withDiscount ? 'with-discount' : ''}`;
29
49
  const cartHasItems = cart?.totalQuantity ? cart.totalQuantity > 0 : false;
50
+ const childrenMap = getLineItemChildrenMap(cart?.lines?.nodes ?? []);
30
51
 
31
52
  return (
32
- <div className={className}>
53
+ <section
54
+ className={className}
55
+ aria-label={layout === 'page' ? 'Cart page' : 'Cart drawer'}
56
+ >
33
57
  <CartEmpty hidden={linesCount} layout={layout} />
34
58
  <div className="cart-details">
35
- <div aria-labelledby="cart-lines">
36
- <ul>
37
- {(cart?.lines?.nodes ?? []).map((line) => (
38
- <CartLineItem key={line.id} line={line} layout={layout} />
39
- ))}
59
+ <p id="cart-lines" className="sr-only">
60
+ Line items
61
+ </p>
62
+ <div>
63
+ <ul aria-labelledby="cart-lines">
64
+ {(cart?.lines?.nodes ?? []).map((line) => {
65
+ // we do not render non-parent lines at the root of the cart
66
+ if (
67
+ 'parentRelationship' in line &&
68
+ line.parentRelationship?.parent
69
+ ) {
70
+ return null;
71
+ }
72
+ return (
73
+ <CartLineItem
74
+ key={line.id}
75
+ line={line}
76
+ layout={layout}
77
+ childrenMap={childrenMap}
78
+ />
79
+ );
80
+ })}
40
81
  </ul>
41
82
  </div>
42
83
  {cartHasItems && <CartSummary cart={cart} layout={layout} />}
43
84
  </div>
44
- </div>
85
+ </section>
45
86
  );
46
87
  }
47
88