---
title: "Hydrogen with Remix (Legacy)"
description: "Learn how to use the Sentry Remix SDK to instrument your Hydrogen app (versions before 2025.5.0)."
url: https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/hydrogen-remix/
---

# Hydrogen with Remix (Legacy) | Sentry for Cloudflare

##### Hydrogen Version

This guide applies to Hydrogen versions **before 2025.5.0** that use Remix v2. For newer versions of Hydrogen (2025.5.0+) that use React Router 7, see the [React Router guide](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/hydrogen-react-router.md).

If you're using Shopify's Hydrogen framework with Remix v2, you can use the Sentry Remix SDK to add Sentry instrumentation to your app.

## [Installing Sentry Remix and Cloudflare SDKs](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/hydrogen-remix.md#installing-sentry-remix-and-cloudflare-sdks)

First, install the Sentry Remix and Cloudflare SDKs with your package manager:

```bash
npm install @sentry/remix @sentry/cloudflare --save
```

## [Instrumenting Your Server](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/hydrogen-remix.md#instrumenting-your-server)

Update your `server.ts` file to use the `wrapRequestHandler` method from `@sentry/cloudflare/request` and `instrumentBuild` from `@sentry/remix/cloudflare`:

`server.ts`

```ts
import { wrapRequestHandler } from "@sentry/cloudflare/request";
import { instrumentBuild } from "@sentry/remix/cloudflare";
import { createRequestHandler } from "@remix-run/cloudflare";
// Virtual entry point for the app
import * as remixBuild from "virtual:remix/server-build";

/**
 * Export a fetch handler in module format.
 */
export default {
  async fetch(
    request: Request,
    env: Env,
    executionContext: ExecutionContext
  ): Promise<Response> {
    return wrapRequestHandler(
      {
        options: {
          dsn: "YOUR_DSN_HERE",
          tracesSampleRate: 1.0,
        },
        // Need to cast to any because this is not on cloudflare
        request: request as any,
        context: executionContext,
      },
      async () => {
        // Instrument your server build with Sentry
        // and use the instrumented build inside the fetch handler
        const instrumentedBuild = instrumentBuild(remixBuild);

        const handleRequest = createRequestHandler({
          build: instrumentedBuild,
          mode: process.env.NODE_ENV,
          getLoadContext: (): AppLoadContext => ({
            // your load context
          }),
        });

        return handleRequest(request);
      }
    );
  },
};
```

## [Instrumenting Your Client](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/hydrogen-remix.md#instrumenting-your-client)

Wrap your Remix root component using `withSentry`:

`app/root.tsx`

```tsx
import * as Sentry from "@sentry/remix/cloudflare";
import { useEffect } from "react";
import { useLocation, useMatches } from "@remix-run/react";

function App() {
  return (
    // Your app content
  );
}

// Pass `useEffect`, `useLocation` and `useMatches` hooks to `withSentry`
export default Sentry.withSentry(App, useEffect, useLocation, useMatches);
```

Finally, update your `entry.client.tsx` file to initialize Sentry SDK on the client:

`app/entry.client.tsx`

```tsx
import * as Sentry from "@sentry/remix/cloudflare";
import { useEffect } from "react";
import { useLocation, useMatches } from "@remix-run/react";

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    Sentry.browserTracingIntegration({
      useEffect,
      useLocation,
      useMatches,
    }),
    // Replay is only available in the client
    Sentry.replayIntegration(),
  ],

  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // We recommend adjusting this value in production
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
  tracesSampleRate: 1.0,

  // Set `tracePropagationTargets` to control for which URLs distributed tracing should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],

  // Capture Replay for 10% of all sessions,
  // plus for 100% of sessions with an error
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/session-replay/configuration/#general-integration-configuration
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
});
```

## [Trace Propagation](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/hydrogen-remix.md#trace-propagation)

Available since: `v10.45.0`

Because Hydrogen uses a custom `entry.server.tsx` that bypasses the default Remix document request handler, the SDK cannot automatically inject trace propagation headers. To connect server-side traces with client-side `pageload` spans, you need to manually add the `Server-Timing` header using `generateSentryServerTimingHeader()`.

Update your `entry.server.tsx` to generate and append the header to your response:

`app/entry.server.tsx`

```tsx
import { generateSentryServerTimingHeader } from "@sentry/remix/cloudflare";


export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext,
) {
  // ...

  const response = new Response(body, {
    headers: responseHeaders,
    status: responseStatusCode,
  });

  const serverTimingValue = generateSentryServerTimingHeader();
  if (serverTimingValue) {

    response.headers.append("Server-Timing", serverTimingValue);
  }

  return response;

}
```

The browser SDK automatically reads the `Server-Timing` header via the [Performance API](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API) and uses it to connect the client-side `pageload` span with the server-side transaction. No additional client-side configuration is needed beyond having `browserTracingIntegration` configured.
