diff --git a/.gitignore b/.gitignore
index eb58d44..8f611c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -134,3 +134,6 @@ dist
 
 # Mac
 .DS_Store
+
+# Yalc
+.yalc
diff --git a/apps/express/package.json b/apps/express/package.json
index 78c1de7..8b3ee9b 100644
--- a/apps/express/package.json
+++ b/apps/express/package.json
@@ -15,7 +15,7 @@
     "extends": "../../package.json"
   },
   "dependencies": {
-    "@sentry/node": "^7.109.0",
+    "@sentry/node": "^8.0.0-beta.1",
     "express": "^4.19.2"
   },
   "devDependencies": {
diff --git a/apps/express/src/app.ts b/apps/express/src/app.ts
index 90a5575..03cdbcc 100644
--- a/apps/express/src/app.ts
+++ b/apps/express/src/app.ts
@@ -1,4 +1,15 @@
 import * as Sentry from '@sentry/node';
+
+Sentry.init({
+  environment: 'qa', // dynamic sampling bias to keep transactions
+  dsn: process.env.E2E_TEST_DSN,
+  includeLocalVariables: true,
+  debug: true,
+  tunnel: `http://localhost:3031/`, // proxy server
+  tracesSampleRate: 1,
+});
+
+// can use `import` instead of `require` because of `'esModuleInterop': true` in tsconfig.json
 import express from 'express';
 
 declare global {
@@ -10,19 +21,6 @@ declare global {
 const app = express();
 const port = 3030;
 
-Sentry.init({
-  environment: 'qa', // dynamic sampling bias to keep transactions
-  dsn: process.env.E2E_TEST_DSN,
-  includeLocalVariables: true,
-  debug: true,
-  tunnel: `http://127.0.0.1:3031/`, // proxy server
-  tracesSampleRate: 1,
-  integrations: [new Sentry.Integrations.Express({ app })],
-});
-
-app.use(Sentry.Handlers.requestHandler());
-app.use(Sentry.Handlers.tracingHandler());
-
 app.get('/test-success', function (req, res) {
   res.send({ version: 'v1' });
 });
@@ -91,7 +89,7 @@ app.get('/test-local-variables-caught', function (req, res) {
   res.send({ exceptionId, randomVariableToRecord });
 });
 
-app.use(Sentry.Handlers.errorHandler());
+Sentry.setupExpressErrorHandler(app);
 
 // @ts-ignore
 app.use(function onError(err, req, res, next) {
diff --git a/apps/fastify/package.json b/apps/fastify/package.json
new file mode 100644
index 0000000..c90bd72
--- /dev/null
+++ b/apps/fastify/package.json
@@ -0,0 +1,20 @@
+{
+  "name": "fastify-test-application",
+  "version": "1.0.0",
+  "directories": {
+    "lib": "lib"
+  },
+  "scripts": {
+    "build": "tsc",
+    "start": "yarn build && node dist/app.js",
+    "clean": "npx rimraf node_modules,pnpm-lock.yaml"
+  },
+  "license": "MIT",
+  "volta": {
+    "extends": "../../package.json"
+  },
+  "dependencies": {
+    "@sentry/node": "8.0.0-beta.1",
+    "fastify": "4.26.2"
+  }
+}
diff --git a/apps/fastify/src/app.ts b/apps/fastify/src/app.ts
new file mode 100644
index 0000000..95ecfe1
--- /dev/null
+++ b/apps/fastify/src/app.ts
@@ -0,0 +1,94 @@
+import * as Sentry from '@sentry/node';
+
+Sentry.init({
+  environment: 'qa', // dynamic sampling bias to keep transactions
+  dsn: process.env.E2E_TEST_DSN,
+  includeLocalVariables: true,
+  integrations: [],
+  tracesSampleRate: 1,
+  tunnel: 'http://localhost:3031/', // proxy server
+});
+
+import { fastify } from 'fastify';
+
+declare global {
+  namespace globalThis {
+    var transactionIds: string[];
+  }
+}
+
+// Make sure fastify is imported after Sentry is initialized
+const app = fastify();
+
+// @ts-ignore
+Sentry.setupFastifyErrorHandler(app);
+
+app.get('/test-success', function (_req, res) {
+  res.send({ version: 'v1' });
+});
+
+app.get('/test-error', async function (req, res) {
+  const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+  await Sentry.flush(2000);
+
+  res.send({ exceptionId });
+});
+
+app.get<{ Params: { param: string } }>('/test-param-success/:param', function (req, res) {
+  res.send({ paramWas: req.params.param });
+});
+
+app.get<{ Params: { param: string } }>('/test-param-error/:param', async function (req, res) {
+  const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+  await Sentry.flush(2000);
+
+  res.send({ exceptionId, paramWas: req.params.param });
+});
+
+app.get('/test-success-manual', async function (req, res) {
+  Sentry.startSpan({ name: 'test-span' }, () => {
+    Sentry.startSpan({ name: 'child-span' }, () => {});
+  });
+
+  await Sentry.flush();
+
+  res.send({
+    transactionIds: global.transactionIds || [],
+  });
+});
+
+app.get('/test-error-manual', async function (req, res) {
+  Sentry.startSpan({ name: 'test-span' }, () => {
+    Sentry.startSpan({ name: 'child-span' }, () => {
+      Sentry.captureException(new Error('This is an error'));
+    });
+  });
+
+  await Sentry.flush(2000);
+
+  res.send({
+    transactionIds: global.transactionIds || [],
+  });
+});
+
+app.get('/test-local-variables-uncaught', function (req, res) {
+  const randomVariableToRecord = 'LOCAL_VARIABLE';
+  throw new Error(`Uncaught Local Variable Error - ${JSON.stringify({ randomVariableToRecord })}`);
+});
+
+app.get('/test-local-variables-caught', function (req, res) {
+  const randomVariableToRecord = 'LOCAL_VARIABLE';
+
+  let exceptionId: string;
+  try {
+    throw new Error('Local Variable Error');
+  } catch (e) {
+    exceptionId = Sentry.captureException(e);
+  }
+
+  res.send({ exceptionId, randomVariableToRecord });
+});
+
+app.listen({ port: 3030 });
diff --git a/apps/fastify/tsconfig.json b/apps/fastify/tsconfig.json
new file mode 100644
index 0000000..899a860
--- /dev/null
+++ b/apps/fastify/tsconfig.json
@@ -0,0 +1,7 @@
+{
+  "extends": "../../tsconfig.json",
+  "include": ["src/**/*.ts"],
+  "compilerOptions": {
+    "outDir": "dist"
+  }
+}
diff --git a/apps/koa/package.json b/apps/koa/package.json
new file mode 100644
index 0000000..1408943
--- /dev/null
+++ b/apps/koa/package.json
@@ -0,0 +1,26 @@
+{
+  "name": "koa-test-application",
+  "version": "1.0.0",
+  "main": "dist/main.js",
+  "directories": {
+    "lib": "lib"
+  },
+  "scripts": {
+    "build": "tsc",
+    "start": "yarn build && node dist/app.js",
+    "clean": "npx rimraf node_modules,pnpm-lock.yaml"
+  },
+  "license": "MIT",
+  "volta": {
+    "extends": "../../package.json"
+  },
+  "dependencies": {
+    "@koa/router": "12.0.1",
+    "@sentry/node": "8.0.0-beta.1",
+    "koa": "2.15.3"
+  },
+  "devDependencies": {
+    "@types/koa": "2.15.0",
+    "@types/koa__router": "12.0.4"
+  }
+}
diff --git a/apps/koa/src/app.ts b/apps/koa/src/app.ts
new file mode 100644
index 0000000..fc76322
--- /dev/null
+++ b/apps/koa/src/app.ts
@@ -0,0 +1,106 @@
+import * as Sentry from '@sentry/node';
+
+Sentry.init({
+  environment: 'qa', // dynamic sampling bias to keep transactions
+  dsn: process.env.E2E_TEST_DSN,
+  includeLocalVariables: true,
+  debug: true,
+  tunnel: `http://localhost:3031/`, // proxy server
+  tracesSampleRate: 1,
+});
+
+import Koa from 'koa';
+import Router from '@koa/router';
+import { stripUrlQueryAndFragment } from '@sentry/utils';
+
+declare global {
+  namespace globalThis {
+    var transactionIds: string[];
+  }
+}
+
+const router = new Router();
+const app = new Koa();
+
+router.get('/test-success', ctx => {
+  ctx.body = { version: 'v1' };
+});
+
+router.get('/test-error', async ctx => {
+  const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+  Sentry.flush(2000);
+
+  ctx.body = { exceptionId };
+});
+
+router.get('/test-param-success/:param', ctx => {
+  ctx.body = { paramWas: ctx.params.param };
+});
+
+router.get('/test-param-error/:param', async ctx => {
+  const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+  Sentry.flush(2000);
+
+  ctx.body = { exceptionId, paramWas: ctx.params.param };
+});
+
+router.get('/test-success-manual', async ctx => {
+  Sentry.startSpan({ name: 'test-transaction', op: 'e2e-test' }, () => {
+    Sentry.startSpan({ name: 'test-span' }, () => undefined);
+  });
+
+  Sentry.flush();
+
+  ctx.body = {
+    transactionIds: global.transactionIds || [],
+  };
+});
+
+router.get('/test-error-manual', async ctx => {
+  Sentry.startSpan({ name: 'test-transaction', op: 'e2e-test' }, () => {
+    Sentry.startSpan({ name: 'test-span' }, () => {
+      Sentry.captureException(new Error('This is an error'));
+    });
+  });
+
+  Sentry.flush();
+
+  ctx.body = {
+    transactionIds: global.transactionIds || [],
+  };
+});
+
+router.get('/test-local-variables-uncaught', ctx => {
+  const randomVariableToRecord = 'LOCAL VARIABLE';
+  throw new Error(`Uncaught Local Variable Error - ${JSON.stringify({ randomVariableToRecord })}`);
+});
+
+router.get('/test-local-variables-caught', ctx => {
+  const randomVariableToRecord = 'LOCAL VARIABLE';
+
+  let exceptionId: string;
+  try {
+    throw new Error('Local Variable Error');
+  } catch (e) {
+    exceptionId = Sentry.captureException(e);
+  }
+
+  ctx.body = { exceptionId, randomVariableToRecord };
+});
+
+Sentry.setupKoaErrorHandler(app);
+
+app.on('error', (err, ctx) => {
+  console.log('error', err);
+
+  ctx.body({
+    error: err.message,
+    status: ctx.status,
+  });
+});
+
+app.use(router.routes()).use(router.allowedMethods());
+
+app.listen(3030);
diff --git a/apps/koa/tsconfig.json b/apps/koa/tsconfig.json
new file mode 100644
index 0000000..899a860
--- /dev/null
+++ b/apps/koa/tsconfig.json
@@ -0,0 +1,7 @@
+{
+  "extends": "../../tsconfig.json",
+  "include": ["src/**/*.ts"],
+  "compilerOptions": {
+    "outDir": "dist"
+  }
+}
diff --git a/apps/nestjs/nest-cli.json b/apps/nestjs/nest-cli.json
new file mode 100644
index 0000000..f9aa683
--- /dev/null
+++ b/apps/nestjs/nest-cli.json
@@ -0,0 +1,8 @@
+{
+  "$schema": "https://json.schemastore.org/nest-cli",
+  "collection": "@nestjs/schematics",
+  "sourceRoot": "src",
+  "compilerOptions": {
+    "deleteOutDir": true
+  }
+}
diff --git a/apps/nestjs/package.json b/apps/nestjs/package.json
new file mode 100644
index 0000000..cab98bd
--- /dev/null
+++ b/apps/nestjs/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "nestjs-test-application",
+  "version": "1.0.0",
+  "main": "dist/main.js",
+  "directories": {
+    "lib": "lib"
+  },
+  "scripts": {
+    "build": "nest build",
+    "start": "nest start",
+    "clean": "npx rimraf node_modules,pnpm-lock.yaml"
+  },
+  "license": "MIT",
+  "volta": {
+    "extends": "../../package.json"
+  },
+  "dependencies": {
+    "@nestjs/common": "10.3.7",
+    "@nestjs/core": "10.3.7",
+    "@nestjs/platform-express": "10.3.7",
+    "@sentry/node": "8.0.0-beta.1",
+    "@sentry/types": "8.0.0-beta.1",
+    "reflect-metadata": "0.2.2",
+    "rxjs": "7.8.1"
+  },
+  "devDependencies": {
+    "@nestjs/cli": "10.3.2",
+    "@nestjs/schematics": "10.1.1",
+    "@types/express": "^4.17.17"
+  }
+}
diff --git a/apps/nestjs/src/app.controller.ts b/apps/nestjs/src/app.controller.ts
new file mode 100644
index 0000000..6ea42e2
--- /dev/null
+++ b/apps/nestjs/src/app.controller.ts
@@ -0,0 +1,47 @@
+import { Controller, Get, Param } from '@nestjs/common';
+import { AppService } from './app.service';
+
+@Controller()
+export class AppController {
+  constructor(private readonly appService: AppService) {}
+
+  @Get('test-success')
+  testSuccess() {
+    return this.appService.testSuccess();
+  }
+
+  @Get('test-error')
+  testError() {
+    return this.appService.testError();
+  }
+
+  @Get('test-param-success/:param')
+  testParamSuccess(@Param() param: string) {
+    return this.appService.testParamSuccess(param);
+  }
+
+  @Get('test-param-error/:param')
+  testParamError(@Param() param: string) {
+    return this.appService.testParamError(param);
+  }
+
+  @Get('test-success-manual')
+  testSuccessManual() {
+    return this.appService.testSuccessManual();
+  }
+
+  @Get('test-error-manual')
+  testErrorManual() {
+    return this.appService.testErrorManual();
+  }
+
+  @Get('test-local-variables-uncaught')
+  testLocalVariablesUncaught() {
+    return this.appService.testLocalVariablesUncaught();
+  }
+
+  @Get('test-local-variables-caught')
+  testLocalVariablesCaught() {
+    return this.appService.testLocalVariablesCaught();
+  }
+}
diff --git a/apps/nestjs/src/app.module.ts b/apps/nestjs/src/app.module.ts
new file mode 100644
index 0000000..8662803
--- /dev/null
+++ b/apps/nestjs/src/app.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+
+@Module({
+  imports: [],
+  controllers: [AppController],
+  providers: [AppService],
+})
+export class AppModule {}
diff --git a/apps/nestjs/src/app.service.ts b/apps/nestjs/src/app.service.ts
new file mode 100644
index 0000000..cf55432
--- /dev/null
+++ b/apps/nestjs/src/app.service.ts
@@ -0,0 +1,71 @@
+import { Injectable } from '@nestjs/common';
+import * as Sentry from '@sentry/node';
+
+@Injectable()
+export class AppService {
+  testSuccess() {
+    return { version: 'v1' };
+  }
+
+  async testError() {
+    const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+    await Sentry.flush(2000);
+
+    return { exceptionId };
+  }
+
+  testParamSuccess(param: string) {
+    return { paramWas: param };
+  }
+
+  async testParamError(param: string) {
+    const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+    await Sentry.flush(2000);
+
+    return { exceptionId, paramWas: param };
+  }
+
+  async testSuccessManual() {
+    Sentry.startSpan({ name: 'test-transaction', op: 'e2e-test' }, () => {
+      Sentry.startSpan({ name: 'test-span' }, () => undefined);
+    });
+
+    await Sentry.flush();
+
+    return 'test-success-body';
+  }
+
+  async testErrorManual() {
+    Sentry.startSpan({ name: 'test-transaction', op: 'e2e-test' }, () => {
+      Sentry.startSpan({ name: 'test-span' }, () => {
+        Sentry.captureException(new Error('This is an error'));
+      });
+    });
+
+    await Sentry.flush();
+
+    return 'test-error-body';
+  }
+
+  testLocalVariablesUncaught() {
+    const randomVariableToRecord = 'LOCAL_VARIABLE';
+    throw new Error(
+      `Uncaught Local Variable Error - ${JSON.stringify({ randomVariableToRecord })}`,
+    );
+  }
+
+  testLocalVariablesCaught() {
+    const randomVariableToRecord = 'LOCAL_VARIABLE';
+
+    let exceptionId: string;
+    try {
+      throw new Error('Local Variable Error');
+    } catch (e) {
+      exceptionId = Sentry.captureException(e);
+    }
+
+    return { exceptionId, randomVariableToRecord };
+  }
+}
diff --git a/apps/nestjs/src/main.ts b/apps/nestjs/src/main.ts
new file mode 100644
index 0000000..2ca5b83
--- /dev/null
+++ b/apps/nestjs/src/main.ts
@@ -0,0 +1,19 @@
+import { NestFactory } from '@nestjs/core';
+import * as Sentry from '@sentry/node';
+import { AppModule } from './app.module';
+
+async function bootstrap() {
+  Sentry.init({
+    environment: 'qa', // dynamic sampling bias to keep transactions
+    dsn: process.env.E2E_TEST_DSN,
+    tunnel: `http://localhost:3031/`, // proxy server
+    tracesSampleRate: 1,
+  });
+
+  const app = await NestFactory.create(AppModule);
+  Sentry.setupNestErrorHandler(app);
+
+  await app.listen(3030);
+}
+
+bootstrap();
diff --git a/apps/nestjs/tsconfig.json b/apps/nestjs/tsconfig.json
new file mode 100644
index 0000000..f182c40
--- /dev/null
+++ b/apps/nestjs/tsconfig.json
@@ -0,0 +1,9 @@
+{
+  "extends": "../../tsconfig.json",
+  "include": ["src/**/*.ts"],
+  "compilerOptions": {
+    "outDir": "dist",
+    "emitDecoratorMetadata": true,
+    "experimentalDecorators": true
+  }
+}
diff --git a/apps/nextjs-14_2_1/.gitignore b/apps/nextjs-14_2_1/.gitignore
new file mode 100644
index 0000000..fd3dbb5
--- /dev/null
+++ b/apps/nextjs-14_2_1/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/apps/nextjs-14_2_1/app/api/test-error-manual/route.ts b/apps/nextjs-14_2_1/app/api/test-error-manual/route.ts
new file mode 100644
index 0000000..fd7fa0d
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-error-manual/route.ts
@@ -0,0 +1,13 @@
+import * as Sentry from '@sentry/nextjs';
+
+export async function GET() {
+  Sentry.startSpan({ name: 'test-span' }, () => {
+    Sentry.startSpan({ name: 'child-span' }, () => {
+      Sentry.captureException(new Error('This is an error'));
+    });
+  });
+
+  await Sentry.flush();
+
+  return Response.json({ data: 'test-error-body' });
+}
diff --git a/apps/nextjs-14_2_1/app/api/test-error/route.ts b/apps/nextjs-14_2_1/app/api/test-error/route.ts
new file mode 100644
index 0000000..29c5216
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-error/route.ts
@@ -0,0 +1,8 @@
+import * as Sentry from '@sentry/nextjs';
+
+export async function GET() {
+  const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+  await Sentry.flush(2000);
+  return Response.json({ exceptionId });
+}
diff --git a/apps/nextjs-14_2_1/app/api/test-local-variables-caught/route.ts b/apps/nextjs-14_2_1/app/api/test-local-variables-caught/route.ts
new file mode 100644
index 0000000..7b26d27
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-local-variables-caught/route.ts
@@ -0,0 +1,14 @@
+import * as Sentry from '@sentry/nextjs';
+
+export async function GET() {
+  const randomVariableToRecord = 'LOCAL_VARIABLE';
+
+  let exceptionId: string;
+  try {
+    throw new Error('Local Variable Error');
+  } catch (e) {
+    exceptionId = Sentry.captureException(e);
+  }
+
+  return Response.json({ exceptionId, randomVariableToRecord });
+}
diff --git a/apps/nextjs-14_2_1/app/api/test-local-variables-uncaught/route.ts b/apps/nextjs-14_2_1/app/api/test-local-variables-uncaught/route.ts
new file mode 100644
index 0000000..3b1a1ca
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-local-variables-uncaught/route.ts
@@ -0,0 +1,4 @@
+export async function GET() {
+  const randomVariableToRecord = 'LOCAL_VARIABLE';
+  throw new Error(`Uncaught Local Variable Error - ${JSON.stringify({ randomVariableToRecord })}`);
+}
diff --git a/apps/nextjs-14_2_1/app/api/test-param-error/[param]/route.ts b/apps/nextjs-14_2_1/app/api/test-param-error/[param]/route.ts
new file mode 100644
index 0000000..76584f6
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-param-error/[param]/route.ts
@@ -0,0 +1,15 @@
+import { NextRequest } from 'next/server';
+import * as Sentry from '@sentry/nextjs';
+
+export async function GET(request: NextRequest) {
+  const exceptionId = Sentry.captureException(new Error('This is an error'));
+
+  await Sentry.flush(2000);
+
+  const { pathname } = new URL(request.url);
+
+  const params = pathname.split('/').filter(Boolean);
+  const param = params[params.length - 1];
+
+  return Response.json({ exceptionId, paramWas: param });
+}
diff --git a/apps/nextjs-14_2_1/app/api/test-param-success/[param]/route.ts b/apps/nextjs-14_2_1/app/api/test-param-success/[param]/route.ts
new file mode 100644
index 0000000..46daabb
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-param-success/[param]/route.ts
@@ -0,0 +1,10 @@
+import { NextRequest } from 'next/server';
+
+export async function GET(request: NextRequest) {
+  const { pathname } = new URL(request.url);
+
+  const params = pathname.split('/').filter(Boolean);
+  const param = params[params.length - 1];
+
+  return Response.json({ paramWas: param });
+}
diff --git a/apps/nextjs-14_2_1/app/api/test-success-manual/route.ts b/apps/nextjs-14_2_1/app/api/test-success-manual/route.ts
new file mode 100644
index 0000000..ceedc9c
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-success-manual/route.ts
@@ -0,0 +1,11 @@
+import * as Sentry from '@sentry/nextjs';
+
+export async function GET() {
+  Sentry.startSpan({ name: 'test-span' }, () => {
+    Sentry.startSpan({ name: 'child-span' }, () => {});
+  });
+
+  await Sentry.flush();
+
+  return Response.json({ data: 'test-success-body' });
+}
diff --git a/apps/nextjs-14_2_1/app/api/test-success/route.ts b/apps/nextjs-14_2_1/app/api/test-success/route.ts
new file mode 100644
index 0000000..35d264b
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/api/test-success/route.ts
@@ -0,0 +1,3 @@
+export async function GET() {
+  return Response.json({ version: 'v1' });
+}
diff --git a/apps/nextjs-14_2_1/app/favicon.ico b/apps/nextjs-14_2_1/app/favicon.ico
new file mode 100644
index 0000000..718d6fe
Binary files /dev/null and b/apps/nextjs-14_2_1/app/favicon.ico differ
diff --git a/apps/nextjs-14_2_1/app/globals.css b/apps/nextjs-14_2_1/app/globals.css
new file mode 100644
index 0000000..b1d52e3
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/globals.css
@@ -0,0 +1,17 @@
+* {
+  box-sizing: border-box;
+  padding: 0;
+  margin: 0;
+}
+
+html,
+body {
+  max-width: 100vw;
+  overflow-x: hidden;
+  font-family: sans-serif;
+}
+
+a {
+  color: inherit;
+  text-decoration: none;
+}
diff --git a/apps/nextjs-14_2_1/app/layout.tsx b/apps/nextjs-14_2_1/app/layout.tsx
new file mode 100644
index 0000000..d729d63
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/layout.tsx
@@ -0,0 +1,14 @@
+import './globals.css';
+import { ReactNode } from 'react';
+
+export default function RootLayout({
+  children,
+}: Readonly<{
+  children: ReactNode;
+}>) {
+  return (
+    
+      
{children}
+    
+  );
+}
diff --git a/apps/nextjs-14_2_1/app/page.tsx b/apps/nextjs-14_2_1/app/page.tsx
new file mode 100644
index 0000000..4af671e
--- /dev/null
+++ b/apps/nextjs-14_2_1/app/page.tsx
@@ -0,0 +1,58 @@
+'use client';
+
+import { useFetchData } from '@/utils/fetchData';
+
+const displayData = (data: any) => (data ? JSON.stringify(data, null, 2) : 'No data');
+
+export default function Home() {
+  const { data: dataSuccess, fetchData: testSuccess } = useFetchData('/api/test-success');
+  const { error: testErrorError, fetchData: testError } = useFetchData('/api/test-error');
+  const { data: dataParamSuccess, fetchData: testParamSuccess } = useFetchData(
+    '/api/test-param-success/1337',
+  );
+  const { data: dataParamError, fetchData: testParamError } = useFetchData(
+    'api/test-param-error/1337',
+  );
+  const { data: dataSuccessManual, fetchData: testSuccessManual } = useFetchData(
+    '/api/test-success-manual',
+  );
+  const { data: dataErrorManual, fetchData: testErrorManual } =
+    useFetchData('/api/test-error-manual');
+  const { data: dataLocalVariablesUncaught, fetchData: testLocalVariablesUncaught } = useFetchData(
+    '/api/test-local-variables-uncaught',
+  );
+  const { data: dataLocalVariablesCaught, fetchData: testLocalVariablesCaught } = useFetchData(
+    '/api/test-local-variables-caught',
+  );
+
+  return (
+    
+      
+        
Layout (/)
+        
+        
{displayData(dataSuccess)}
+
+        
+        
{displayData(testErrorError)}
+
+        
+        
{displayData(dataParamSuccess)}
+
+        
+        
{displayData(dataParamError)}
+
+        
+        
{displayData(dataSuccessManual)}
+
+        
+        
{displayData(dataErrorManual)}
+
+        
+        
{displayData(dataLocalVariablesUncaught)}
+
+        
+        
{displayData(dataLocalVariablesCaught)}
+