SDKs
JavaScript
Next.js

Next.js Integration

Capture errors from Next.js App Router and Pages Router applications.

Installation

npm install @statly/observe

App Router Setup

Initialize SDK

Create a provider component:

// app/providers.tsx
'use client';
 
import { useEffect } from 'react';
import { init } from '@statly/observe';
 
export function StatlyProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    init({
      dsn: process.env.NEXT_PUBLIC_STATLY_DSN!,
      environment: process.env.NODE_ENV,
    });
  }, []);
 
  return <>{children}</>;
}

Add to your layout:

// app/layout.tsx
import { StatlyProvider } from './providers';
 
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <StatlyProvider>{children}</StatlyProvider>
      </body>
    </html>
  );
}

Error Boundary

Capture React errors:

// app/error.tsx
'use client';
 
import { useEffect } from 'react';
import { captureException } from '@statly/observe';
 
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    captureException(error, {
      digest: error.digest,
      source: 'error-boundary',
    });
  }, [error]);
 
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={() => reset()}>Try again</button>
    </div>
  );
}

Server Actions

Wrap server actions:

// app/actions.ts
'use server';
 
import { withStatlyServerAction } from '@statly/observe/nextjs';
 
async function createUserAction(data: FormData) {
  // Your logic here
  const user = await db.users.create({
    name: data.get('name'),
  });
  return user;
}
 
export const createUser = withStatlyServerAction(
  createUserAction,
  'createUser'
);

Route Handlers

Wrap App Router route handlers:

// app/api/users/route.ts
import { NextResponse } from 'next/server';
import { withStatly } from '@statly/observe/nextjs';
 
export const GET = withStatly(async (request) => {
  const users = await db.users.findMany();
  return NextResponse.json(users);
});
 
export const POST = withStatly(async (request) => {
  const data = await request.json();
  const user = await db.users.create(data);
  return NextResponse.json(user, { status: 201 });
});

Pages Router Setup

Initialize SDK

// pages/_app.tsx
import { useEffect } from 'react';
import { init } from '@statly/observe';
import type { AppProps } from 'next/app';
 
export default function App({ Component, pageProps }: AppProps) {
  useEffect(() => {
    init({
      dsn: process.env.NEXT_PUBLIC_STATLY_DSN!,
      environment: process.env.NODE_ENV,
    });
  }, []);
 
  return <Component {...pageProps} />;
}

API Routes

Wrap Pages Router API handlers:

// pages/api/users.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { withStatlyPagesApi } from '@statly/observe/nextjs';
 
async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'GET') {
    const users = await db.users.findMany();
    res.json(users);
  }
}
 
export default withStatlyPagesApi(handler);

getServerSideProps

Wrap data fetching:

// pages/users/[id].tsx
import { withStatlyGetServerSideProps } from '@statly/observe/nextjs';
 
export const getServerSideProps = withStatlyGetServerSideProps(
  async (context) => {
    const user = await db.users.findUnique({
      where: { id: context.params.id },
    });
 
    return { props: { user } };
  }
);

Exported Functions

withStatly(handler)

Wrap App Router route handlers:

import { withStatly } from '@statly/observe/nextjs';
 
export const GET = withStatly(async (request) => {
  // Handler code
});

withStatlyPagesApi(handler)

Wrap Pages Router API routes:

import { withStatlyPagesApi } from '@statly/observe/nextjs';
 
export default withStatlyPagesApi(async (req, res) => {
  // Handler code
});

withStatlyServerAction(action, name?)

Wrap server actions:

import { withStatlyServerAction } from '@statly/observe/nextjs';
 
export const myAction = withStatlyServerAction(
  async (data) => { /* ... */ },
  'myAction' // Optional name for tracking
);

withStatlyGetServerSideProps(handler)

Wrap getServerSideProps:

import { withStatlyGetServerSideProps } from '@statly/observe/nextjs';
 
export const getServerSideProps = withStatlyGetServerSideProps(
  async (context) => {
    return { props: {} };
  }
);

withStatlyGetStaticProps(handler)

Wrap getStaticProps:

import { withStatlyGetStaticProps } from '@statly/observe/nextjs';
 
export const getStaticProps = withStatlyGetStaticProps(
  async (context) => {
    return { props: {} };
  }
);

captureNextJsError(error, context?)

Capture Next.js specific errors:

import { captureNextJsError } from '@statly/observe/nextjs';
 
// In error boundary
captureNextJsError(error, { page: '/users' });

Automatically extracts Next.js error digest and adds source metadata.