Next.js
Next.js
Section titled “Next.js”5-minute integration for Next.js 14+. App Router is the recommended path; Pages Router is covered after.
1. Install
Section titled “1. Install”bun add @goliapkg/sentori-next# orpnpm add @goliapkg/sentori-next2. Environment
Section titled “2. Environment”.env.local:
NEXT_PUBLIC_SENTORI_TOKEN=st_pk_...NEXT_PUBLIC_SENTORI_RELEASE=myapp@1.2.3NEXT_PUBLIC_SENTORI_ENVIRONMENT=prodNEXT_PUBLIC_* is required so the SDK can read them on the browser
side. Optional server-only overrides (SENTORI_TOKEN, etc.) let you
differentiate server traffic on the dashboard.
3. App Router
Section titled “3. App Router”3a. instrumentation.ts
Section titled “3a. instrumentation.ts”// instrumentation.ts (project root)export { register, onRequestError } from '@goliapkg/sentori-next/instrumentation'That’s the entire server wiring. register() boots the SDK on Node
start; onRequestError captures every server-side request error
with route + method tags. The edge runtime is skipped automatically.
3b. app/layout.tsx
Section titled “3b. app/layout.tsx”'use client'import { clientInit, SentoriProvider } from '@goliapkg/sentori-next/client'
clientInit() // reads NEXT_PUBLIC_SENTORI_*
export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <SentoriProvider config={configFromEnv()}>{children}</SentoriProvider> </body> </html> )}
function configFromEnv() { return { token: process.env.NEXT_PUBLIC_SENTORI_TOKEN!, release: process.env.NEXT_PUBLIC_SENTORI_RELEASE!, environment: process.env.NEXT_PUBLIC_SENTORI_ENVIRONMENT ?? 'prod', }}3c. app/error.tsx
Section titled “3c. app/error.tsx”'use client'import { useReportNextError } from '@goliapkg/sentori-next/app-router'
export default function Error({ error, reset,}: { error: Error & { digest?: string } reset: () => void}) { useReportNextError(error) return ( <div> <h2>Something went wrong</h2> <button onClick={reset} type="button">Try again</button> </div> )}For a global catch-all that wraps the root layout too, drop the same
component into app/global-error.tsx.
3d. Optional — navigation breadcrumbs
Section titled “3d. Optional — navigation breadcrumbs”// app/Shell.tsx — thin client wrapper used by app/layout.tsx'use client'import { useNextRouter } from '@goliapkg/sentori-next/app-router'
export function Shell({ children }: { children: React.ReactNode }) { useNextRouter() return <>{children}</>}4. Pages Router
Section titled “4. Pages Router”4a. pages/_app.tsx
Section titled “4a. pages/_app.tsx”import { clientInit, SentoriProvider } from '@goliapkg/sentori-next/client'
clientInit()
export default function MyApp({ Component, pageProps }) { return ( <SentoriProvider config={configFromEnv()}> <Component {...pageProps} /> </SentoriProvider> )}4b. pages/_error.tsx
Section titled “4b. pages/_error.tsx”import { useCaptureError } from '@goliapkg/sentori-next/client'import { useEffect } from 'react'
export default function ErrorPage({ statusCode }: { statusCode: number }) { const capture = useCaptureError() useEffect(() => { capture(new Error(`Pages Router ${statusCode}`), { tags: { source: 'next.pages._error' }, }) }, [capture, statusCode]) return <p>Sorry — something broke ({statusCode}).</p>}4c. pages/api/* — route handlers
Section titled “4c. pages/api/* — route handlers”instrumentation.ts from §3a covers Pages API routes too — Next
forwards both Pages and App Router errors through the same
onRequestError hook.
5. Source maps
Section titled “5. Source maps”5a. Generate them
Section titled “5a. Generate them”next.config.js:
module.exports = { productionBrowserSourceMaps: true,}Server-side maps are generated by default. After next build, the
maps live in .next/static/chunks/*.map (browser) and
.next/server/**/*.map (server).
5b. Upload from CI
Section titled “5b. Upload from CI”sentori-cli upload sourcemap takes a release name + a file or
directory and walks it for .js / .js.map pairs.
sentori-cli upload sourcemap \ --release "myapp@$(git rev-parse --short HEAD)" \ --token "$SENTORI_TOKEN" \ --ingest-url "$SENTORI_INGEST_URL" \ .next/static/chunks/5c. GitHub Actions
Section titled “5c. GitHub Actions”.github/workflows/deploy.yml:
name: Deployon: push: branches: [main]jobs: build-and-upload: runs-on: ubuntu-latest env: SENTORI_TOKEN: ${{ secrets.SENTORI_TOKEN }} SENTORI_INGEST_URL: https://ingest.sentori.golia.jp NEXT_PUBLIC_SENTORI_TOKEN: ${{ secrets.SENTORI_TOKEN }} NEXT_PUBLIC_SENTORI_RELEASE: myapp@${{ github.sha }} NEXT_PUBLIC_SENTORI_ENVIRONMENT: prod steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile - run: bun run build - name: Install sentori-cli run: | curl -fsSL https://cdn.sentori.golia.jp/install-cli.sh | bash echo "$HOME/.sentori/bin" >> "$GITHUB_PATH" - name: Upload sourcemaps run: | sentori-cli upload sourcemap \ --release "myapp@${{ github.sha }}" \ .next/static/chunks/ # ... your deploy step (Vercel CLI, AWS, Cloudflare Pages, ...)What gets captured
Section titled “What gets captured”| Surface | Caught by |
|---|---|
| Server Components / RSC throws | instrumentation.ts:onRequestError |
Route handlers (app/api/*/route.ts) | instrumentation.ts:onRequestError |
Pages Router API (pages/api/*) | instrumentation.ts:onRequestError |
| Client component renders | app/error.tsx → useReportNextError |
| Unhandled browser errors / promises | JS SDK global hooks (clientInit) |