npm package: @liteverge/otel-nextjs
Description: OpenTelemetry configuration SDK for Next.js applications
Author: liteverge.com
Latest version: 0.0.1-alpha

# @liteverge/otel-nextjs

OpenTelemetry instrumentation for Next.js applications with automatic page tracking, error monitoring, and structured logging.

## Installation

```bash
npm install @liteverge/otel-nextjs
# or
pnpm add @liteverge/otel-nextjs
# or
yarn add @liteverge/otel-nextjs
```

## Quick Start

### App Router (Next.js 13+)

#### 1. Add the Provider to your root layout

The `LitevergeProvider` is a Client Component and can be used directly in your Server Component layout:

```tsx
// app/layout.tsx
import { LitevergeProvider } from "@liteverge/otel-nextjs";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <LitevergeProvider
          config={{
            apiKey: process.env.NEXT_PUBLIC_LITEVERGE_API_KEY!,
            serviceName: "my-nextjs-app",
            endpoint: "https://ingest.liteverge.ai",
            environment: process.env.NEXT_PUBLIC_ENV || "production",
            source: "nextjs",
            
            // Feature flags
            captureMetrics: true,
            captureErrors: true,
            captureNetworkRequests: false,
            enableWebPageAnalytics: true,
          }}
        >
          {children}
        </LitevergeProvider>
      </body>
    </html>
  );
}
```

> **Note:** The `LitevergeProvider` is a Client Component (marked with `"use client"`), so it can be imported and used in Server Components. All initialization happens client-side only, ensuring SSR compatibility.

#### 2. Add automatic page tracking

```tsx
// app/page-tracker.tsx
"use client";

import { usePageTracking } from "@liteverge/otel-nextjs";

export function PageTracker() {
  usePageTracking();
  return null;
}
```

```tsx
// app/layout.tsx
import { LitevergeProvider } from "@liteverge/otel-nextjs";
import { PageTracker } from "./page-tracker";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <LitevergeProvider config={{ /* ... */ }}>
          <PageTracker />
          {children}
        </LitevergeProvider>
      </body>
    </html>
  );
}
```

### Pages Router (Next.js 12 and earlier)

```tsx
// pages/_app.tsx
import type { AppProps } from "next/app";
import { LitevergeProvider } from "@liteverge/otel-nextjs";
import { useEffect } from "react";
import { useRouter } from "next/router";
import { trackPageView } from "@liteverge/otel-nextjs";

export default function App({ Component, pageProps }: AppProps) {
  const router = useRouter();

  useEffect(() => {
    // Track initial page load
    trackPageView({ route: router.pathname });

    // Track route changes
    const handleRouteChange = (url: string) => {
      trackPageView({ route: url });
    };

    router.events.on("routeChangeComplete", handleRouteChange);
    return () => router.events.off("routeChangeComplete", handleRouteChange);
  }, [router]);

  return (
    <LitevergeProvider
      config={{
        apiKey: process.env.NEXT_PUBLIC_LITEVERGE_API_KEY!,
        serviceName: "my-nextjs-app",
        endpoint: "https://ingest.liteverge.ai",
        environment: process.env.NEXT_PUBLIC_ENV || "production",
        source: "nextjs",
        captureMetrics: true,
        captureErrors: true,
      }}
    >
      <Component {...pageProps} />
    </LitevergeProvider>
  );
}
```

## Usage Examples

### Track Custom Events

```tsx
"use client";

import { useTrackEvent } from "@liteverge/otel-nextjs";

export function SignupButton() {
  const trackEvent = useTrackEvent();

  const handleClick = () => {
    trackEvent("button_clicked", {
      buttonId: "signup",
      page: "homepage",
    });
  };

  return <button onClick={handleClick}>Sign Up</button>;
}
```

### Structured Logging

```tsx
"use client";

import { useLogger } from "@liteverge/otel-nextjs";

export function MyComponent() {
  const logger = useLogger();

  const handleSubmit = async (data: FormData) => {
    try {
      logger.info("Form submission started", { formId: "contact" });
      await submitForm(data);
      logger.info("Form submitted successfully");
    } catch (error) {
      logger.error("Form submission failed", { formId: "contact" }, error);
    }
  };

  return <form onSubmit={handleSubmit}>...</form>;
}
```

### User Identification

```tsx
"use client";

import { useIdentifyUser } from "@liteverge/otel-nextjs";
import { useEffect } from "react";

export function UserProvider({ user, children }) {
  const identifyUser = useIdentifyUser();

  useEffect(() => {
    if (user) {
      identifyUser(user.id, {
        email: user.email,
        name: user.name,
        plan: user.plan,
      });
    }
  }, [user, identifyUser]);

  return <>{children}</>;
}
```

### Error Boundary

```tsx
// app/error.tsx
"use client";

import { useEffect } from "react";
import { captureException } from "@liteverge/otel-nextjs";

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

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

### Manual Tracking (Without Hooks)

```tsx
// Works in both client and server components
import { trackEvent, trackPageView } from "@liteverge/otel-nextjs";

// These functions have built-in browser checks
export function someFunction() {
  trackEvent("custom_event", { key: "value" });
  trackPageView({ route: "/custom-route" });
}
```

## Configuration Options

```typescript
interface LitevergeBrowserConfig {
  // Required
  apiKey: string;
  serviceName: string;
  
  // Optional
  endpoint?: string; // Default: "https://ingest.liteverge.ai"
  environment?: string; // Default: "production"
  source: string; // Recommended: "nextjs"
  debug?: boolean;
  
  // Logging (optional - only needed if you want to use structured logging)
  logging?: {
    withTraces: boolean; // Attach logs to active traces
  };

  // Feature flags
  captureErrors?: boolean; // Default: true
  captureUserInteractions?: boolean; // Default: false
  captureNetworkRequests?: boolean; // Default: false
  capturePageLoads?: boolean; // Default: false
  captureMetrics?: boolean; // Default: false
  enableWebPageAnalytics?: boolean; // Default: false

  // Sampling
  sendOnlyErrors?: boolean; // Only send error traces
  sampleRate?: number; // 0.0 to 1.0, default: 1.0

  // User context
  userContext?: {
    userId?: string;
    email?: string;
    name?: string;
    [key: string]: any;
  };

  // Metrics
  metricsExportIntervalMillis?: number; // Default: 60000
  metricsExportTimeoutMillis?: number;
}
```

## API Reference

### Hooks

- `usePageTracking()` - Automatically track page views in App Router
- `useTrackEvent()` - Get a stable function to track custom events
- `useLogger()` - Get the logger instance
- `useLogInfo()` - Get a stable info logging function
- `useLogError()` - Get a stable error logging function
- `useIdentifyUser()` - Get a stable user identification function

### Functions

- `trackPageView(properties?)` - Manually track a page view
- `trackEvent(name, properties?)` - Track a custom event
- `identifyUser(id, traits?)` - Identify the current user
- `captureException(error, context?)` - Capture an error
- `setUser(user)` - Set user context
- `getLogger()` - Get the logger instance
- `recordMetric(name, value, attributes?)` - Record a custom metric

### Components

- `<LitevergeProvider>` - Root provider for initialization
- `<ErrorBoundary>` - React error boundary with automatic error capture

## Environment Variables

Make sure to prefix your environment variables with `NEXT_PUBLIC_` so they're available in the browser:

```env
NEXT_PUBLIC_LITEVERGE_API_KEY=your_api_key_here
NEXT_PUBLIC_ENV=production
```

## Best Practices

1. **Keep the provider at the root** - Add `<LitevergeProvider>` to your root layout
2. **Use hooks in client components** - All hooks require `'use client'` directive
3. **Enable only what you need** - Use feature flags to control bundle size
4. **Set appropriate sample rates** - Use `sampleRate` to control data volume in production
5. **Logging is optional** - Only configure `logging` if you need structured logging. Metrics, traces, and errors work without it.
6. **Identify users early** - Call `identifyUser()` as soon as authentication is available

## TypeScript Support

This package is written in TypeScript and includes full type definitions.

## Troubleshooting

### "Class extends value undefined is not a constructor or null"

If you see this error when importing `LitevergeProvider`:

```
TypeError: Class extends value undefined is not a constructor or null
```

This typically means you're using an older version of the package. The `LitevergeProvider` is now a Client Component (marked with `"use client"`) and can be safely imported in Server Components.

**Solution:** Update to the latest version of `@liteverge/otel-nextjs`:

```bash
npm install @liteverge/otel-nextjs@latest
# or
pnpm update @liteverge/otel-nextjs
```

### Provider not initializing

If the provider doesn't seem to initialize:

1. Check that your API key is prefixed with `NEXT_PUBLIC_` in your `.env` file
2. Verify the API key is being passed correctly to the config
3. Enable `debug: true` in the config to see initialization logs
4. Check the browser console for any error messages

## License

MIT

## Links

- [Documentation](https://docs.liteverge.ai)
- [GitHub](https://github.com/liteverge/ts-otel-sdk)