Skip to main content

Installation

npm install @squasher/nextjs

Setup

Create instrumentation.ts in your project root (or src/instrumentation.ts if using the src/ layout):
instrumentation.ts
import { init } from "@squasher/nextjs";

init({
  apiKey: process.env.SQUASHER_API_KEY!,
  projectId: process.env.SQUASHER_PROJECT_ID!,
  environment: process.env.NODE_ENV,
  release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
});
next.config.js
module.exports = {
  experimental: { instrumentationHook: true },
};
Automatic in Next.js 15+.

Middleware

Wrap your middleware to capture edge function errors:
middleware.ts
import { withSquasher } from "@squasher/nextjs";
import { NextResponse } from "next/server";

export default withSquasher(async (request) => {
  return NextResponse.next();
});

export const config = { matcher: ["/((?!_next|favicon.ico).*)"] };

API Route Handlers

Wrap App Router route handlers:
app/api/users/route.ts
import { squasherApiHandler } from "@squasher/nextjs";

export const GET = squasherApiHandler(async (request) => {
  const users = await db.query("SELECT * FROM users");
  return Response.json(users);
});

Error Boundary (Client)

Use in layout.tsx to wrap page content. Do not use inside error.tsx — App Router’s error.tsx is already an error boundary.
app/providers.tsx
"use client";
import { SquasherErrorBoundary } from "@squasher/nextjs/client";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <SquasherErrorBoundary fallback={<div>Something went wrong.</div>}>
      {children}
    </SquasherErrorBoundary>
  );
}
app/layout.tsx
import { Providers } from "./providers";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Manual Capture

import { captureError, captureMessage, getClient } from "@squasher/nextjs";

try {
  await riskyOperation();
} catch (error) {
  await captureError(error as Error, { context: "checkout" });
}

await captureMessage("Deployment started", "info");

getClient().setUser({ id: user.id, email: user.email });
getClient().addBreadcrumb({ category: "navigation", message: "/settings" });

Source Maps

Production stack traces are minified. Upload source maps for readable traces:
squasher sourcemaps upload \
  --project $SQUASHER_PROJECT_ID \
  --release $(git rev-parse HEAD) \
  .next/static/chunks/*.map
See Source Maps for CI setup.

Configuration

OptionTypeDefaultDescription
apiKeystringRequiredProject API key (sq_pk_...)
projectIdstringRequiredProject ID (UUID from dashboard)
endpointstringhttps://ingest.squasher.aiIngestion endpoint
environmentstringEnvironment tag
releasestringRelease version (e.g. git SHA)
sampleRatenumber1Sample rate 0-1
debugbooleanfalseLog SDK activity to console
beforeSendfunctionReturn event to send, or null to drop

Bundle Size

Under 5KB gzipped client bundle. Server-side code is tree-shaken. One network request per captured error — no polling.