diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 2180ddbf3b9b..79f2ad9e595e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1014,6 +1014,7 @@ jobs:
'react-router-6-use-routes',
'react-router-5',
'react-router-6',
+ 'solidjs',
'svelte-5',
'sveltekit',
'sveltekit-2',
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/.gitignore b/dev-packages/e2e-tests/test-applications/solidjs/.gitignore
new file mode 100644
index 000000000000..84634c973eeb
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/.gitignore
@@ -0,0 +1,29 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+/test-results/
+/playwright-report/
+/playwright/.cache/
+
+!*.d.ts
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/.npmrc b/dev-packages/e2e-tests/test-applications/solidjs/.npmrc
new file mode 100644
index 000000000000..070f80f05092
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/.npmrc
@@ -0,0 +1,2 @@
+@sentry:registry=http://127.0.0.1:4873
+@sentry-internal:registry=http://127.0.0.1:4873
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/README.md b/dev-packages/e2e-tests/test-applications/solidjs/README.md
new file mode 100644
index 000000000000..81e5eb6c2d40
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/README.md
@@ -0,0 +1,40 @@
+## Usage
+
+Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.
+
+This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely
+be removed once you clone a template.
+
+```bash
+$ npm install # or pnpm install or yarn install
+```
+
+## Exploring the template
+
+This template's goal is to showcase the routing features of Solid. It also showcase how the router and Suspense work
+together to parallelize data fetching tied to a route via the `.data.ts` pattern.
+
+You can learn more about it on the [`@solidjs/router` repository](https://github.com/solidjs/solid-router)
+
+### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
+
+## Available Scripts
+
+In the project directory, you can run:
+
+### `npm run dev` or `npm start`
+
+Runs the app in the development mode. Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+
+The page will reload if you make edits.
+
+### `npm run build`
+
+Builds the app for production to the `dist` folder. It correctly bundles Solid in production mode and optimizes the
+build for the best performance.
+
+The build is minified and the filenames include the hashes. Your app is ready to be deployed!
+
+## Deployment
+
+You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/index.html b/dev-packages/e2e-tests/test-applications/solidjs/index.html
new file mode 100644
index 000000000000..1905a0429019
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ Solid App
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
+
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/package.json b/dev-packages/e2e-tests/test-applications/solidjs/package.json
new file mode 100644
index 000000000000..1922a6e26d17
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "solidjs",
+ "version": "0.0.0",
+ "description": "",
+ "scripts": {
+ "build": "vite build",
+ "clean": "npx rimraf node_modules pnpm-lock.yaml dist",
+ "dev": "vite",
+ "preview": "vite preview",
+ "start": "vite",
+ "test:prod": "TEST_ENV=production playwright test",
+ "test:build": "pnpm install && npx playwright install && pnpm build",
+ "test:assert": "pnpm test:prod"
+ },
+ "license": "MIT",
+ "devDependencies": {
+ "@playwright/test": "^1.44.1",
+ "@sentry-internal/test-utils": "link:../../../test-utils",
+ "@sentry/types": "latest || *",
+ "@sentry/utils": "latest || *",
+ "autoprefixer": "^10.4.17",
+ "postcss": "^8.4.33",
+ "solid-devtools": "^0.29.2",
+ "tailwindcss": "^3.4.1",
+ "vite": "^5.0.11",
+ "vite-plugin-solid": "^2.8.2"
+ },
+ "dependencies": {
+ "@solidjs/router": "^0.13.5",
+ "solid-js": "^1.8.11",
+ "@sentry/solidjs": "latest || *"
+ }
+}
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/solidjs/playwright.config.mjs
new file mode 100644
index 000000000000..0c468af7d879
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/playwright.config.mjs
@@ -0,0 +1,8 @@
+import { getPlaywrightConfig } from '@sentry-internal/test-utils';
+
+const config = getPlaywrightConfig({
+ startCommand: 'pnpm preview --port 3030',
+ port: 3030,
+});
+
+export default config;
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/postcss.config.js b/dev-packages/e2e-tests/test-applications/solidjs/postcss.config.js
new file mode 100644
index 000000000000..12a703d900da
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/errors/404.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/errors/404.tsx
new file mode 100644
index 000000000000..56e5ad5e3be0
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/src/errors/404.tsx
@@ -0,0 +1,8 @@
+export default function NotFound() {
+ return (
+
+ 404: Not Found
+ It's gone 😞
+
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/index.css b/dev-packages/e2e-tests/test-applications/solidjs/src/index.css
new file mode 100644
index 000000000000..b5c61c956711
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/src/index.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/index.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/index.tsx
new file mode 100644
index 000000000000..47e7c0e52904
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/src/index.tsx
@@ -0,0 +1,21 @@
+/* @refresh reload */
+import * as Sentry from '@sentry/solidjs';
+import { Router, useBeforeLeave, useLocation } from '@solidjs/router';
+import { render } from 'solid-js/web';
+import './index.css';
+import PageRoot from './pageroot';
+import { routes } from './routes';
+
+Sentry.init({
+ dsn: import.meta.env.PUBLIC_E2E_TEST_DSN,
+ debug: true,
+ environment: 'qa', // dynamic sampling bias to keep transactions
+ integrations: [Sentry.solidRouterBrowserTracingIntegration({ useBeforeLeave, useLocation })],
+ release: 'e2e-test',
+ tunnel: 'http://localhost:3031/', // proxy server
+ tracesSampleRate: 1.0,
+});
+
+const SentryRouter = Sentry.withSentryRouterRouting(Router);
+
+render(() => {routes} , document.getElementById('root'));
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/pageroot.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/pageroot.tsx
new file mode 100644
index 000000000000..d9770c8a3868
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/src/pageroot.tsx
@@ -0,0 +1,23 @@
+import { A } from '@solidjs/router';
+
+export default function PageRoot(props) {
+ return (
+ <>
+
+
+
+ {props.children}
+ >
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/pages/home.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/home.tsx
new file mode 100644
index 000000000000..7500846f0555
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/home.tsx
@@ -0,0 +1,39 @@
+import { A } from '@solidjs/router';
+import { createSignal } from 'solid-js';
+
+export default function Home() {
+ const [count, setCount] = createSignal(0);
+
+ return (
+
+ Home
+ This is the home page.
+
+
+ setCount(count() - 1)}>
+ -
+
+
+ Count: {count()}
+
+ setCount(count() + 1)}>
+ +
+
+
+
+
{
+ throw new Error('Error thrown from SolidJS E2E test app');
+ }}
+ >
+ Throw error
+
+
+ User 5
+
+
+
+ );
+}
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/pages/user.tsx b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/user.tsx
new file mode 100644
index 000000000000..639ab0be8118
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/src/pages/user.tsx
@@ -0,0 +1,6 @@
+import { useParams } from '@solidjs/router';
+
+export default function User() {
+ const params = useParams();
+ return User ID: {params.id}
;
+}
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/src/routes.ts b/dev-packages/e2e-tests/test-applications/solidjs/src/routes.ts
new file mode 100644
index 000000000000..7b115f68c00c
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/src/routes.ts
@@ -0,0 +1,18 @@
+import { lazy } from 'solid-js';
+
+import Home from './pages/home';
+
+export const routes = [
+ {
+ path: '/',
+ component: Home,
+ },
+ {
+ path: '/user/:id',
+ component: lazy(() => import('./pages/user')),
+ },
+ {
+ path: '**',
+ component: lazy(() => import('./errors/404')),
+ },
+];
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/solidjs/start-event-proxy.mjs
new file mode 100644
index 000000000000..207afe3f56e1
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/start-event-proxy.mjs
@@ -0,0 +1,6 @@
+import { startEventProxyServer } from '@sentry-internal/test-utils';
+
+startEventProxyServer({
+ port: 3031,
+ proxyServerName: 'solidjs',
+});
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tailwind.config.ts b/dev-packages/e2e-tests/test-applications/solidjs/tailwind.config.ts
new file mode 100644
index 000000000000..f69a95185570
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/tailwind.config.ts
@@ -0,0 +1,11 @@
+import type { Config } from 'tailwindcss';
+
+const config: Config = {
+ content: ['./src/**/*.{js,jsx,ts,tsx}'],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};
+
+export default config;
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/solidjs/tests/errors.test.ts
new file mode 100644
index 000000000000..92618f628407
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/tests/errors.test.ts
@@ -0,0 +1,28 @@
+import { expect, test } from '@playwright/test';
+import { waitForError } from '@sentry-internal/test-utils';
+
+test('sends an error', async ({ page }) => {
+ const errorPromise = waitForError('solidjs', async errorEvent => {
+ return !errorEvent.type;
+ });
+
+ await Promise.all([page.goto(`/`), page.locator('#errorBtn').click()]);
+
+ const error = await errorPromise;
+
+ expect(error).toMatchObject({
+ exception: {
+ values: [
+ {
+ type: 'Error',
+ value: 'Error thrown from SolidJS E2E test app',
+ mechanism: {
+ type: 'onerror',
+ handled: false,
+ },
+ },
+ ],
+ },
+ transaction: '/',
+ });
+});
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/solidjs/tests/performance.test.ts
new file mode 100644
index 000000000000..166dfe01d32b
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/tests/performance.test.ts
@@ -0,0 +1,91 @@
+import { expect, test } from '@playwright/test';
+import { waitForTransaction } from '@sentry-internal/test-utils';
+
+test('sends a pageload transaction', async ({ page }) => {
+ const transactionPromise = waitForTransaction('solidjs', async transactionEvent => {
+ return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
+ });
+
+ const [, pageloadTransaction] = await Promise.all([page.goto('/'), transactionPromise]);
+
+ expect(pageloadTransaction).toMatchObject({
+ contexts: {
+ trace: {
+ op: 'pageload',
+ origin: 'auto.pageload.browser',
+ },
+ },
+ transaction: '/',
+ transaction_info: {
+ source: 'url',
+ },
+ });
+});
+
+test('sends a navigation transaction', async ({ page }) => {
+ const transactionPromise = waitForTransaction('solidjs', async transactionEvent => {
+ return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation';
+ });
+
+ await page.goto(`/`);
+
+ const [, navigationTransaction] = await Promise.all([page.locator('#navLink').click(), transactionPromise]);
+
+ expect(navigationTransaction).toMatchObject({
+ contexts: {
+ trace: {
+ op: 'navigation',
+ origin: 'auto.navigation.solidjs.solidrouter',
+ },
+ },
+ transaction: '/user/5',
+ transaction_info: {
+ source: 'url',
+ },
+ });
+});
+
+test('updates the transaction when using the back button', async ({ page }) => {
+ // Solid Router sends a `-1` navigation when using the back button.
+ // The sentry solidRouterBrowserTracingIntegration tries to update such
+ // transactions with the proper name once the `useLocation` hook triggers.
+ const navigationTxnPromise = waitForTransaction('solidjs', async transactionEvent => {
+ return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation';
+ });
+
+ await page.goto(`/`);
+
+ const [, navigationTxn] = await Promise.all([page.locator('#navLink').click(), navigationTxnPromise]);
+
+ expect(navigationTxn).toMatchObject({
+ contexts: {
+ trace: {
+ op: 'navigation',
+ origin: 'auto.navigation.solidjs.solidrouter',
+ },
+ },
+ transaction: '/user/5',
+ transaction_info: {
+ source: 'url',
+ },
+ });
+
+ const backNavigationTxnPromise = waitForTransaction('solidjs', async transactionEvent => {
+ return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation';
+ });
+
+ const [, backNavigationTxn] = await Promise.all([page.goBack(), backNavigationTxnPromise]);
+
+ expect(backNavigationTxn).toMatchObject({
+ contexts: {
+ trace: {
+ op: 'navigation',
+ origin: 'auto.navigation.solidjs.solidrouter',
+ },
+ },
+ transaction: '/',
+ transaction_info: {
+ source: 'url',
+ },
+ });
+});
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/tsconfig.json b/dev-packages/e2e-tests/test-applications/solidjs/tsconfig.json
new file mode 100644
index 000000000000..ba12e96f069a
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "node",
+ "allowSyntheticDefaultImports": true,
+ "esModuleInterop": true,
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js",
+ "types": ["vite/client"],
+ "noEmit": true,
+ "isolatedModules": true,
+ },
+}
diff --git a/dev-packages/e2e-tests/test-applications/solidjs/vite.config.ts b/dev-packages/e2e-tests/test-applications/solidjs/vite.config.ts
new file mode 100644
index 000000000000..d1835ee1b8ff
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/solidjs/vite.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vite';
+import solidPlugin from 'vite-plugin-solid';
+
+export default defineConfig({
+ plugins: [solidPlugin()],
+ build: {
+ target: 'esnext',
+ },
+ envPrefix: 'PUBLIC_',
+});