Updates

See the latest product improvements, feature releases, and roadmap updates to our Hydrogen + Oxygen stack

May 21, 2025

May 2025 release

Welcome to our May release! In this release, we are bringing Hydrogen up to date with React Router 7.

Hydrogen now on React Router 7

With our May release, Hydrogen now uses React Router 7 as the foundation. Upgrading to Hydrogen 2025.05 will require upgrading your project to React Router 7. Going forward, all future Hydrogen versions will only support React Router 7.

Migrating to React Router 7 is a seamless transition but you must first enable all Remix Future Flags and run a codemod. Let’s get started! 

How to upgrade

Make sure you are on Hydrogen 2025.4.0 with all Remix Future Flags turned on! Make sure your storefront is running correctly and commit all changes before proceeding. Follow this document if you haven’t turned on your future flags yet: Hydrogen future flag migration for React Router 7

The next step is to run this codemod which will do most of the heavy lifting. In your terminal, run

Code Example

npx codemod remix/2/react-router/upgrade
– but don't worry, after the codemod, there are still more steps to do before your project will be ready.

Add react-router.config.ts file with these contents:

Code Example


import type {Config} from '@react-router/dev/config';

export default {
  appDirectory: 'app',
  buildDirectory: 'dist',
  ssr: true,
} satisfies Config;
  

In vite.config.ts delete all parameters of the reactRouter() plugin. These are just leftovers that the codemod did not clean up.

Code Example


// if you have declared this type augmentation, delete it
- declare module '@remix-run/server-runtime' {
-   interface Future {
-     v3_singleFetch: true;
-   }
- }

...
export default defineConfig({
  plugins: [
    tailwindcss(),
    hydrogen(),
    oxygen(),
-    reactRouter({
-      presets: [hydrogen.v3preset()],
-      future: {
-        v3_fetcherPersist: true,
-        v3_relativeSplatPath: true,
-        v3_throwAbortReason: true,
-        v3_lazyRouteDiscovery: true,
-        v3_routeConfig: true,
-        v3_singleFetch: true,
-      },
-    }),
+   reactRouter(),
    tsconfigPaths(),
  ],
...
  

Update the hydrogen dependencies to the 2025.5.0 version

Code Example


npm install --force \
@shopify/hydrogen@2025.5.0 \
@shopify/remix-oxygen@3.0.0 \
@shopify/cli@3.80.4
  

Change env.d.ts: the declare module should be aimed at react-router and you have to add LoaderFunctionArgs and ActionFunctionArgs (reference file here)

Code Example


    ...
- declare module '@shopify/remix-oxygen' {
+ declare module 'react-router' {
...
+  // TODO: remove this once we've migrated to `Route.LoaderArgs` for our loaders
+  interface LoaderFunctionArgs {
+    context: AppLoadContext;
+  }
+
+  // TODO: remove this once we've migrated to `Route.ActionArgs` for our actions
+  interface ActionFunctionArgs {
+    context: AppLoadContext;
+  }
...
}
  

Change tsconfig.json: add ".react-router/types/**/*" to include, and add "rootDirs": [".", "./.react-router/types"] reference file HERE

Code Example


    {
      "include": [
        "./**/*.d.ts",
        "./**/*.ts",
        "./**/*.tsx",
    +    ".react-router/types/**/*"
      ],
      "compilerOptions": {
    +    "rootDirs": [".", "./.react-router/types"],
        "lib": [
    ...
  

Add .react-router to the .gitignore file

Now try running npm run codegen and npm run typecheck and npm run dev.

That's it for now. See you in the next release!

May 21, 2025

How to Adopt All Future Flags

Future Flag Migration for React Router 7

Before upgrading to React Router 7, you need to make sure to adopt all Remix future flags. The CLI upgrade command (npx shopify hydrogen upgrade) provides guides on how to do this, but this guide consolidates all the steps.

First of all, the legacy classic Remix compiler is no longer supported, and you must upgrade to Vite if you haven't already. After running npx shopify hydrogen upgrade, run npx shopify hydrogen setup vite to migrate to Vite.

Next enable each of these future flags. It's easiest to do one at a time, making sure the app is functional after each step. At the end you should have all future flags enabled within the remix vite plugin:

Code Example


remix({
  presets: [hydrogen.v3preset()],
  future: {
    v3_fetcherPersist: true,
    v3_relativeSplatPath: true,
    v3_throwAbortReason: true,
    v3_lazyRouteDiscovery: true,
    v3_routeConfig: true,
    v3_singleFetch: true,
  },
})
  

v3_fetcherPersist

Enabling this flag is unlikely to affect your app. See the Remix docs for more information.

v3_relativeSplatPath

If you have any routes with a path + a splat like dashboard.$.tsx that have relative links like <Link to="relative"> or <Link to="../relative"> beneath it, you will need to update your code.

See the Remix docs for more information.

v3_throwAbortReason

When a server-side request is aborted, such as when a user navigates away from a page before the loader finishes, Remix will throw the request.signal.reason instead of an error like new Error("query() call aborted..."). Enabling this is unlikely to affect your app.

See the Remix docs for more information.

v3_lazyRouteDiscovery

Unlikely to affect your app. See the Remix docs for more information.

v3_singleFetch

Single Fetch is a new data loading strategy and streaming format. For more detailed upgrade instructions, see the v3_singleFetch PR or refer to the Remix guide.

  1. In your entry.server.tsx, add nonce to the <RemixServer>:

    Code Example

    
    const body = await renderToReadableStream(
      <NonceProvider>
        <RemixServer
          context={remixContext}
          url={request.url}
    +     nonce={nonce}
        />
      </NonceProvider>
    );
  2. Return plain objects from loaders and actions instead of using json or defer:

    Code Example

    
    // Before
    import {json} from "@shopify/remix-oxygen";
    
    export async function loader({}: LoaderFunctionArgs) {
      let tasks = await fetchTasks();
      return json(tasks);
    }
    
    // After
    export async function loader({}: LoaderFunctionArgs) {
      let tasks = await fetchTasks();
      return tasks;
    }
          

    Code Example

    
    // When setting headers
    import {data} from "@shopify/remix-oxygen";
    
    export async function loader({}: LoaderFunctionArgs) {
      let tasks = await fetchTasks();
      return data(tasks, {
        headers: {
          "Cache-Control": "public, max-age=604800"
        }
      });
    }
          

Update your shouldRevalidate in root.tsx:

Code Example


export const shouldRevalidate: ShouldRevalidateFunction = ({
 formMethod,
 currentUrl,
 nextUrl,
}) => {
  if (formMethod && formMethod !== 'GET') return true;
  if (currentUrl.toString() === nextUrl.toString()) return true;

  // Defaulting to no revalidation for root loader data to improve performance.
  // When using this feature, you risk your UI getting out of sync with your server.
  // Use with caution. If you are uncomfortable with this optimization, update the
  // line below to `return defaultShouldRevalidate` instead.
  // For more details see: https://remix.run/docs/en/main/route/should-revalidate
  return false;
};
  

v3_routeConfig

Config-based routing is the new default in React Router v7, configured via the routes.ts file. Support for routes.ts in Remix is a migration path toward React Router v7.

  1. Install the package: npm install -D @remix-run/route-config @remix-run/route-config
  2. Add a routes.ts file:

    Code Example

    
    import {flatRoutes} from '@remix-run/fs-routes';
    import {type RouteConfig} from '@remix-run/route-config';
    import {hydrogenRoutes} from '@shopify/hydrogen';
    
    export default hydrogenRoutes([
      ...(await flatRoutes()),
    ]) satisfies RouteConfig;
          

Update vite.config.js to use hydrogen.v3preset() and enable v3_routeConfig:

Code Example


export default defineConfig({
  plugins: [
    hydrogen(),
    oxygen(),
    remix({
      presets: [hydrogen.v3preset()],
      future: {
        v3_fetcherPersist: true,
        v3_relativeSplatPath: true,
        v3_throwAbortReason: true,
        v3_lazyRouteDiscovery: true,
        v3_singleFetch: true,
        v3_routeConfig: true,
      },
    }),
    tsconfigPaths(),
  ],
});
  

See the Remix docs for more information.

May 19, 2025

April 2025 release

Welcome to the April release! In this release, we bring fixes to internationalization, cart functionality, and template improvements. Let's dive into what's new.

Internationalization Improvements

Fixed duplicate content issues with internationalized product handles (#2821). Previously, translated product handles could create duplicate content at multiple URLs. For example:

https://hydrogen.shop/de-de/products/das-chaos
https://hydrogen.shop/de-de/products/the-havoc

The starter template now redirects to the localized URL, improving SEO and user experience.

Cart and Customer Account Enhancements

  • Fixed cart quantity validation (#2855)
  • Improved customer account logout handling (#2843)
    • Now clears all session data by default
    • Added keepSession option for custom data retention

Product Management Updates

  • Deprecated <VariantSelector /> (#2837)
    • We recommend using the getProductOptions utility instead.
    • Please refer to the implementation in our skeleton template, which has already made this transition
  • Refactored ProductItem into a separate component (#2872)

Cart Delivery Features

Added support for cart delivery address mutations (#2850):

  • cartDeliveryAddressesAdd
  • cartDeliveryAddressesRemove
  • cartDeliveryAddressesUpdate

Migration Notes

Upgrading from VariantSelector

When migrating from VariantSelector to getProductOptions:

  1. Update SFAPI product query with new fields:
    • encodedVariantExistence
    • encodedVariantAvailability
  1. Remove VARIANTS_QUERY from loadDeferredData
  2. Update Product component to use getAdjacentAndFirstAvailableVariants
  3. Implement URL parameter handling for variant selection

For more detailed instructions, please refer to the changelog.

To take advantage of all the latest features and improvements in Hydrogen, just run npx shopify hydrogen upgrade. That’s it for the April release!

March 31, 2025

March 2025 release

Welcome to our March release! In this release, we’ve added support for Vite 6 and the Remix v3_routeConfig future flag

Support for Vite 6

Hydrogen has completed the migration from Vite 5 to Vite 6, following the Remix upgrade to Vite 6 in version 2.16.0. Vite 6 offers performance enhancements and improved HMR (Hot Module Replacement). If you have any custom Vite integrations, please refer to vite migration guide for more information.

Turn on Remix future flag: v3_routeConfig

Remix is merging with React Router 7. Enabling v3_routeConfig future flag is the recommended migration path to React Router 7.

Update your vite.config.ts:

Code Example


   export default defineConfig({
  plugins: [
    hydrogen(),
    oxygen(),
    remix({
      presets: [hydrogen.v3preset()], // Update this to hydrogen.v3preset()
      future: {
        v3_fetcherPersist: true,
        v3_relativeSplatPath: true,
        v3_throwAbortReason: true,
        v3_lazyRouteDiscovery: true,
        v3_singleFetch: true,
        v3_routeConfig: true, // add this flag
      },
    }),
    tsconfigPaths(),
  ],

Update your package.json and install the new packages. Make sure to match the Remix version along with other Remix npm packages and ensure the versions are 2.16.1 or above:

Code Example

"devDependencies": {
 ...
 "@remix-run/fs-routes": "^2.16.1",
 "@remix-run/route-config": "^2.16.1",

Add a routes.ts file. This is your new Remix route configuration file.

Code Example


export default hydrogenRoutes([
  ...(await flatRoutes()),
  // Manual route definitions can be added to this array, in addition to or instead of using the `flatRoutes` file-based routing convention.
  // See https://remix.run/docs/en/main/guides/routing for more details
]) satisfies RouteConfig;

For more detailed upgrade instructions, see the v3_routeConfig PR or refer to the Remix guide.


To take advantage of all the latest features and improvements in Hydrogen, just run npx shopify hydrogen upgrade. That’s it for the March release — see you in April!

Get building

Spin up a new Hydrogen app in minutes.

See documentation