Skip to main content
GreenSlope

Next.js quickstart

Target: your first trace in your tenant in about four minutes. This quickstart assumes Next.js 14 or 15 with the App Router. If you're on Pages Router, the steps are the same but the instrumentation hook location differs — see Next.js setup once you're done here.

1. Sign up and grab your tenant key

Create a GreenSlope tenant. During signup you'll get a tenant ingest key that looks like gs_ing_live_…. Keep it close — it goes in one env var.

# In your .env.local (do not commit)
GREENSLOPE_INGEST_KEY="gs_ing_live_…"

2. Install the OTel packages

pnpm add @opentelemetry/api \
  @opentelemetry/sdk-node \
  @opentelemetry/auto-instrumentations-node \
  @opentelemetry/exporter-trace-otlp-http \
  @opentelemetry/resources \
  @opentelemetry/semantic-conventions

Everything is an upstream @opentelemetry/* package. If you've instrumented another OTel-compatible backend before, these will be familiar.

3. Add the instrumentation hook

Next.js calls instrumentation.ts at the root of your project (or under src/) exactly once per runtime. That's where the OTel SDK starts.

// instrumentation.ts
import { NodeSDK } from "@opentelemetry/sdk-node"
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node"
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
import { resourceFromAttributes } from "@opentelemetry/resources"
import {
  ATTR_SERVICE_NAME,
  ATTR_SERVICE_VERSION
} from "@opentelemetry/semantic-conventions"
 
export async function register() {
  const sdk = new NodeSDK({
    resource: resourceFromAttributes({
      [ATTR_SERVICE_NAME]: "web",
      [ATTR_SERVICE_VERSION]: process.env.NEXT_PUBLIC_APP_VERSION ?? "0.0.0",
      "greenslope.release.id":
        process.env.VERCEL_GIT_COMMIT_SHA ?? process.env.GIT_SHA ?? "local"
    }),
    traceExporter: new OTLPTraceExporter({
      url: "https://ingest.greenslope.io/v1/otel/v1/traces",
      headers: {
        "x-greenslope-key": process.env.GREENSLOPE_INGEST_KEY ?? ""
      }
    }),
    instrumentations: [getNodeAutoInstrumentations()]
  })
  sdk.start()
}

The three resource attributes are required:

See Release attribution for why all three matter.

4. Enable the hook in next.config.ts

// next.config.ts
import type { NextConfig } from "next"
 
const config: NextConfig = {
  // Nothing to add — Next.js 15 picks up instrumentation.ts automatically.
}
 
export default config

5. Send a test span

Start your dev server, then trigger any route in your app. That's enough — the auto-instrumentation captures incoming HTTP requests automatically, so you don't need to add a manual span.

pnpm dev
# visit http://localhost:3000 in a browser

Verify

Open your tenant dashboard at app.greenslope.io. Go to Live traces. You should see a span for GET / within ten seconds, tagged with service.name=web, your version, and your release ID.

If nothing shows up, jump to Troubleshooting: first trace doesn't arrive.

What to do next

Related