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-conventionsEverything 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:
service.name— what this service is called. One per deployable.service.version— human-readable version, e.g.2026.4.21.greenslope.release.id— a stable ID for the deployed build, usually a git SHA. This is what powers release attribution.
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 config5. 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 browserVerify
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