Installation - Next.js
Before you start, create a project in the DockRay panel. Its settings hold the project token - the public identifier that goes into the ingest URL - and the API keys tab is where you generate a private key. The key is shown once, when it is generated: DockRay stores only its hash. If you do not have a project yet, start with Getting Started.
Requirements
- Next.js 14 or 15, App Router or Pages Router,
- Node.js 18 or newer - the integration uses the built-in
fetch, - npm.
Installing the package
npm install @dockcodes/dock-ray-next
Credentials
RAY_TOKEN=project-token
RAY_PRIVATE_KEY=project-private-key
RAY_URL=https://dockray.io
RAY_TRACES_SAMPLE_RATE=0.2
RAY_PRIVATE_KEY must never get a NEXT_PUBLIC_ prefix - and this is not a style choice. Next inlines every variable with that prefix straight into the bundle shipped to the browser, so the private key would become public the moment you build. Without RAY_TOKEN and RAY_PRIVATE_KEY the integration stays inert - no requests, no errors - so you can wire it once and never wrap it in a condition.
Server error reporting
In instrumentation.ts at the project root:
import { initRay, rayRequestError } from '@dockcodes/dock-ray-next';
export function register() {
initRay();
}
export const onRequestError = rayRequestError();
onRequestError is the only hook that sees every error Next catches - from Server Components, Route Handlers, Server Actions and streaming renders. Next calls it once the response has already failed, so reporting never delays a request. Every report is tagged with the route context (router, route, route_type, render_source), which is what lets the panel show where an error actually came from.
Middleware and the Edge Runtime
Next always builds middleware as an edge bundle, and an edge bundle cannot resolve node:fs or node:zlib. Middleware and edge routes import a separate entry point:
import { initRay, withRayMiddleware } from '@dockcodes/dock-ray-next/edge';
initRay();
export const middleware = withRayMiddleware(async (request) => {
// ...
});
Edge events lose stack source context and gzip compression - nothing else changes. The edge wrapper awaits its report instead of firing and forgetting: an edge invocation can be frozen the moment the function returns, so an unfinished send might never leave.
Pages Router and API routes
onRequestError covers the App Router. For the Pages Router, or anywhere you want an error explicitly marked as yours, use the wrapper:
import { withRay } from '@dockcodes/dock-ray-next';
export default withRay(async function handler(req, res) {
const order = await processOrder(req.body);
res.status(200).json({ success: true, order });
});
withRay reports and rethrows the error - it never swallows it, so your own error handling still runs.
The first test
import { getRay } from '@dockcodes/dock-ray-next';
await getRay().captureMessage('DockRay control message');
Call this from a temporary route or a Server Action on a staging environment. The message should appear in the panel under Errors for the project the token points at.