---
title: "Remix on Cloudflare"
description: "Learn how to instrument your Remix app on Cloudflare Workers and Pages and capture your first errors with Sentry."
url: https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix/
---

# Remix on Cloudflare | Sentry for Cloudflare

## [Prerequisites](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#prerequisites)

You need:

* A Sentry [account](https://sentry.io/signup/) and [project](https://docs.sentry.io/product/projects.md)
* Your application up and running
* Remix version `2.0.0`+

## [Install](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#install)

Choose the features you want to configure, and this guide will show you how:

Error Monitoring\[ ]Tracing\[ ]Session Replay\[ ]Logs\[ ]User Feedback

Want to learn more about these features?

* [**Issues**](https://docs.sentry.io/product/issues.md) (always enabled)
  <!-- -->
  :
  <!-- -->
  Sentry's core error monitoring product that automatically reports errors, uncaught exceptions, and unhandled rejections. If you have something that looks like an exception, Sentry can capture it.
* [**Tracing**](https://docs.sentry.io/product/tracing.md):
  <!-- -->
  Track software performance while seeing the impact of errors across multiple systems. For example, distributed tracing allows you to follow a request from the frontend to the backend and back.
* [**Session Replay**](https://docs.sentry.io/product/explore/session-replay/web.md):
  <!-- -->
  Get to the root cause of an issue faster by viewing a video-like reproduction of what was happening in the user's browser before, during, and after the problem.
* [**Logs**](https://docs.sentry.io/product/explore/logs.md):
  <!-- -->
  Centralize and analyze your application logs to correlate them with errors and performance issues. Search, filter, and visualize log data to understand what's happening in your applications.
* [**User Feedback**](https://docs.sentry.io/product/user-feedback.md):
  <!-- -->
  Collect feedback directly from users when they encounter errors, allowing them to describe what happened and provide context that helps you understand and resolve issues faster.

### [Install the Sentry SDK](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#install-the-sentry-sdk)

Run the command for your preferred package manager to add the Sentry SDK to your application:

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

## [Configure](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#configure)

### [Configure Client-Side Sentry](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#configure-client-side-sentry)

Create a client file `entry.client.tsx` in the `app` folder of your project if you don't have one already. In this file, import and initialize the Sentry SDK:

`entry.client.tsx`

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

Sentry.init({
  dsn: "___PUBLIC_DSN___",

  // Adds request headers and IP for users, for more info visit:
  // https://docs.sentry.io/platforms/javascript/guides/remix/configuration/options/#sendDefaultPii
  sendDefaultPii: true,

  integrations: [
    // ___PRODUCT_OPTION_START___ performance
    Sentry.browserTracingIntegration({
      useEffect,
      useLocation,
      useMatches,
    }),
    // ___PRODUCT_OPTION_END___ performance
    // ___PRODUCT_OPTION_START___ session-replay
    // Replay is only available in the client
    Sentry.replayIntegration(),
    // ___PRODUCT_OPTION_END___ session-replay
    // ___PRODUCT_OPTION_START___ user-feedback
    Sentry.feedbackIntegration({
      // Additional SDK configuration goes in here, for example:
      colorScheme: "system",
    }),
    // ___PRODUCT_OPTION_END___ user-feedback
  ],
  // ___PRODUCT_OPTION_START___ performance

  // 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/],
  // ___PRODUCT_OPTION_END___ performance
  // ___PRODUCT_OPTION_START___ session-replay

  // 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,
  // ___PRODUCT_OPTION_END___ session-replay
  // ___PRODUCT_OPTION_START___ logs

  // Enable logs to be sent to Sentry
  enableLogs: true,
  // ___PRODUCT_OPTION_END___ logs
});
```

#### [Remix ErrorBoundary](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#remix-errorboundary)

To capture errors from your [ErrorBoundary](https://remix.run/docs/en/main/route/error-boundary), define it in `root.tsx` to act as a fallback for all routes or create route-specific error boundaries in your route components.

In your `ErrorBoundary` component, use `Sentry.captureRemixErrorBoundaryError` to send the captured error to Sentry:

`root.tsx`

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

export const ErrorBoundary = () => {
  const error = useRouteError();

  captureRemixErrorBoundaryError(error);

  return <div> ... </div>;
};
```

#### [Performance Monitoring](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#performance-monitoring)

Wrap your Remix root component with `withSentry` to capture performance data:

`root.tsx`

```tsx
import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

import { withSentry } from "@sentry/remix";

function App() {
  return (
    <html>
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

export default withSentry(App);
```

### [Configure Server-Side Sentry](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#configure-server-side-sentry)

Create a `_middleware.js` file in your [`functions` directory](https://developers.cloudflare.com/pages/functions/) (Cloudflare Pages [middleware](https://developers.cloudflare.com/pages/functions/middleware/)). Create the directory in the root of your project if it doesn't already exist, then create the file and import and initialize the Sentry Cloudflare SDK:

`functions/_middleware.js`

```javascript
import * as Sentry from "@sentry/cloudflare";

export const onRequest = [
  // Make sure Sentry is the first middleware
  Sentry.sentryPagesPlugin((context) => ({
    dsn: "___PUBLIC_DSN___",

    // Adds request headers and IP for users, for more info visit: and captures action formData attributes
    // https://docs.sentry.io/platforms/javascript/guides/remix/configuration/options/#sendDefaultPii
    sendDefaultPii: true,
    // ___PRODUCT_OPTION_START___ performance

    // 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,
    // ___PRODUCT_OPTION_END___ performance
    // ___PRODUCT_OPTION_START___ logs

    // Enable logs to be sent to Sentry
    enableLogs: true,
    // ___PRODUCT_OPTION_END___ logs

    // Optionally capture action formData attributes with errors.
    // This requires `sendDefaultPii` set to true as well.
    captureActionFormDataKeys: {
      key_x: true,
      key_y: true,
    },
  })),
  // Add more middlewares here
];
```

### [Capture Server-Side Errors](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#capture-server-side-errors)

To automatically capture server-side errors, instrument the [`handleError`](https://remix.run/docs/en/main/file-conventions/entry.server#handleerror) function in your server entry point (`entry.server.tsx`). You can wrap your custom error handler with `wrapHandleErrorWithSentry` or directly use `sentryHandleError`:

##### Tip

Sentry's Remix SDK automatically records your [`action`](https://remix.run/docs/en/main/route/action) and [`loader`](https://remix.run/docs/en/main/route/loader) transactions for performance monitoring. You can also initialize Sentry's database integrations, such as [Prisma](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/prisma.md), to get spans for your database calls.

`entry.server.tsx`

```typescript
import * as Sentry from "@sentry/remix";

export const handleError = Sentry.wrapHandleErrorWithSentry(
  (error, { request }) => {
    // Custom handleError implementation
  },
);

// Alternative: Use the Sentry utility function if you don't need to wrap a custom function
export const handleError = Sentry.sentryHandleError;
```

### [Configure Cloudflare for Sentry](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#configure-cloudflare-for-sentry)

Since the SDK needs access to the `AsyncLocalStorage` API, you need to set the `nodejs_compat` compatibility flag in your `wrangler.(jsonc|toml)` configuration file:

`wrangler.jsonc`

```jsonc
{
  "compatibility_flags": ["nodejs_compat"],
}
```

### [Release Configuration (Optional)](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#release-configuration-optional)

If you don't set the `release` option manually, the SDK automatically detects it from these sources (in order of priority):

1. The `SENTRY_RELEASE` environment variable
2. The `CF_VERSION_METADATA.id` binding (if configured)

To enable automatic release detection via Cloudflare's version metadata, add the `CF_VERSION_METADATA` binding in your wrangler configuration. This provides access to the [Cloudflare version metadata](https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/).

`wrangler.jsonc`

```jsonc
{
  // ...
  "version_metadata": {
    "binding": "CF_VERSION_METADATA",
  },
}
```

Using an SDK version before 10.35.0?

In earlier versions, you need to manually extract `CF_VERSION_METADATA.id` and pass it as the `release` option:

```javascript
Sentry.withSentry(
  (env) => ({
    dsn: "___PUBLIC_DSN___",
    release: env.CF_VERSION_METADATA?.id,
  }),
  // ...
);
```

### [Add Readable Stack Traces With Source Maps (Optional)](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#add-readable-stack-traces-with-source-maps-optional)

To upload source maps for clear error stack traces, add your Sentry auth token, organization, and project slug in your `vite.config.ts` file:

##### Not using Vite?

Check our [Source Maps documentation](https://docs.sentry.io/platforms/javascript/guides/remix/sourcemaps.md) for alternative setup options.

`vite.config.ts`

```javascript
import { defineConfig } from "vite";
import { vitePlugin as remix } from "@remix-run/dev";

import { sentryVitePlugin } from "@sentry/vite-plugin";


export default defineConfig({
  plugins: [
    remix({
      // ... your Remix plugin options
    }),

    sentryVitePlugin({
      // If you use .sentryclirc or environment variables,
      // you don't need to specify these options
      org: "___ORG_SLUG___",
      project: "___PROJECT_SLUG___",
      // store your auth token in an environment variable
      authToken: process.env.SENTRY_AUTH_TOKEN,
    }),

  ],


  build: {
    sourcemap: "hidden",
    // ... rest of your Vite build options
  },

});
```

To keep your auth token secure, always store it in an environment variable instead of directly in your files:

`.env`

```bash
SENTRY_AUTH_TOKEN=___ORG_AUTH_TOKEN___
```

Using environment variables in Vite configs

Vite doesn't automatically load `.env` files into `process.env` when evaluating the config file. If you store your auth token in a `.env` file and want to access it via `process.env.SENTRY_AUTH_TOKEN`, use Vite's [`loadEnv`](https://vite.dev/guide/api-javascript#loadenv) helper.

Alternatively, use a `.env.sentry-build-plugin` file, which the Sentry plugin reads automatically.

`vite.config.js`

```javascript
import { defineConfig, loadEnv } from "vite";

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), "");

  return {
    plugins: [
      sentryVitePlugin({
        authToken: env.SENTRY_AUTH_TOKEN,
        // ...
      }),
    ],
  };
});
```

## [Verify Your Setup](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#verify-your-setup)

Let's test your setup and confirm that Sentry is working correctly and sending data to your Sentry project.

### [Issues](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#issues)

##### Important

Errors triggered from within your browser's developer tools (like the browser console) are sandboxed, so they will not trigger Sentry's error monitoring.

To verify that Sentry captures errors and creates issues in your Sentry project, add a test button to one of your pages.

Open the page in a browser and click the button to trigger a frontend error.

```javascript
<button
  type="button"
  onClick={() => {
    throw new Error("Sentry Example Frontend Error");
  }}
>
  <span>Throw Sample Error</span>
</button>;
```

### [Tracing](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#tracing)

To test your tracing configuration, update the previous code snippet by calling a non-existing route and starting a trace to measure the time it takes for the execution of your code.

Open the page in a browser and click the button to trigger the frontend error and a trace.

```javascript
<button
  type="button"
  onClick={async () => {
    await Sentry.startSpan(
      {
        name: "Example Frontend Span",
        op: "test",
      },
      async () => {
        const res = await fetch("/api/sentry-example-api");
        if (!res.ok) {
          throw new Error("Sentry Example Frontend Error");
        }
      },
    );
  }}
>
  <span>Throw Sample Error</span>
</button>;
```

### [Logs NEW](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#logs-)

To verify that Sentry catches your logs, add some log statements to your application:

```javascript
Sentry.logger.info("User example action completed");

Sentry.logger.warn("Slow operation detected", {
  operation: "data_fetch",
  duration: 3500,
});

Sentry.logger.error("Validation failed", {
  field: "email",
  reason: "Invalid email",
});
```

### [View Captured Data in Sentry](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#view-captured-data-in-sentry)

Now, head over to your project on [Sentry.io](https://sentry.io) to view the collected data (it takes a couple of moments for the data to appear).

Need help locating the captured errors in your Sentry project?

* Open the
  <!-- -->
  [**Issues**](https://sentry.io/orgredirect/organizations/:orgslug/issues/)
  <!-- -->
  page and select an error from the issues list to view the full details and context of this error. For more details, see this
  <!-- -->
  [interactive walkthrough](https://docs.sentry.io/product/sentry-basics/integrate-frontend/generate-first-error.md#ui-walkthrough).
* Open the
  <!-- -->
  [**Traces**](https://sentry.io/orgredirect/organizations/:orgslug/explore/traces/)
  <!-- -->
  page and select a trace to reveal more information about each span, its duration, and any errors. For an interactive UI walkthrough, click
  <!-- -->
  [here](https://docs.sentry.io/product/sentry-basics/distributed-tracing/generate-first-error.md#ui-walkthrough).
* Open the
  <!-- -->
  [**Replays**](https://sentry.io/orgredirect/organizations/:orgslug/replays/)
  <!-- -->
  page and select an entry from the list to get a detailed view where you can replay the interaction and get more information to help you troubleshoot.
* Open the
  <!-- -->
  [**Logs**](https://sentry.io/orgredirect/organizations/:orgslug/explore/logs/)
  <!-- -->
  page and filter by service, environment, or search keywords to view log entries from your application. For an interactive UI walkthrough, click
  <!-- -->
  [here](https://docs.sentry.io/product/explore/logs.md#overview).
* Open the
  <!-- -->
  [**User Feedback**](https://sentry.io/orgredirect/organizations/:orgslug/feedback/)
  <!-- -->
  page and click on individual feedback to see more details all in one view. For more information, click [here](https://docs.sentry.io/product/user-feedback.md).

## [Next Steps](https://docs.sentry.io/platforms/javascript/guides/cloudflare/frameworks/remix.md#next-steps)

At this point, you should have integrated Sentry into your Remix application and should already be sending error and performance data to your Sentry project.

Now's a good time to customize your setup and look into more advanced topics. Our next recommended steps for you are:

* Explore [practical guides](https://docs.sentry.io/guides.md) on what to monitor, log, track, and investigate after setup
* Learn how to [manually capture errors](https://docs.sentry.io/platforms/javascript/guides/cloudflare/usage.md)
* Continue to [customize your configuration](https://docs.sentry.io/platforms/javascript/guides/cloudflare/configuration.md)
* Get familiar with [Sentry's product features](https://docs.sentry.io/product.md) like tracing, insights, and alerts

Are you having problems setting up the SDK?

* If you encountered issues with the manual setup, try [our installation wizard](https://docs.sentry.io/platforms/javascript/guides/cloudflare.md)
* Find various support topics in [Cloudflare troubleshooting](https://docs.sentry.io/platforms/javascript/guides/cloudflare/troubleshooting.md) and [Remix troubleshooting](https://docs.sentry.io/platforms/javascript/guides/remix/troubleshooting.md)
* [Get support](https://sentry.zendesk.com/hc/en-us/)
