# Framework Wrappers

> Set up TraceKit in React, Vue, Angular, Next.js, and Nuxt with framework-specific error capture, navigation breadcrumbs, and performance monitoring.

- Canonical: https://tracekit.dev/docs/frontend/frameworks

Set up TraceKit in React, Vue, Angular, Next.js, and Nuxt with framework-specific error capture, navigation breadcrumbs, and performance monitoring.

## Introduction

TraceKit provides framework-specific wrappers that add error boundaries, navigation breadcrumbs, and framework-aware error capture on top of the core `@tracekit/browser` SDK.

All wrappers re-export every function from `@tracekit/browser`, so you only need one import. For example, `import { init, captureException } from '@tracekit/react'` works the same as importing from `@tracekit/browser` directly.

For the core API reference (init, captureException, captureMessage, setUser, setTag, setExtra, addBreadcrumb, getClient), see the [Browser SDK documentation](/docs/frontend/browser-sdk).

| Framework | Package | Key Features |
| --- | --- | --- |
| React | `@tracekit/react` | ErrorBoundary, React 19 createRoot hooks, React Router breadcrumbs |
| Vue | `@tracekit/vue` | Vue plugin, error handler chaining, Vue Router breadcrumbs |
| Angular | `@tracekit/angular` | Standalone + NgModule APIs, ErrorHandler, router breadcrumbs |
| Next.js | `@tracekit/nextjs` | Multi-runtime init (client + server), GlobalError, Pages Router HOC |
| Nuxt | `@tracekit/nuxt` | Auto-init plugin, useTraceKit composable, router breadcrumbs |

## React

`@tracekit/react` provides an error boundary component, React 19 createRoot error hooks, and React Router breadcrumb tracking.

### Installation

```bash
npm install @tracekit/react
```

### Quick Start

```tsx
import { init, TraceKitErrorBoundary } from '@tracekit/react';

init({ apiKey: 'your-api-key', release: '1.0.0' });

function App() {
  return (
    <TraceKitErrorBoundary fallback={<p>Something went wrong.</p>}>
      <MyApp />
    </TraceKitErrorBoundary>
  );
}
```

That is all you need for basic React error capture. The SDK automatically captures uncaught errors, unhandled rejections, console errors, and network requests as breadcrumbs. The ErrorBoundary adds React-specific component stack traces.

### TraceKitErrorBoundary

A React error boundary that captures render errors with `componentStack` context and sends them to TraceKit. Renders a user-provided fallback on error. Does not re-throw -- swallows the error and shows the fallback UI.

When an error is caught, the boundary calls `captureException` with the error and `componentStack` context, marks it as `handled: true` with mechanism `react.errorBoundary`, then renders the fallback.

**Props**

| Field | Type | Description |
| --- | --- | --- |
| `children` | ReactNode | The component tree to wrap with error boundary protection. |
| `fallback` | ReactNode \| (error, componentStack, resetError) => ReactNode | Static element or render function called when an error is caught. |
| `onError` | ((error: Error, componentStack: string) => void)? | Optional callback invoked when an error is caught. |

The fallback render function receives three arguments:

```tsx
// Fallback render function signature
(error: Error, componentStack: string, resetError: () => void) => ReactNode

// Example usage
<TraceKitErrorBoundary
  fallback={(error, componentStack, resetError) => (
    <div>
      <h2>Error: {error.message}</h2>
      <pre>{componentStack}</pre>
      <button onClick={resetError}>Try again</button>
    </div>
  )}
>
  <MyApp />
</TraceKitErrorBoundary>
```

### traceKitCreateRootOptions

A function that returns React 19 `createRoot` error callbacks. These hooks capture errors that occur outside of error boundaries: uncaught errors, caught errors from error boundaries (with additional context), and recoverable hydration mismatches.

```tsx
import { createRoot } from 'react-dom/client';
import { traceKitCreateRootOptions } from '@tracekit/react';

const root = createRoot(document.getElementById('root')!, {
  ...traceKitCreateRootOptions(),
});

root.render(<App />);
```

The `onUncaughtError`, `onCaughtError`, and `onRecoverableError` callbacks are React 19 features. React 18 ignores unknown options, so calling `traceKitCreateRootOptions()` is safe in React 18 -- the hooks simply won't fire. In React 18, rely on TraceKitErrorBoundary for error capture.

**Returned Hooks**

| Field | Type | Description |
| --- | --- | --- |
| `onUncaughtError` | (error, errorInfo) => void | Fires for errors not caught by any error boundary. Captured as unhandled. |
| `onCaughtError` | (error, errorInfo) => void | Fires for errors caught by an error boundary. Captured as handled. |
| `onRecoverableError` | (error, errorInfo) => void | Fires for hydration mismatch errors React recovers from. Captured as handled. |

### TraceKitRouterBreadcrumbs

An invisible component that records React Router navigation changes as breadcrumbs. Must be placed inside a `BrowserRouter`.

| Field | Type | Description |
| --- | --- | --- |
| `parameterizedRoutes` | boolean? | Default: true. When true, uses the raw pathname from useLocation. Breadcrumbs record from/to navigation paths. |

```tsx
import { BrowserRouter, Routes, Route } from 'react-router';
import { TraceKitRouterBreadcrumbs } from '@tracekit/react';

function App() {
  return (
    <BrowserRouter>
      <TraceKitRouterBreadcrumbs />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/users/:id" element={<UserProfile />} />
      </Routes>
    </BrowserRouter>
  );
}
```

### Re-exported Functions

`@tracekit/react` re-exports all public functions from `@tracekit/browser` for convenience:

```ts
import {
  init, captureException, captureMessage, setUser,
  setTag, setExtra, addBreadcrumb, getClient,
} from '@tracekit/react';
```

### Complete Example

Full React setup with ErrorBoundary, createRoot hooks, and Router breadcrumbs.

```tsx title="main.tsx"
import { createRoot } from 'react-dom/client';
import { init, traceKitCreateRootOptions } from '@tracekit/react';
import App from './App';

// 1. Initialize the SDK
init({
  apiKey: process.env.REACT_APP_TRACEKIT_API_KEY!,
  release: process.env.REACT_APP_VERSION || '0.0.0',
  environment: process.env.NODE_ENV || 'production',
});

// 2. Create root with React 19 error hooks
const root = createRoot(document.getElementById('root')!, {
  ...traceKitCreateRootOptions(),
});

root.render(<App />);
```

```tsx title="App.tsx"
import { BrowserRouter, Routes, Route } from 'react-router';
import {
  TraceKitErrorBoundary,
  TraceKitRouterBreadcrumbs,
  setUser,
} from '@tracekit/react';
import { Home } from './pages/Home';
import { UserProfile } from './pages/UserProfile';
import { Settings } from './pages/Settings';

export default function App() {
  return (
    <TraceKitErrorBoundary
      fallback={(error, componentStack, resetError) => (
        <div className="error-page">
          <h1>Something went wrong</h1>
          <p>{error.message}</p>
          <button onClick={resetError}>Try again</button>
        </div>
      )}
      onError={(error, componentStack) => {
        console.error('Caught by ErrorBoundary:', error.message);
      }}
    >
      <BrowserRouter>
        <TraceKitRouterBreadcrumbs />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/users/:id" element={<UserProfile />} />
          <Route path="/settings" element={<Settings />} />
        </Routes>
      </BrowserRouter>
    </TraceKitErrorBoundary>
  );
}
```

## Vue

`@tracekit/vue` provides a Vue plugin that auto-initializes the SDK, sets up Vue error handler chaining, and optionally captures Vue Router navigation breadcrumbs.

### Installation

```bash
npm install @tracekit/vue
```

### Quick Start

```ts
import { createApp } from 'vue';
import { TraceKitPlugin } from '@tracekit/vue';
import App from './App.vue';

const app = createApp(App);
app.use(TraceKitPlugin, {
  apiKey: 'your-api-key',
  release: '1.0.0',
});
app.mount('#app');
```

The plugin handles everything: SDK initialization, Vue error handler setup (with chaining to existing handlers), and optional router breadcrumbs. Pass a `router` instance in options to enable navigation breadcrumbs.

### TraceKitPlugin

A Vue plugin that handles SDK initialization, error handler setup, and optional router breadcrumbs in a single `app.use()` call.

**TraceKitVueOptions** -- Extends `TracekitBrowserConfig` (see [Browser SDK configuration](/docs/frontend/browser-sdk#configuration)) with two additional options:

| Field | Type | Description |
| --- | --- | --- |
| `router` | Router? | Vue Router instance. When provided, the plugin automatically captures route change breadcrumbs. |
| `parameterizedRoutes` | boolean? | Default: true. When true, breadcrumbs use the route config pattern (e.g., /users/:id) instead of the actual URL. |

### setupErrorHandler(app)

Manually set up the Vue error handler. The plugin calls this automatically, but you can call it directly if you need more control. The error handler chains to the previous handler rather than overwriting it.

```ts
import { createApp } from 'vue';
import { init } from '@tracekit/browser';
import { setupErrorHandler } from '@tracekit/vue';

const app = createApp(App);
init({ apiKey: 'your-api-key' });
setupErrorHandler(app);
app.mount('#app');
```

### setupRouterBreadcrumbs(router, parameterized?)

Manually set up Vue Router breadcrumbs. Uses `router.afterEach` to capture navigation events with from/to paths.

```ts
import { createRouter, createWebHistory } from 'vue-router';
import { setupRouterBreadcrumbs } from '@tracekit/vue';

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/users/:id', component: UserProfile },
  ],
});

setupRouterBreadcrumbs(router);
// Or with actual URLs instead of parameterized patterns
setupRouterBreadcrumbs(router, false);
```

### Re-exported Functions

```ts
import {
  captureException, captureMessage, setUser,
  setTag, setExtra, addBreadcrumb, getClient,
} from '@tracekit/vue';
```

`init()` is not re-exported from `@tracekit/vue` because TraceKitPlugin calls it automatically. If you need manual initialization, import `init` from `@tracekit/browser` directly.

### Complete Example

```ts title="main.ts"
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import { TraceKitPlugin, setUser } from '@tracekit/vue';
import App from './App.vue';
import Home from './views/Home.vue';
import UserProfile from './views/UserProfile.vue';
import Settings from './views/Settings.vue';

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/users/:id', component: UserProfile },
    { path: '/settings', component: Settings },
  ],
});

const app = createApp(App);

app.use(TraceKitPlugin, {
  apiKey: import.meta.env.VITE_TRACEKIT_API_KEY,
  release: import.meta.env.VITE_APP_VERSION || '0.0.0',
  environment: import.meta.env.MODE,
  router,
  parameterizedRoutes: true,
});

app.use(router);
app.mount('#app');

router.beforeEach(async (to) => {
  const user = await authStore.getUser();
  if (user) {
    setUser({ id: user.id, email: user.email, username: user.name });
  }
});
```

## Angular

`@tracekit/angular` supports both standalone applications (Angular 15+) and NgModule-based applications. It replaces Angular's default ErrorHandler with one that captures errors via TraceKit.

### Installation

```bash
npm install @tracekit/angular
```

### Quick Start (Standalone)

```ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideTraceKit } from '@tracekit/angular';
import { AppComponent } from './app.component';

bootstrapApplication(AppComponent, {
  providers: [
    ...provideTraceKit({
      apiKey: 'your-api-key',
      release: '1.0.0',
    }),
  ],
});
```

### Standalone API (Angular 15+)

**provideTraceKit(config)** -- Initializes the `@tracekit/browser` SDK and returns a `Provider[]` array that replaces Angular's default `ErrorHandler` with `TraceKitErrorHandler`. Use the spread operator to merge into your providers array.

**TraceKitAngularConfig** -- Extends `TracekitBrowserConfig` (see [Browser SDK configuration](/docs/frontend/browser-sdk#configuration)) with:

| Field | Type | Description |
| --- | --- | --- |
| `parameterizedRoutes` | boolean? | Default: true. When true, router breadcrumbs use the route config path (e.g., /users/:id) instead of the actual URL. |

**provideTraceKitRouter(parameterized?)** -- Returns a `Provider[]` array that sets up router breadcrumbs via `APP_INITIALIZER`. The router is lazily resolved from Angular's injector to avoid circular dependency issues.

```ts
import { provideRouter } from '@angular/router';
import { provideTraceKit, provideTraceKitRouter } from '@tracekit/angular';

bootstrapApplication(AppComponent, {
  providers: [
    ...provideTraceKit({ apiKey: 'your-api-key' }),
    provideRouter(routes),
    ...provideTraceKitRouter(),
  ],
});
```

### NgModule API

**TraceKitModule.forRoot(config)** -- For NgModule-based applications. Returns a module with providers that initializes the SDK and replaces the default ErrorHandler.

Use `provideTraceKit` for standalone apps and `TraceKitModule.forRoot` for NgModule apps. Do not mix both approaches in the same application.

### Re-exported Functions

```ts
import {
  captureException, captureMessage, setUser,
  setTag, setExtra, addBreadcrumb, getClient,
} from '@tracekit/angular';
```

### Complete Examples

**Standalone Application**

```ts
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { provideTraceKit, provideTraceKitRouter } from '@tracekit/angular';
import { AppComponent } from './app.component';

const routes = [
  { path: '', loadComponent: () => import('./home.component') },
  { path: 'users/:id', loadComponent: () => import('./user.component') },
];

bootstrapApplication(AppComponent, {
  providers: [
    ...provideTraceKit({
      apiKey: 'your-api-key',
      release: '1.0.0',
      environment: 'production',
    }),
    provideRouter(routes),
    ...provideTraceKitRouter(),
  ],
});
```

**NgModule Application**

```ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { TraceKitModule } from '@tracekit/angular';
import { AppComponent } from './app.component';
import { HomeComponent } from './home.component';
import { UsersComponent } from './users.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'users/:id', component: UsersComponent },
];

@NgModule({
  declarations: [AppComponent, HomeComponent, UsersComponent],
  imports: [
    BrowserModule,
    RouterModule.forRoot(routes),
    TraceKitModule.forRoot({
      apiKey: 'your-api-key',
      release: '1.0.0',
      environment: 'production',
    }),
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

**Using TraceKit in a Component**

```ts
// user.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { captureException, setUser } from '@tracekit/angular';

@Component({
  selector: 'app-user',
  template: '<h1>{{ user?.name }}</h1>',
})
export class UserComponent implements OnInit {
  user: any;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    const id = this.route.snapshot.paramMap.get('id');
    this.loadUser(id!);
  }

  async loadUser(id: string) {
    try {
      const res = await fetch('/api/users/' + id);
      this.user = await res.json();
      setUser({ id: this.user.id, email: this.user.email });
    } catch (err) {
      captureException(err as Error, { userId: id });
    }
  }
}
```

Import `captureException` and other functions directly from `@tracekit/angular`. No dependency injection is needed for the SDK functions -- they work as plain function calls.

## Next.js

`@tracekit/nextjs` supports Next.js multi-runtime architecture with separate initialization for client-side (browser) and server-side (Node.js/Edge). It provides error boundary components for both App Router and Pages Router.

### Installation

```bash
npm install @tracekit/nextjs
```

### Quick Start

```ts title="instrumentation-client.ts"
import { initClient, onRouterTransitionStart } from '@tracekit/nextjs';

initClient({
  apiKey: process.env.NEXT_PUBLIC_TRACEKIT_API_KEY!,
  release: process.env.NEXT_PUBLIC_APP_VERSION,
});

export { onRouterTransitionStart };
```

```ts title="instrumentation.ts"
import { initServer } from '@tracekit/nextjs';

export function register() {
  initServer({
    apiKey: process.env.TRACEKIT_API_KEY!,
    release: process.env.APP_VERSION,
  });
}
```

### Multi-Runtime Architecture

Next.js runs code in two separate runtimes: the browser (client) and Node.js/Edge (server). Each runtime requires its own initialization.

| Runtime | File | Function | What It Does |
| --- | --- | --- | --- |
| Client | instrumentation-client.ts | initClient(config) | Initializes `@tracekit/browser` for client-side error capture, breadcrumbs, and distributed tracing. |
| Server | instrumentation.ts | initServer(config) | Stores server config for captureRequestError. Runs in register(). |

### initClient(config: TraceKitNextConfig)

Client-side initialization. Accepts the same options as `TracekitBrowserConfig` (see [Browser SDK configuration](/docs/frontend/browser-sdk#configuration)). Call this in `instrumentation-client.ts`.

### initServer(config: TraceKitServerConfig)

Server-side initialization. Stores configuration for use by `captureRequestError`. Call this inside the `register()` function in `instrumentation.ts`.

| Field | Type | Description |
| --- | --- | --- |
| `apiKey` | string | Required. Your TraceKit project API key. |
| `release` | string? | Release version for error grouping. |
| `environment` | string? | Deployment environment (e.g., production, staging). |
| `apiEndpoint` | string? | TraceKit API endpoint. Default: https://app.tracekit.dev |

### onRouterTransitionStart

Next.js 15.3+ navigation hook that captures client-side route transitions as breadcrumbs. Export this from `instrumentation-client.ts`.

```ts
function onRouterTransitionStart(
  url: string,
  navigationType: 'push' | 'replace' | 'traverse'
): void
```

```ts title="instrumentation-client.ts"
export { onRouterTransitionStart } from '@tracekit/nextjs';
```

Records breadcrumbs with from/to URLs and navigation type (push, replace, or traverse). Page loads do not trigger this hook -- they are captured by the base navigation integration from `@tracekit/browser`.

### captureRequestError

Server-side request error capture. Matches Next.js `onRequestError` signature. Sends error payload to TraceKit via HTTP POST. Fire-and-forget -- never throws.

```ts title="instrumentation.ts"
import { initServer, captureRequestError } from '@tracekit/nextjs';

export function register() {
  initServer({ apiKey: process.env.TRACEKIT_API_KEY! });
}

export const onRequestError = captureRequestError;
```

**RequestErrorContext** -- Context provided by Next.js with each server error:

| Field | Type | Description |
| --- | --- | --- |
| `routerKind` | string | Router type: 'Pages Router' or 'App Router'. |
| `routePath` | string | Route pattern, e.g., '/users/[id]'. |
| `routeType` | string | Route type: 'page', 'route', or 'middleware'. |

### GlobalError

App Router global error component. Captures errors via `captureException` and renders a resettable error UI. Use as the default export in `app/global-error.tsx`.

```tsx title="app/global-error.tsx"
// Default export captures errors and renders a resettable error UI.
export { GlobalError as default } from '@tracekit/nextjs';

// Or customize the error UI:
'use client';

import { useEffect } from 'react';
import { captureException } from '@tracekit/nextjs';

export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    captureException(error);
  }, [error]);

  return (
    <html>
      <body>
        <h2>Something went wrong!</h2>
        <button onClick={reset}>Try again</button>
      </body>
    </html>
  );
}
```

### withTraceKitErrorPage(Page)

Pages Router higher-order component. Wraps your custom error page to capture errors via `captureException`.

```tsx title="pages/_error.tsx"
import { withTraceKitErrorPage } from '@tracekit/nextjs';

function CustomErrorPage({ statusCode }: { statusCode?: number }) {
  return (
    <div>
      <h1>{statusCode ? statusCode + ' - Server Error' : 'Client Error'}</h1>
      <p>An unexpected error occurred.</p>
    </div>
  );
}

CustomErrorPage.getInitialProps = ({ res, err }: any) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  return { statusCode, err };
};

export default withTraceKitErrorPage(CustomErrorPage);
```

### Re-exported Functions

```ts
import {
  captureException, captureMessage, setUser,
  setTag, setExtra, addBreadcrumb, getClient,
} from '@tracekit/nextjs';
```

These re-exports are client-side functions from `@tracekit/browser`. Do not use them in server-side code (API routes, server components). For server-side error capture, use `captureRequestError`.

### Complete Example

All files needed for a full Next.js App Router setup.

```bash title=".env.local"
NEXT_PUBLIC_TRACEKIT_API_KEY=your-client-api-key
TRACEKIT_API_KEY=your-server-api-key
APP_VERSION=1.0.0
NEXT_PUBLIC_APP_VERSION=1.0.0
```

```ts title="instrumentation-client.ts"
import { initClient, onRouterTransitionStart } from '@tracekit/nextjs';

initClient({
  apiKey: process.env.NEXT_PUBLIC_TRACEKIT_API_KEY!,
  release: process.env.NEXT_PUBLIC_APP_VERSION,
  environment: process.env.NODE_ENV,
  tracePropagationTargets: [
    process.env.NEXT_PUBLIC_API_URL || 'https://api.example.com',
  ],
});

export { onRouterTransitionStart };
```

```ts title="instrumentation.ts"
import { initServer, captureRequestError } from '@tracekit/nextjs';

export function register() {
  initServer({
    apiKey: process.env.TRACEKIT_API_KEY!,
    release: process.env.APP_VERSION,
    environment: process.env.NODE_ENV,
  });
}

export const onRequestError = captureRequestError;
```

```tsx title="app/global-error.tsx"
export { GlobalError as default } from '@tracekit/nextjs';
```

## Nuxt

`@tracekit/nuxt` provides a Nuxt plugin factory and a composable for accessing TraceKit functions within components.

### Installation

```bash
npm install @tracekit/nuxt
```

### Quick Start

```ts title="plugins/tracekit.client.ts"
import { defineNuxtPlugin } from '#imports';
import { createTraceKitPlugin } from '@tracekit/nuxt';

export default defineNuxtPlugin(createTraceKitPlugin({
  apiKey: 'your-api-key',
  release: '1.0.0',
}));
```

The plugin file **must** end in `.client.ts` to ensure it only runs in the browser. Without the `.client` suffix, Nuxt will also execute the plugin on the server where browser APIs are unavailable.

### createTraceKitPlugin(config)

Creates a Nuxt plugin function that initializes the `@tracekit/browser` SDK, hooks into `vue:error` for component error capture, and provides composable functions via `useNuxtApp().$tracekit`.

**TraceKitNuxtConfig** -- Extends `TracekitBrowserConfig` (see [Browser SDK configuration](/docs/frontend/browser-sdk#configuration)) with:

| Field | Type | Description |
| --- | --- | --- |
| `parameterizedRoutes` | boolean? | Default: true. When true, router breadcrumbs use route patterns instead of actual URLs. |

### useTraceKit()

A composable that returns TraceKit error capture functions. Works inside any Nuxt component setup since the SDK is already initialized by the plugin.

| Field | Type | Description |
| --- | --- | --- |
| `captureException` | (error: Error, context?: Record) => string | Manually capture an error. Returns the event ID. |
| `captureMessage` | (message: string, level?: SeverityLevel) => string | Send a message event. Returns the event ID. |
| `setUser` | (user: UserContext \| null) => void | Set or clear the current user context. |

```vue
<script setup lang="ts">
import { useTraceKit } from '@tracekit/nuxt';

const { captureException, setUser } = useTraceKit();

async function loadData() {
  try {
    const data = await $fetch('/api/dashboard');
    // ...
  } catch (err) {
    captureException(err as Error, { component: 'Dashboard' });
  }
}

// Set user context after authentication
onMounted(async () => {
  const { data: user } = await useFetch('/api/auth/me');
  if (user.value) {
    setUser({ id: user.value.id, email: user.value.email });
  }
});
</script>
```

### Re-exported Functions

```ts
import {
  init, captureException, captureMessage, setUser,
  setTag, setExtra, addBreadcrumb, getClient,
} from '@tracekit/nuxt';
```

### Complete Example

```ts title="plugins/tracekit.client.ts"
import { defineNuxtPlugin, useRouter } from '#imports';
import { createTraceKitPlugin, setupRouterBreadcrumbs } from '@tracekit/nuxt';

export default defineNuxtPlugin((nuxtApp) => {
  const provided = createTraceKitPlugin({
    apiKey: useRuntimeConfig().public.tracekitApiKey as string,
    release: useRuntimeConfig().public.appVersion as string,
    environment: process.env.NODE_ENV,
    parameterizedRoutes: true,
  })(nuxtApp);

  const router = useRouter();
  setupRouterBreadcrumbs(router);

  return provided;
});
```

```vue title="pages/users/[id].vue"
<script setup lang="ts">
import { useTraceKit } from '@tracekit/nuxt';

const route = useRoute();
const { captureException, captureMessage, setUser } = useTraceKit();

const { data: user, error } = await useFetch(`/api/users/${route.params.id}`);

if (error.value) {
  captureException(new Error(error.value.message), {
    userId: route.params.id,
  });
}

captureMessage('User profile viewed', 'info');
</script>

<template>
  <div v-if="user">
    <h1>{{ user.name }}</h1>
    <p>{{ user.email }}</p>
  </div>
  <div v-else>
    <p>User not found</p>
  </div>
</template>
```

## Troubleshooting

### React 19 vs React 18: createRoot hooks

The `onUncaughtError`, `onCaughtError`, and `onRecoverableError` callbacks only fire in React 19. In React 18, `traceKitCreateRootOptions()` returns the same object, but React ignores unknown options.

**Recommendation:** In React 18, rely solely on `TraceKitErrorBoundary` for error capture. Calling `traceKitCreateRootOptions()` is harmless but does nothing.

### Angular: standalone vs NgModule

Use `provideTraceKit()` for standalone applications (Angular 15+) and `TraceKitModule.forRoot()` for NgModule-based applications. Both register the same `TraceKitErrorHandler` and initialize the SDK.

**Do not mix both approaches.** Using `provideTraceKit` inside an NgModule and `TraceKitModule.forRoot` in the same app results in double initialization.

### Next.js: client vs server initialization

`initClient` initializes the browser SDK and must only run in the browser (`instrumentation-client.ts`). `initServer` stores config for server-side error capture and must only run in Node.js/Edge (`instrumentation.ts`).

**Do not call initClient on the server.** It imports `@tracekit/browser` which depends on browser APIs (window, document, navigator). Calling it in a server context causes runtime errors.

### Vue: router plugin installation order

Install `TraceKitPlugin` before `app.use(router)` if you want router breadcrumbs from the first navigation.

```ts
// Correct order: TraceKit first, then router
app.use(TraceKitPlugin, { apiKey: '...', router });
app.use(router);
app.mount('#app');
```

### Nuxt: client-only plugin execution

The plugin file must end in `.client.ts` (e.g., `plugins/tracekit.client.ts`). Without the `.client` suffix, Nuxt runs the plugin during server-side rendering where browser APIs like `window` and `document` are not available, causing errors.

### Re-exports: single import convenience

All wrappers re-export core SDK functions. You do not need to install `@tracekit/browser` separately -- your framework package includes it as a dependency.

```ts
// These are equivalent:
import { captureException } from '@tracekit/browser';
import { captureException } from '@tracekit/react';
import { captureException } from '@tracekit/vue';
// Use whichever package you have installed
```

### Debug mode across all frameworks

Enable `debug: true` in your init configuration to see SDK activity in the browser console. This works identically across all framework wrappers.

```ts
init({
  apiKey: 'your-api-key',
  debug: process.env.NODE_ENV === 'development',
});
```

### Breadcrumbs not appearing in error events

Breadcrumbs are only attached to subsequent error events, not previous ones. If your router breadcrumbs are not appearing, ensure that (1) the router component or plugin is installed before the first navigation occurs, (2) the SDK is initialized with `init()` before the router setup, and (3) you have not disabled navigation breadcrumbs via `integrations: { navigation: false }`.
