> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/getsentry/sentry-javascript/llms.txt
> Use this file to discover all available pages before exploring further.

# Remix Installation

> Install and configure the Sentry SDK for Remix applications

The `@sentry/remix` package provides comprehensive error tracking and performance monitoring for Remix applications, with support for both client and server environments.

## Prerequisites

* Node.js 18 or newer
* Remix 2.x
* React 18.x
* A Sentry account and project DSN

## Installation

<Steps>
  <Step title="Install the Package">
    Install `@sentry/remix` using your preferred package manager:

    <CodeGroup>
      ```bash npm theme={null}
      npm install @sentry/remix
      ```

      ```bash yarn theme={null}
      yarn add @sentry/remix
      ```

      ```bash pnpm theme={null}
      pnpm add @sentry/remix
      ```
    </CodeGroup>

    **Current Version:** 10.42.0
  </Step>

  <Step title="Initialize Client-Side">
    Create or update `app/entry.client.tsx`:

    ```typescript theme={null}
    import { useLocation, useMatches } from '@remix-run/react';
    import * as Sentry from '@sentry/remix';
    import { useEffect } from 'react';
    import { hydrateRoot } from 'react-dom/client';
    import { RemixBrowser } from '@remix-run/react';

    Sentry.init({
      dsn: 'YOUR_DSN_HERE',
      
      tracesSampleRate: 1.0,
      
      replaysSessionSampleRate: 0.1,
      replaysOnErrorSampleRate: 1.0,
      
      integrations: [
        Sentry.browserTracingIntegration({
          useEffect,
          useLocation,
          useMatches,
        }),
        Sentry.replayIntegration(),
      ],
    });

    hydrateRoot(document, <RemixBrowser />);
    ```
  </Step>

  <Step title="Initialize Server-Side">
    Create or update `app/entry.server.tsx`:

    ```typescript theme={null}
    import { PassThrough } from 'stream';
    import type { EntryContext } from '@remix-run/node';
    import { Response } from '@remix-run/node';
    import { RemixServer } from '@remix-run/react';
    import { renderToPipeableStream } from 'react-dom/server';
    import * as Sentry from '@sentry/remix';

    Sentry.init({
      dsn: 'YOUR_DSN_HERE',
      tracesSampleRate: 1.0,
    });

    export default function handleRequest(
      request: Request,
      responseStatusCode: number,
      responseHeaders: Headers,
      remixContext: EntryContext
    ) {
      return new Promise((resolve, reject) => {
        const { pipe, abort } = renderToPipeableStream(
          <RemixServer context={remixContext} url={request.url} />,
          {
            onShellReady: () => {
              const body = new PassThrough();
              responseHeaders.set('Content-Type', 'text/html');
              
              resolve(
                new Response(body as any, {
                  headers: responseHeaders,
                  status: responseStatusCode,
                })
              );
              
              pipe(body);
            },
            onShellError: (error: unknown) => {
              reject(error);
            },
            onError: (error: unknown) => {
              responseStatusCode = 500;
              Sentry.captureException(error);
            },
          }
        );
        
        setTimeout(abort, 5000);
      });
    }
    ```
  </Step>

  <Step title="Wrap Root Component">
    Wrap your root component with `withSentry` in `app/root.tsx`:

    ```typescript theme={null}
    import {
      Links,
      LiveReload,
      Meta,
      Outlet,
      Scripts,
      ScrollRestoration,
    } from '@remix-run/react';
    import { withSentry } from '@sentry/remix';

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

    export default withSentry(App);
    ```
  </Step>

  <Step title="Verify Installation">
    Create a test route to verify Sentry is working:

    ```typescript theme={null}
    // app/routes/sentry-test.tsx
    import * as Sentry from '@sentry/remix';

    export default function SentryTest() {
      return (
        <button
          onClick={() => {
            Sentry.captureException(new Error('Test error'));
          }}
        >
          Trigger Test Error
        </button>
      );
    }
    ```

    Visit the route and click the button. Check your Sentry dashboard to see the error.
  </Step>
</Steps>

## Loaders and Actions

### Loader Functions

Errors in loaders are automatically captured:

```typescript theme={null}
// app/routes/users.$id.tsx
import type { LoaderFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
import * as Sentry from '@sentry/remix';

export async function loader({ params }: LoaderFunctionArgs) {
  try {
    const user = await fetchUser(params.id);
    return json({ user });
  } catch (error) {
    Sentry.captureException(error);
    throw new Response('User not found', { status: 404 });
  }
}
```

### Action Functions

```typescript theme={null}
// app/routes/contact.tsx
import type { ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
import * as Sentry from '@sentry/remix';

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const email = formData.get('email');
  
  try {
    await sendEmail(email);
    return json({ success: true });
  } catch (error) {
    Sentry.captureException(error);
    return json({ success: false, error: 'Failed to send email' }, { status: 500 });
  }
}
```

## Error Boundaries

Create custom error boundaries with Sentry integration:

```typescript theme={null}
// app/routes/_index.tsx
import { useRouteError, isRouteErrorResponse } from '@remix-run/react';
import * as Sentry from '@sentry/remix';
import { useEffect } from 'react';

export function ErrorBoundary() {
  const error = useRouteError();
  
  useEffect(() => {
    if (!isRouteErrorResponse(error)) {
      Sentry.captureException(error);
    }
  }, [error]);
  
  if (isRouteErrorResponse(error)) {
    return (
      <div>
        <h1>{error.status} {error.statusText}</h1>
        <p>{error.data}</p>
      </div>
    );
  }
  
  return (
    <div>
      <h1>Error</h1>
      <p>Something went wrong</p>
    </div>
  );
}
```

## Performance Monitoring

### Automatic Instrumentation

The SDK automatically creates spans for:

* Page loads and navigation
* Loaders and actions
* Server requests
* Database queries (with integrations)

### Custom Spans

```typescript theme={null}
import * as Sentry from '@sentry/remix';
import type { LoaderFunctionArgs } from '@remix-run/node';

export async function loader({ params }: LoaderFunctionArgs) {
  const data = await Sentry.startSpan(
    { name: 'fetch-user-data', op: 'db.query' },
    async () => {
      return await db.user.findUnique({
        where: { id: params.id },
      });
    }
  );
  
  return json({ data });
}
```

## Database Integrations

### Prisma

```typescript theme={null}
// app/entry.server.tsx
import * as Sentry from '@sentry/remix';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  integrations: [
    Sentry.prismaIntegration(),
  ],
  tracesSampleRate: 1.0,
});
```

Then use Prisma normally:

```typescript theme={null}
import { prisma } from '~/db.server';

export async function loader() {
  // Prisma queries are automatically instrumented
  const users = await prisma.user.findMany();
  return json({ users });
}
```

### MongoDB

```typescript theme={null}
// app/entry.server.tsx
import * as Sentry from '@sentry/remix';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  integrations: [
    Sentry.mongoIntegration(),
  ],
  tracesSampleRate: 1.0,
});
```

## Setting Context

### User Context

```typescript theme={null}
// app/root.tsx
import { useLoaderData } from '@remix-run/react';
import * as Sentry from '@sentry/remix';
import { useEffect } from 'react';

export default function App() {
  const { user } = useLoaderData<typeof loader>();
  
  useEffect(() => {
    if (user) {
      Sentry.setUser({
        id: user.id,
        email: user.email,
        username: user.username,
      });
    } else {
      Sentry.setUser(null);
    }
  }, [user]);
  
  return (
    // ... rest of your app
  );
}
```

### Tags and Extra Context

```typescript theme={null}
import * as Sentry from '@sentry/remix';

// Set tags
Sentry.setTag('route', location.pathname);
Sentry.setTag('user_tier', 'premium');

// Set extra context
Sentry.setExtra('api_version', 'v2');
Sentry.setContext('request', {
  method: request.method,
  url: request.url,
});
```

### Breadcrumbs

```typescript theme={null}
import * as Sentry from '@sentry/remix';

Sentry.addBreadcrumb({
  category: 'action',
  message: 'User submitted form',
  level: 'info',
  data: {
    formId: 'contact-form',
  },
});
```

## Session Replay

Configure Session Replay in your client entry:

```typescript theme={null}
// app/entry.client.tsx
import * as Sentry from '@sentry/remix';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  integrations: [
    Sentry.replayIntegration({
      maskAllText: true,
      blockAllMedia: true,
      maskAllInputs: true,
    }),
  ],
  
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
});
```

## Source Maps

Sentry provides a CLI tool for uploading source maps:

### Using the Upload Script

1. Build your app with source maps:
   ```bash theme={null}
   remix build --sourcemap
   ```

2. Upload source maps:
   ```bash theme={null}
   npx sentry-upload-sourcemaps \
     --org your-org \
     --project your-project \
     --auth-token YOUR_AUTH_TOKEN \
     --release VERSION
   ```

### Automated with package.json

```json theme={null}
{
  "scripts": {
    "build": "remix build --sourcemap",
    "postbuild": "sentry-upload-sourcemaps --org your-org --project your-project"
  }
}
```

### Using Sentry CLI Directly

For more control, use [`sentry-cli`](https://github.com/getsentry/sentry-cli) directly:

```bash theme={null}
sentry-cli releases new VERSION
sentry-cli releases files VERSION upload-sourcemaps ./build
sentry-cli releases finalize VERSION
```

## Cloudflare Workers

For Cloudflare Workers deployment:

```typescript theme={null}
// app/entry.server.tsx
import * as Sentry from '@sentry/remix/cloudflare';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  tracesSampleRate: 1.0,
});
```

Import from `@sentry/remix/cloudflare` instead of `@sentry/remix` for edge runtime support.

## Advanced Configuration

### Sampling

```typescript theme={null}
Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  tracesSampler: (samplingContext) => {
    // Don't sample health checks
    if (samplingContext.request?.url?.includes('/health')) {
      return 0;
    }
    
    // Sample API routes at 50%
    if (samplingContext.request?.url?.includes('/api')) {
      return 0.5;
    }
    
    return 0.1;
  },
});
```

### Environment Detection

```typescript theme={null}
Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  environment: process.env.NODE_ENV,
  enabled: process.env.NODE_ENV === 'production',
});
```

### Custom Transport

```typescript theme={null}
import { makeFetchTransport } from '@sentry/remix';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  transport: makeFetchTransport,
});
```

## Troubleshooting

### Errors Not Captured

1. Ensure both `entry.client.tsx` and `entry.server.tsx` are configured
2. Check that `withSentry` wraps your root component
3. Verify DSN is correct in both client and server configs

### Source Maps Not Working

1. Ensure you're building with `--sourcemap` flag
2. Check that source maps are being uploaded correctly
3. Verify release version matches between build and upload

### Performance Data Missing

1. Ensure `tracesSampleRate` is greater than 0
2. Check that integrations are configured properly
3. Verify Sentry is initialized before app runs

<Warning>
  Make sure to call `Sentry.init()` in both `entry.client.tsx` and `entry.server.tsx` with appropriate configurations for each environment.
</Warning>

## Next Steps

* Configure [Error Boundaries](/essentials/error-boundaries)
* Set up [Session Replay](/essentials/session-replay)
* Learn about [Performance Monitoring](/essentials/performance-monitoring)
* Explore [Database Integrations](/essentials/database-integrations)

## Related Documentation

* [Official Remix SDK Docs](https://docs.sentry.io/platforms/javascript/guides/remix/)
* [Sentry Remix Package on npm](https://www.npmjs.com/package/@sentry/remix)
* [Source Code on GitHub](https://github.com/getsentry/sentry-javascript/tree/master/packages/remix)
