diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index cbc80ec59f33..56f61126a45a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -815,6 +815,7 @@ jobs:
'create-react-app',
'create-next-app',
'create-remix-app',
+ 'create-remix-app-v2',
'nextjs-app-dir',
'react-create-hash-router',
'react-router-6-use-routes',
diff --git a/packages/e2e-tests/test-applications/create-remix-app-v2/.eslintrc.js b/packages/e2e-tests/test-applications/create-remix-app-v2/.eslintrc.js
new file mode 100644
index 000000000000..f2faf1470fd8
--- /dev/null
+++ b/packages/e2e-tests/test-applications/create-remix-app-v2/.eslintrc.js
@@ -0,0 +1,4 @@
+/** @type {import('eslint').Linter.Config} */
+module.exports = {
+ extends: ['@remix-run/eslint-config', '@remix-run/eslint-config/node'],
+};
diff --git a/packages/e2e-tests/test-applications/create-remix-app-v2/.gitignore b/packages/e2e-tests/test-applications/create-remix-app-v2/.gitignore
new file mode 100644
index 000000000000..3f7bf98da3e1
--- /dev/null
+++ b/packages/e2e-tests/test-applications/create-remix-app-v2/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+
+/.cache
+/build
+/public/build
+.env
diff --git a/packages/e2e-tests/test-applications/create-remix-app-v2/.npmrc b/packages/e2e-tests/test-applications/create-remix-app-v2/.npmrc
new file mode 100644
index 000000000000..c6b3ef9b3eaa
--- /dev/null
+++ b/packages/e2e-tests/test-applications/create-remix-app-v2/.npmrc
@@ -0,0 +1,2 @@
+@sentry:registry=http://localhost:4873
+@sentry-internal:registry=http://localhost:4873
diff --git a/packages/e2e-tests/test-applications/create-remix-app-v2/README.md b/packages/e2e-tests/test-applications/create-remix-app-v2/README.md
new file mode 100644
index 000000000000..54336d746713
--- /dev/null
+++ b/packages/e2e-tests/test-applications/create-remix-app-v2/README.md
@@ -0,0 +1,61 @@
+# Welcome to Remix!
+
+- [Remix Docs](https://remix.run/docs)
+
+## Development
+
+From your terminal:
+
+```sh
+npm run dev
+```
+
+This starts your app in development mode, rebuilding assets on file changes.
+
+## Deployment
+
+First, build your app for production:
+
+```sh
+npm run build
+```
+
+Then run the app in production mode:
+
+```sh
+npm start
+```
+
+Now you'll need to pick a host to deploy it to.
+
+### DIY
+
+If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
+
+Make sure to deploy the output of `remix build`
+
+- `build/`
+- `public/build/`
+
+### Using a Template
+
+When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new
+project, then copy over relevant code/assets from your current app to the new project that's pre-configured for your
+target server.
+
+Most importantly, this means everything in the `app/` directory, but if you've further customized your current
+application outside of there it may also include:
+
+- Any assets you've added/updated in `public/`
+- Any updated versions of root files such as `.eslintrc.js`, etc.
+
+```sh
+cd ..
+# create a new project, and pick a pre-configured host
+npx create-remix@latest
+cd my-new-remix-app
+# remove the new project's app (not the old one!)
+rm -rf app
+# copy your app over
+cp -R ../my-old-remix-app/app app
+```
diff --git a/packages/e2e-tests/test-applications/create-remix-app-v2/app/entry.client.tsx b/packages/e2e-tests/test-applications/create-remix-app-v2/app/entry.client.tsx
new file mode 100644
index 000000000000..605d8e792d23
--- /dev/null
+++ b/packages/e2e-tests/test-applications/create-remix-app-v2/app/entry.client.tsx
@@ -0,0 +1,49 @@
+/**
+ * By default, Remix will handle hydrating your app on the client for you.
+ * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
+ * For more information, see https://remix.run/file-conventions/entry.client
+ */
+
+import { RemixBrowser, useLocation, useMatches } from '@remix-run/react';
+import { startTransition, StrictMode, useEffect } from 'react';
+import { hydrateRoot } from 'react-dom/client';
+import * as Sentry from '@sentry/remix';
+
+Sentry.init({
+ dsn: window.ENV.SENTRY_DSN,
+ integrations: [
+ new Sentry.BrowserTracing({
+ routingInstrumentation: Sentry.remixRouterInstrumentation(useEffect, useLocation, useMatches),
+ }),
+ new Sentry.Replay(),
+ ],
+ // Performance Monitoring
+ tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
+ // Session Replay
+ replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
+ replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
+});
+
+Sentry.addGlobalEventProcessor(event => {
+ if (
+ event.type === 'transaction' &&
+ (event.contexts?.trace?.op === 'pageload' || event.contexts?.trace?.op === 'navigation')
+ ) {
+ const eventId = event.event_id;
+ if (eventId) {
+ window.recordedTransactions = window.recordedTransactions || [];
+ window.recordedTransactions.push(eventId);
+ }
+ }
+
+ return event;
+});
+
+startTransition(() => {
+ hydrateRoot(
+ document,
+
, R extends React.FC errorBoundaryOptions?: ErrorBoundaryProps; } = { // We don't want to wrap application with Sentry's ErrorBoundary by default for Remix v2 - wrapWithErrorBoundary: getFutureFlagsBrowser()?.v2_errorBoundary ? false : true, + wrapWithErrorBoundary: true, errorBoundaryOptions: {}, }, ): R { @@ -154,17 +158,16 @@ export function withSentry
, R extends React.FC
isBaseLocation = false;
+ if (!isRemixV2(readRemixVersionFromLoader()) && options.wrapWithErrorBoundary) {
+ // @ts-expect-error Setting more specific React Component typing for `R` generic above
+ // will break advanced type inference done by react router params
+ return withErrorBoundary(OrigApp, options.errorBoundaryOptions)(props);
+ }
// @ts-expect-error Setting more specific React Component typing for `R` generic above
// will break advanced type inference done by react router params
return