npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sophonz/nextjs

v0.0.7

Published

One-config Sophonz monitoring for Next.js — browser and server, on one trace

Readme

@sophonz/nextjs

한국어

Sophonz monitoring for Next.js. Configures @sophonz/browser-sdk and @sophonz/node-sdk from one config, so browser and server spans share a trace.

Part of the Sophonz OpenTelemetry suite.

Install

bun add @sophonz/nextjs
# or
pnpm add @sophonz/nextjs
# or
npm install @sophonz/nextjs

Setup

instrumentation.ts at the project root:

export { register } from '@sophonz/nextjs/server';

app/layout.tsx:

import { SophonzProvider } from '@sophonz/nextjs/client';

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

.env:

NEXT_PUBLIC_SOPHONZ_COLLECTOR_URL=https://in.sophonz.ai
NEXT_PUBLIC_SOPHONZ_APP_NAME=my-app
NEXT_PUBLIC_SOPHONZ_APP_VERSION=1.0.0
NEXT_PUBLIC_SOPHONZ_APP_KEY=your-app-key
NEXT_PUBLIC_SOPHONZ_PROJECT=my-project
NEXT_PUBLIC_SOPHONZ_ENVIRONMENT=production

NEXT_PUBLIC_ is required — Next inlines only that prefix into the client bundle. appKey therefore reaches the browser; it is an ingestion key, not an access token.

next.config.js:

module.exports = {
  serverExternalPackages: ['@sophonz/nextjs', '@sophonz/node-sdk'],
};

OpenTelemetry patches modules through Node's require hook. Bundled modules are not required at runtime, so the hook misses them and database and HTTP client spans are lost.

Configuring in code

Config passed in wins over the environment.

// instrumentation.ts
import { register as sophonz } from '@sophonz/nextjs/server';

export const register = () =>
  sophonz({
    appName: 'my-app',
    server: { advancedNetworkCapture: true },
  });
<SophonzProvider
  appName="my-app"
  tracePropagationTargets={[/^https:\/\/api\.example\.com/]}
  browser={{ disableReplay: false }}
/>

Config

| Option | Type | Description | |--------|------|-------------| | collectorUrl | string | OTLP collector base URL | | appName | string | service.name | | appVersion | string | service.version | | appKey | string | service.key. Reaches the browser | | project | string | service.namespace | | deploymentEnvironment | string | e.g. production | | tracePropagationTargets | (string | RegExp)[] | Origins the browser sends traceparent to. Default: current origin | | debug | boolean | Verbose logging on both sides | | browser | object | Passed to @sophonz/browser-sdk | | server | object | Passed to @sophonz/node-sdk |

Use browser and server to reach any option of the underlying SDKs.

Defaults this package sets:

  • tracePropagationTargets: current origin only. Cross-origin requires the other end to allow traceparent in CORS.
  • Server betaMode: true — required for setTraceAttributes() to work.
  • Server disableStartupLogs: true — suppresses the SDK's startup spinner.
  • Browser disableIntercom: true — otherwise the SDK polls for a global Intercom and logs an error when absent.

Collected

Next.js (verified on Next 16): BaseServer.handleRequest, AppRender.getBodyResult, AppRender.fetch, NextNodeServer.startResponse, with next.route, next.rsc, next.segment, next.span_type.

Server SDK: HTTP server and client spans, database and Redis clients, Node runtime metrics, console.* as logs, and an error log record for every span ending with ERROR status, carrying that span's trace.id.

Browser SDK: page loads, Web Vitals, user interactions, fetch and XHR, JavaScript errors, optional session replay.

Request attributes

Next has no middleware chain, so @sophonz/node-sdk's Express/Koa/Fastify helpers do not apply.

import { setTraceAttributes } from '@sophonz/node-sdk';

export async function GET() {
  setTraceAttributes({ 'user.id': userId });
}

Deployment modes

| Mode | Server monitoring | Notes | |------|-------------------|-------| | next start | yes | | | output: 'standalone' | yes | Run node .next/standalone/server.js | | Serverless (Vercel, Lambda) | partial | Spans can be lost between invocations | | output: 'export' | n/a | No server; provider still works | | Edge runtime / middleware | no | |

Serverless: the platform freezes the process between invocations, so the batch processor's timer may not fire. @sophonz/node-sdk exports shutdown() but no forceFlush(), so there is no per-invocation flush. Long-lived instances are unaffected.

Edge runtime: register() returns without starting when NEXT_RUNTIME === 'edge'. The check is written so the bundler folds it, keeping the Node SDK out of the Edge bundle. Middleware and runtime = 'edge' routes are not traced; requests through them are traced once they reach a Node route.

Verifying

Browser console:

window.Sophonz.inited   // true
document.cookie         // contains __sophonz_rum_sid

Trace propagation:

curl -H "traceparent: 00-abababababababababababababababab-1111111111111111-01" \
  http://localhost:3000/api/your-route

Server spans for that request carry abababababababababababababababab.

Local collector for testing:

node -e "require('http').createServer((q,s)=>{let b=[];q.on('data',c=>b.push(c));q.on('end',()=>{console.log(q.url,Buffer.concat(b).length+'B');s.writeHead(200,{'access-control-allow-origin':'*','access-control-allow-methods':'POST, OPTIONS','access-control-allow-headers':'*'});s.end('{}')})}).listen(4318)"

Set NEXT_PUBLIC_SOPHONZ_COLLECTOR_URL=http://localhost:4318. The CORS headers are required — without them the browser's export fails preflight.

Troubleshooting

No console output, nothing collected. The provider did not mount. Verify @sophonz/nextjs is built. In a monorepo, run the app through a task that builds dependencies first; next dev alone rebuilds nothing.

Browser data but no server data. The halves point at different collectors. register() derives server endpoints from collectorUrl, but an explicitly set OTEL_EXPORTER_OTLP_TRACES_ENDPOINT takes precedence.

Server spans have their own trace id. The browser is not propagating. Add the API origin to tracePropagationTargets, and allow traceparent in its CORS config.

Module not found: Can't resolve <dynamic>. Fixed in @sophonz/node-sdk 0.2.5. Earlier versions resolve module names at runtime, which bundlers report on every compile. Collection is unaffected.

Config changes have no effect. NEXT_PUBLIC_ values are inlined at build time. Restart the dev server; Fast Refresh does not re-inline them.

API

@sophonz/nextjs/server

  • register(config?) — starts the server SDK. Returns { started, reason?, missing? }. reason is 'edge-runtime', 'already-started' or 'incomplete-config'.

@sophonz/nextjs/client

  • SophonzProvider — Client Component. Initializes once on mount, imports the browser SDK dynamically.

@sophonz/nextjs

  • resolveConfig(input?) — merges explicit config over the environment.
  • missingFields(config) — required fields that are absent.
  • ENV_KEYS — env var names.
  • SophonzNextConfig — config type.

Peer Dependencies

  • next >= 13.4.0
  • react >= 18

License

See LICENSE in this package.


Part of sophonz-js.