diff --git a/.gitignore b/.gitignore
index 6d114876..b139f739 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,5 @@ packages/node/test-data
yarn.lock
.exceptionless
+
+example/nextjs/.next/
diff --git a/example/nextjs/README.md b/example/nextjs/README.md
new file mode 100644
index 00000000..0155b247
--- /dev/null
+++ b/example/nextjs/README.md
@@ -0,0 +1,52 @@
+## Exceptionless for Next.js
+
+This example is a very small App Router site that shows the Exceptionless integration shape we want for a Next.js app: simple setup, rich metadata, and clear client/server error coverage.
+
+- `instrumentation-client.js` for browser startup and navigation logging
+- `instrumentation.js` for server startup and `onRequestError`
+- `app/error.jsx` for route-level client render failures
+- `app/global-error.jsx` for root-level client render failures
+- `app/api/demo/route.js` for explicit server-side logging from a route handler
+
+### What it covers
+
+- Manual client logs with structured data
+- Handled client exceptions submitted from a `try`/`catch`
+- Unhandled client promise rejections captured by the browser global handler
+- A client transition crash that lands in `app/error.jsx`
+- A server route log enriched with request headers, IP, path, query string, and JSON body
+- An unhandled route handler error captured by `onRequestError`
+- A server component render error captured by `onRequestError`
+
+### Why it is shaped this way
+
+This sticks to the native Next.js file boundaries instead of inventing another framework layer:
+
+- `instrumentation-client.js` is where client-side monitoring starts before the app becomes interactive.
+- `instrumentation.js` and `onRequestError` are where uncaught server render, route handler, server action, and proxy errors are captured.
+- `app/error.jsx` and `app/global-error.jsx` stay responsible for client render failures inside the App Router.
+- Route handlers submit logs directly with `Exceptionless.createLog(...)`, the environment module memoizes `Exceptionless.startup(...)`, and the server flushes with `Exceptionless.processQueue()` when needed.
+
+### Vercel-specific notes
+
+- The server helper flushes the Exceptionless queue explicitly. That matters for short-lived serverless runtimes where a background timer may not get enough time to send queued events.
+- The route handler uses `after()` so normal server logs flush after the response is sent.
+- The example imports `@exceptionless/browser` and `@exceptionless/node` directly and uses the default Next.js bundler behavior, which is Turbopack on Next 16.
+- Because this is a workspace example, you still need the root `npm run build` step before starting it locally so the SDK packages have fresh `dist/` output.
+- If we later package this for production ergonomics, the clean split is likely a very thin `@exceptionless/nextjs` helper for framework hooks plus an optional `@exceptionless/vercel` add-on for `@vercel/otel`, deployment metadata, and queue-flush helpers.
+
+### Environment variables
+
+Set the env vars you want the example to use:
+
+- `NEXT_PUBLIC_EXCEPTIONLESS_API_KEY`
+- `NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL`
+- `EXCEPTIONLESS_API_KEY`
+- `EXCEPTIONLESS_SERVER_URL`
+
+### Run locally
+
+1. `npm install`
+2. `npm run build`
+3. `cd example/nextjs`
+4. `npm run dev`
diff --git a/example/nextjs/app/api/demo/route.js b/example/nextjs/app/api/demo/route.js
new file mode 100644
index 00000000..e9d91b18
--- /dev/null
+++ b/example/nextjs/app/api/demo/route.js
@@ -0,0 +1,30 @@
+import { after } from "next/server";
+
+import { startup } from "../../../lib/exceptionless-server.js";
+import { buildRequestContextFromRequest } from "../../../lib/next-request.js";
+
+export async function POST(request) {
+ const parsedBody = await request.json().catch(() => ({}));
+ const body = typeof parsedBody === "object" && parsedBody !== null ? parsedBody : { value: parsedBody };
+ const mode = typeof body.mode === "string" ? body.mode : "log";
+
+ if (mode === "error") {
+ throw new Error("Route handler crash from the Exceptionless Next.js demo");
+ }
+
+ const { Exceptionless, KnownEventDataKeys } = await startup();
+
+ const builder = Exceptionless.createLog("nextjs.route", "Route handler log from the demo page", "info").addTags("route-handler");
+ builder.setContextProperty(KnownEventDataKeys.RequestInfo, buildRequestContextFromRequest(request, body));
+ await builder.submit();
+
+ after(async () => {
+ const { Exceptionless } = await startup();
+ await Exceptionless.processQueue();
+ });
+
+ return Response.json({
+ ok: true,
+ message: "Server route log submitted. The queue will flush in next/after()."
+ });
+}
diff --git a/example/nextjs/app/error.jsx b/example/nextjs/app/error.jsx
new file mode 100644
index 00000000..315571ce
--- /dev/null
+++ b/example/nextjs/app/error.jsx
@@ -0,0 +1,43 @@
+"use client";
+
+import Link from "next/link";
+import { useEffect } from "react";
+
+import { Exceptionless, startup } from "../lib/exceptionless-browser.js";
+
+export default function ErrorPage({ error, reset }) {
+ useEffect(() => {
+ if (!error.digest) {
+ void (async () => {
+ try {
+ await startup();
+ await Exceptionless.createException(error).addTags("error-boundary").setProperty("handledBy", "app/error.jsx").submit();
+ } catch (submitError) {
+ console.error("Exceptionless route boundary capture failed", submitError);
+ }
+ })();
+ }
+ }, [error]);
+
+ return (
+
+
+
+
Route Error Boundary
+
Something inside this route broke.
+
+ Client-only render errors are submitted here. Server-rendered failures already have a digest and are captured by `instrumentation.js` through
+ `onRequestError`.
+
+
+ reset()}>
+ Retry this route
+
+ Back to the example
+
+ {error.digest ?
Server digest: {error.digest}
: null}
+
+
+
+ );
+}
diff --git a/example/nextjs/app/global-error.jsx b/example/nextjs/app/global-error.jsx
new file mode 100644
index 00000000..e738eaba
--- /dev/null
+++ b/example/nextjs/app/global-error.jsx
@@ -0,0 +1,46 @@
+"use client";
+
+import Link from "next/link";
+import { useEffect } from "react";
+
+import { Exceptionless, startup } from "../lib/exceptionless-browser.js";
+
+export default function GlobalError({ error, reset }) {
+ useEffect(() => {
+ if (!error.digest) {
+ void (async () => {
+ try {
+ await startup();
+ await Exceptionless.createException(error).addTags("error-boundary").setProperty("handledBy", "app/global-error.jsx").submit();
+ } catch (submitError) {
+ console.error("Exceptionless global boundary capture failed", submitError);
+ }
+ })();
+ }
+ }, [error]);
+
+ return (
+
+
+
+
+
+
Global Error Boundary
+
The root layout failed.
+
+ This is the last-resort client boundary for the App Router. In normal server-rendered failures we still prefer the richer `onRequestError` path.
+
+
+ reset()}>
+ Retry the app shell
+
+ Back to the example
+
+ {error.digest ?
Server digest: {error.digest}
: null}
+
+
+
+
+
+ );
+}
diff --git a/example/nextjs/app/globals.css b/example/nextjs/app/globals.css
new file mode 100644
index 00000000..4eb0870c
--- /dev/null
+++ b/example/nextjs/app/globals.css
@@ -0,0 +1,249 @@
+:root {
+ color-scheme: light;
+ --bg: #f4efe7;
+ --surface: rgba(255, 255, 255, 0.78);
+ --surface-strong: rgba(255, 255, 255, 0.94);
+ --border: rgba(23, 29, 43, 0.12);
+ --text: #1b2130;
+ --muted: #5d6779;
+ --accent: #0f766e;
+ --accent-soft: rgba(15, 118, 110, 0.1);
+ --danger: #b42318;
+ --shadow: 0 20px 50px rgba(38, 45, 61, 0.12);
+}
+
+* {
+ box-sizing: border-box;
+}
+
+html,
+body {
+ margin: 0;
+ min-height: 100%;
+ font-family: "Geist", "IBM Plex Sans", "Avenir Next", system-ui, sans-serif;
+ background:
+ radial-gradient(circle at top left, rgba(15, 118, 110, 0.14), transparent 35%),
+ radial-gradient(circle at top right, rgba(210, 84, 30, 0.12), transparent 30%), var(--bg);
+ color: var(--text);
+}
+
+body {
+ line-height: 1.5;
+}
+
+a {
+ color: inherit;
+}
+
+button {
+ font: inherit;
+}
+
+.page {
+ width: min(1120px, calc(100vw - 32px));
+ margin: 0 auto;
+ padding: 48px 0 64px;
+}
+
+.hero {
+ display: grid;
+ gap: 16px;
+ margin-bottom: 28px;
+}
+
+.eyebrow {
+ margin: 0;
+ color: var(--accent);
+ font-size: 0.85rem;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+}
+
+.hero h1,
+.error-shell h1 {
+ margin: 0;
+ max-width: 12ch;
+ font-size: clamp(2.8rem, 7vw, 5.4rem);
+ line-height: 0.95;
+ letter-spacing: -0.05em;
+}
+
+.hero p,
+.error-shell p {
+ margin: 0;
+ max-width: 70ch;
+ color: var(--muted);
+ font-size: 1.02rem;
+}
+
+.hero-meta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.hero-meta span {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px 12px;
+ border: 1px solid var(--border);
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.55);
+ color: var(--muted);
+ font-size: 0.92rem;
+}
+
+.demo-grid {
+ display: grid;
+ gap: 20px;
+ grid-template-columns: minmax(0, 1.2fr) minmax(280px, 0.8fr);
+}
+
+.panel {
+ border: 1px solid var(--border);
+ border-radius: 24px;
+ background: var(--surface);
+ backdrop-filter: blur(10px);
+ box-shadow: var(--shadow);
+}
+
+.panel-body {
+ padding: 24px;
+}
+
+.panel h2 {
+ margin: 0 0 8px;
+ font-size: 1.3rem;
+ letter-spacing: -0.03em;
+}
+
+.panel p {
+ margin: 0;
+ color: var(--muted);
+}
+
+.button-grid {
+ display: grid;
+ gap: 12px;
+ margin-top: 18px;
+}
+
+.button-grid button,
+.button-grid a {
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+ align-items: center;
+ gap: 16px;
+ padding: 14px 16px;
+ border: 1px solid var(--border);
+ border-radius: 18px;
+ background: var(--surface-strong);
+ color: inherit;
+ cursor: pointer;
+ text-decoration: none;
+ transition:
+ transform 160ms ease,
+ border-color 160ms ease,
+ box-shadow 160ms ease;
+}
+
+.button-grid button:hover,
+.button-grid a:hover {
+ transform: translateY(-1px);
+ border-color: rgba(15, 118, 110, 0.3);
+ box-shadow: 0 12px 28px rgba(30, 34, 45, 0.09);
+}
+
+.button-grid button:disabled {
+ opacity: 0.7;
+ cursor: progress;
+ transform: none;
+}
+
+.button-label {
+ display: grid;
+ gap: 3px;
+ text-align: left;
+}
+
+.button-label strong {
+ font-size: 0.98rem;
+}
+
+.button-label span {
+ color: var(--muted);
+ font-size: 0.9rem;
+}
+
+.button-arrow {
+ color: var(--accent);
+ font-size: 1.2rem;
+}
+
+.status {
+ margin-top: 18px;
+ padding: 14px 16px;
+ border-radius: 18px;
+ background: var(--accent-soft);
+ color: var(--text);
+}
+
+.status strong {
+ display: block;
+ margin-bottom: 4px;
+ font-size: 0.95rem;
+}
+
+.note-list {
+ margin: 18px 0 0;
+ padding-left: 18px;
+ color: var(--muted);
+}
+
+.note-list li + li {
+ margin-top: 10px;
+}
+
+.error-shell {
+ min-height: 100vh;
+ display: grid;
+ place-items: center;
+ padding: 24px;
+}
+
+.error-card {
+ width: min(620px, 100%);
+}
+
+.error-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ margin-top: 22px;
+}
+
+.error-actions button,
+.error-actions a {
+ padding: 12px 16px;
+ border: 1px solid var(--border);
+ border-radius: 14px;
+ background: var(--surface-strong);
+ color: inherit;
+ text-decoration: none;
+ cursor: pointer;
+}
+
+.error-digest {
+ margin-top: 14px;
+ color: var(--muted);
+ font-size: 0.92rem;
+}
+
+@media (max-width: 900px) {
+ .demo-grid {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/example/nextjs/app/layout.jsx b/example/nextjs/app/layout.jsx
new file mode 100644
index 00000000..04740dab
--- /dev/null
+++ b/example/nextjs/app/layout.jsx
@@ -0,0 +1,14 @@
+import "./globals.css";
+
+export const metadata = {
+ title: "Exceptionless for Next.js",
+ description: "A small reference app for Exceptionless client and server monitoring in Next.js."
+};
+
+export default function RootLayout({ children }) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/example/nextjs/app/page.jsx b/example/nextjs/app/page.jsx
new file mode 100644
index 00000000..cefcc686
--- /dev/null
+++ b/example/nextjs/app/page.jsx
@@ -0,0 +1,42 @@
+import ClientDemoPanel from "../components/ClientDemoPanel.jsx";
+
+export default function HomePage() {
+ const deploymentTarget = process.env.VERCEL_ENV ?? "local";
+
+ return (
+
+
+ Exceptionless for Next.js
+ Client and server monitoring for Next.js.
+
+ This reference app keeps the setup small, but still captures the important Exceptionless signals across browser and server paths: logs, handled
+ errors, unhandled errors, request metadata, and App Router error boundaries.
+
+
+ Deployment target: {deploymentTarget}
+ App Router reference integration
+
+
+
+
+
+
+
+
+
What the integration covers
+
+ The client path uses browser startup plus route boundaries. The server path uses `onRequestError`, explicit queue flushes, and a small request
+ adapter so Exceptionless can attach rich request metadata to the same event builders we already use elsewhere.
+
+
+ `instrumentation-client.js` starts Exceptionless before the app becomes interactive and logs route transitions.
+ `app/error.jsx` captures client-side render failures, but skips digest-backed server render errors to avoid duplicates.
+ `instrumentation.js` registers the node client once per server instance and captures uncaught render and route errors.
+ `app/api/demo/route.js` shows explicit server logging with request metadata plus `after()` for a Vercel-friendly flush.
+
+
+
+
+
+ );
+}
diff --git a/example/nextjs/app/server-component-error/page.jsx b/example/nextjs/app/server-component-error/page.jsx
new file mode 100644
index 00000000..a52d196a
--- /dev/null
+++ b/example/nextjs/app/server-component-error/page.jsx
@@ -0,0 +1,5 @@
+export const dynamic = "force-dynamic";
+
+export default function ServerComponentErrorPage() {
+ throw new Error("Server component crash from the Exceptionless Next.js demo");
+}
diff --git a/example/nextjs/components/ClientDemoPanel.jsx b/example/nextjs/components/ClientDemoPanel.jsx
new file mode 100644
index 00000000..b73583c2
--- /dev/null
+++ b/example/nextjs/components/ClientDemoPanel.jsx
@@ -0,0 +1,156 @@
+"use client";
+
+import Link from "next/link";
+import { useState, useTransition } from "react";
+
+import { Exceptionless, startup } from "../lib/exceptionless-browser.js";
+
+export default function ClientDemoPanel() {
+ const [status, setStatus] = useState("Ready. Pick any path below to generate client or server telemetry.");
+ const [pending, startTransition] = useTransition();
+
+ async function sendClientLog() {
+ setStatus("Submitting a structured client log...");
+
+ await startup();
+
+ await Exceptionless.createLog("nextjs.client", "Client log from the demo page", "info")
+ .addTags("manual-log")
+ .setProperty("currentUrl", window.location.href)
+ .setProperty("timezone", Intl.DateTimeFormat().resolvedOptions().timeZone)
+ .submit();
+
+ setStatus("Client log submitted.");
+ }
+
+ async function sendHandledClientError() {
+ setStatus("Submitting a handled client error...");
+
+ try {
+ throw new Error("Handled client error from the Exceptionless Next.js demo");
+ } catch (error) {
+ await startup();
+
+ await Exceptionless.createException(error)
+ .addTags("handled-error")
+ .setProperty("handledBy", "ClientDemoPanel.handleTryCatch")
+ .setProperty("currentUrl", window.location.href)
+ .submit();
+ }
+
+ setStatus("Handled client error submitted.");
+ }
+
+ function triggerUnhandledRejection() {
+ setStatus("Triggered an unhandled promise rejection. The browser global handler should capture it.");
+ Promise.reject(new Error("Unhandled promise rejection from the Exceptionless Next.js demo"));
+ }
+
+ function triggerBoundaryCrash() {
+ setStatus("Crashing the route boundary...");
+
+ startTransition(() => {
+ throw new Error("Client transition crash from the Exceptionless Next.js demo");
+ });
+ }
+
+ async function callServerRoute(mode) {
+ setStatus(mode === "error" ? "Triggering a route handler crash..." : "Submitting a route handler log...");
+
+ const response = await fetch("/api/demo", {
+ method: "POST",
+ headers: {
+ "content-type": "application/json"
+ },
+ body: JSON.stringify({
+ mode,
+ triggeredFrom: "ClientDemoPanel",
+ currentUrl: window.location.href,
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
+ })
+ });
+
+ if (!response.ok) {
+ setStatus(`Route handler error triggered with HTTP ${response.status}. The server onRequestError hook should capture it.`);
+ return;
+ }
+
+ const payload = await response.json();
+ setStatus(payload.message);
+ }
+
+ return (
+
+
+
Try the integration
+
+ The first four buttons stay in the browser. The next two go through a real Next route handler. The link at the bottom opens a route that throws during
+ server rendering.
+
+
+
+ void sendClientLog()} disabled={pending}>
+
+ Send client log
+ Manual log event with URL and timezone metadata.
+
+ +
+
+
+ void sendHandledClientError()} disabled={pending}>
+
+ Send handled client error
+ Manual exception capture from a local try/catch block.
+
+ +
+
+
+
+
+ Trigger unhandled rejection
+ Exercises the browser global handler installed during startup.
+
+ !
+
+
+
+
+ Crash the route boundary
+ Throws inside a transition so `app/error.jsx` catches it.
+
+ !
+
+
+ void callServerRoute("log")} disabled={pending}>
+
+ Send server route log
+ Hits `/api/demo` and enriches the log with request data.
+
+ +
+
+
+ void callServerRoute("error")} disabled={pending}>
+
+ Trigger route handler error
+ Throws in `/api/demo` so `instrumentation.js` captures it.
+
+ !
+
+
+
+
+ Open the server component error route
+ Exercises the App Router render path and `onRequestError`.
+
+ →
+
+
+
+
+ Latest status
+ {status}
+
+
+
+ );
+}
diff --git a/example/nextjs/instrumentation-client.js b/example/nextjs/instrumentation-client.js
new file mode 100644
index 00000000..224c4294
--- /dev/null
+++ b/example/nextjs/instrumentation-client.js
@@ -0,0 +1,23 @@
+import { Exceptionless, startup } from "./lib/exceptionless-browser.js";
+
+void startup().catch((error) => {
+ console.error("Exceptionless browser startup failed", error);
+});
+
+export function onRouterTransitionStart(url, navigationType) {
+ void recordRouterTransitionStart(url, navigationType);
+}
+
+async function recordRouterTransitionStart(url, navigationType) {
+ try {
+ await startup();
+
+ await Exceptionless.createLog("nextjs.navigation", "Route transition started", "info")
+ .addTags("navigation")
+ .setProperty("navigationType", navigationType)
+ .setProperty("url", url)
+ .submit();
+ } catch (error) {
+ console.error("Exceptionless navigation tracking failed", error);
+ }
+}
diff --git a/example/nextjs/instrumentation.js b/example/nextjs/instrumentation.js
new file mode 100644
index 00000000..28da1f81
--- /dev/null
+++ b/example/nextjs/instrumentation.js
@@ -0,0 +1,35 @@
+import { buildRequestContextFromOnRequestError } from "./lib/next-request.js";
+
+export async function register() {
+ if (process.env.NEXT_RUNTIME !== "nodejs") {
+ return;
+ }
+
+ const { startup } = await import("./lib/exceptionless-server.js");
+ await startup();
+}
+
+export async function onRequestError(error, request, context) {
+ if (process.env.NEXT_RUNTIME !== "nodejs") {
+ return;
+ }
+
+ const { startup } = await import("./lib/exceptionless-server.js");
+ const digest = typeof error === "object" && error !== null && "digest" in error ? error.digest : undefined;
+
+ const { Exceptionless, KnownEventDataKeys, toError } = await startup();
+
+ const builder = Exceptionless.createUnhandledException(toError(error), `nextjs.${context.routeType}`).addTags("on-request-error");
+
+ builder.setContextProperty(KnownEventDataKeys.RequestInfo, buildRequestContextFromOnRequestError(request));
+ builder.setProperty("digest", digest);
+ builder.setProperty("routePath", context.routePath);
+ builder.setProperty("routeType", context.routeType);
+ builder.setProperty("routerKind", context.routerKind);
+ builder.setProperty("renderSource", context.renderSource);
+ builder.setProperty("renderType", context.renderType);
+ builder.setProperty("revalidateReason", context.revalidateReason);
+
+ await builder.submit();
+ await Exceptionless.processQueue();
+}
diff --git a/example/nextjs/lib/exceptionless-browser.js b/example/nextjs/lib/exceptionless-browser.js
new file mode 100644
index 00000000..64a152cd
--- /dev/null
+++ b/example/nextjs/lib/exceptionless-browser.js
@@ -0,0 +1,52 @@
+import { Exceptionless, KnownEventDataKeys } from "@exceptionless/browser";
+
+export { Exceptionless };
+
+let startupPromise;
+
+export function startup() {
+ startupPromise ??= Exceptionless.startup((config) => {
+ if (process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY) {
+ config.apiKey = process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY;
+ }
+
+ if (process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL) {
+ config.serverUrl = process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL;
+ }
+
+ if (process.env.NODE_ENV !== "production") {
+ config.useDebugLogger();
+ }
+
+ config.addDataExclusions("authorization", "cookie", "password", "set-cookie", "token");
+ config.defaultTags.push("Example", "nextjs", "client");
+ config.addPlugin({
+ priority: 90,
+ name: "NextEnvironmentInfoPlugin",
+ run(context) {
+ const eventData = context.event.data ?? {};
+ context.event.data = eventData;
+
+ const environment =
+ typeof eventData[KnownEventDataKeys.EnvironmentInfo] === "object" && eventData[KnownEventDataKeys.EnvironmentInfo] !== null
+ ? eventData[KnownEventDataKeys.EnvironmentInfo]
+ : {};
+ const environmentData = typeof environment.data === "object" && environment.data !== null ? environment.data : {};
+
+ eventData[KnownEventDataKeys.EnvironmentInfo] = {
+ ...environment,
+ data: {
+ ...environmentData,
+ framework: "Next.js",
+ router: "App Router",
+ runtime: "browser"
+ }
+ };
+
+ return Promise.resolve();
+ }
+ });
+ });
+
+ return startupPromise;
+}
diff --git a/example/nextjs/lib/exceptionless-server.js b/example/nextjs/lib/exceptionless-server.js
new file mode 100644
index 00000000..941ef68d
--- /dev/null
+++ b/example/nextjs/lib/exceptionless-server.js
@@ -0,0 +1,60 @@
+import { Exceptionless, KnownEventDataKeys, toError } from "@exceptionless/node";
+
+export { Exceptionless, KnownEventDataKeys, toError };
+
+let startupPromise;
+
+export async function startup() {
+ startupPromise ??= Exceptionless.startup((config) => {
+ const apiKey = (process.env.EXCEPTIONLESS_API_KEY || process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY || "").trim();
+ if (apiKey) {
+ config.apiKey = apiKey;
+ }
+
+ const serverUrl = (process.env.EXCEPTIONLESS_SERVER_URL || process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL || "").trim();
+ if (serverUrl) {
+ config.serverUrl = serverUrl;
+ }
+
+ if (process.env.NODE_ENV !== "production") {
+ config.useDebugLogger();
+ }
+
+ config.addDataExclusions("authorization", "cookie", "password", "set-cookie", "token");
+ config.defaultTags.push("Example", "nextjs", "server");
+ config.addPlugin({
+ priority: 90,
+ name: "NextEnvironmentInfoPlugin",
+ run(context) {
+ const eventData = context.event.data ?? {};
+ context.event.data = eventData;
+
+ const environment =
+ typeof eventData[KnownEventDataKeys.EnvironmentInfo] === "object" && eventData[KnownEventDataKeys.EnvironmentInfo] !== null
+ ? eventData[KnownEventDataKeys.EnvironmentInfo]
+ : {};
+ const environmentData = typeof environment.data === "object" && environment.data !== null ? environment.data : {};
+
+ eventData[KnownEventDataKeys.EnvironmentInfo] = {
+ ...environment,
+ data: {
+ ...environmentData,
+ framework: "Next.js",
+ router: "App Router",
+ runtime: "nodejs",
+ ...((process.env.VERCEL_ENV ?? process.env.NODE_ENV) ? { deployment: process.env.VERCEL_ENV ?? process.env.NODE_ENV } : {}),
+ ...(process.env.VERCEL_REGION ? { region: process.env.VERCEL_REGION } : {}),
+ ...(process.env.VERCEL_URL ? { url: process.env.VERCEL_URL } : {}),
+ ...(process.env.VERCEL_GIT_COMMIT_SHA ? { commit: process.env.VERCEL_GIT_COMMIT_SHA } : {})
+ }
+ };
+
+ return Promise.resolve();
+ }
+ });
+ });
+
+ await startupPromise;
+
+ return { Exceptionless, KnownEventDataKeys, toError };
+}
diff --git a/example/nextjs/lib/next-request.js b/example/nextjs/lib/next-request.js
new file mode 100644
index 00000000..8e5d0ce9
--- /dev/null
+++ b/example/nextjs/lib/next-request.js
@@ -0,0 +1,56 @@
+export function buildRequestContextFromRequest(request, body) {
+ return buildRequestContext({
+ method: request.method,
+ pathOrUrl: request.url,
+ headers: request.headers,
+ body
+ });
+}
+
+export function buildRequestContextFromOnRequestError(request) {
+ return buildRequestContext({
+ method: request.method,
+ pathOrUrl: request.path,
+ headers: request.headers
+ });
+}
+
+export function buildRequestContext({ method, pathOrUrl, headers, body }) {
+ const normalizedHeaders = normalizeHeaders(headers);
+ const origin = getOrigin(normalizedHeaders);
+ const url = new URL(pathOrUrl, origin);
+
+ return {
+ method,
+ secure: url.protocol === "https:",
+ ip: getClientIp(normalizedHeaders),
+ hostname: url.hostname,
+ path: url.pathname,
+ headers: normalizedHeaders,
+ params: Object.fromEntries(url.searchParams.entries()),
+ body
+ };
+}
+
+function normalizeHeaders(headers) {
+ if (headers instanceof Headers) {
+ return Object.fromEntries(Array.from(headers.entries()).map(([key, value]) => [key.toLowerCase(), value]));
+ }
+
+ return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), Array.isArray(value) ? value.join(", ") : String(value)]));
+}
+
+function getOrigin(headers) {
+ const host = headers["x-forwarded-host"] ?? headers.host ?? "localhost";
+ const protocol = headers["x-forwarded-proto"] ?? "http";
+ return `${protocol}://${host}`;
+}
+
+function getClientIp(headers) {
+ const forwardedFor = headers["x-forwarded-for"];
+ if (forwardedFor) {
+ return forwardedFor.split(",")[0]?.trim() ?? "";
+ }
+
+ return headers["x-real-ip"] ?? "";
+}
diff --git a/example/nextjs/package.json b/example/nextjs/package.json
new file mode 100644
index 00000000..d050a307
--- /dev/null
+++ b/example/nextjs/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "nextjs-example",
+ "private": true,
+ "version": "3.0.0-dev",
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "@exceptionless/browser": "3.0.0-dev",
+ "@exceptionless/node": "3.0.0-dev",
+ "next": "^16.2.1",
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4"
+ },
+ "type": "module",
+ "publishConfig": {
+ "access": "restricted"
+ }
+}
diff --git a/example/nextjs/test/next-request.test.js b/example/nextjs/test/next-request.test.js
new file mode 100644
index 00000000..7a5a527c
--- /dev/null
+++ b/example/nextjs/test/next-request.test.js
@@ -0,0 +1,73 @@
+import { describe, expect, test } from "vitest";
+
+import { buildRequestContextFromOnRequestError, buildRequestContextFromRequest } from "../lib/next-request.js";
+
+describe("next request adapter", () => {
+ test("builds request info from a web request", () => {
+ const request = new Request("https://demo.exceptionless.dev/api/demo?mode=log&ref=homepage", {
+ method: "POST",
+ headers: {
+ "content-type": "application/json",
+ "user-agent": "Vitest Browser",
+ "x-forwarded-for": "203.0.113.10, 10.0.0.5"
+ }
+ });
+
+ const result = buildRequestContextFromRequest(request, {
+ mode: "log",
+ triggeredFrom: "test"
+ });
+
+ expect(result).toEqual({
+ method: "POST",
+ secure: true,
+ ip: "203.0.113.10",
+ hostname: "demo.exceptionless.dev",
+ path: "/api/demo",
+ headers: {
+ "content-type": "application/json",
+ "user-agent": "Vitest Browser",
+ "x-forwarded-for": "203.0.113.10, 10.0.0.5"
+ },
+ params: {
+ mode: "log",
+ ref: "homepage"
+ },
+ body: {
+ mode: "log",
+ triggeredFrom: "test"
+ }
+ });
+ });
+
+ test("builds request info from the onRequestError payload", () => {
+ const result = buildRequestContextFromOnRequestError({
+ path: "/server-component-error?from=test",
+ method: "GET",
+ headers: {
+ host: "localhost:3000",
+ "user-agent": "Vitest Server",
+ "x-forwarded-proto": "https",
+ "x-real-ip": "127.0.0.1"
+ }
+ });
+
+ expect(result).toEqual({
+ method: "GET",
+ secure: true,
+ ip: "127.0.0.1",
+ hostname: "localhost",
+ path: "/server-component-error",
+ headers: {
+ host: "localhost:3000",
+ "user-agent": "Vitest Server",
+ "x-forwarded-proto": "https",
+ "x-real-ip": "127.0.0.1"
+ },
+ params: {
+ from: "test"
+ },
+ body: undefined
+ });
+ });
+});
diff --git a/package-lock.json b/package-lock.json
index 955d9984..91fe8b3b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -49,6 +49,17 @@
"express": "^5.2.1"
}
},
+ "example/nextjs": {
+ "name": "nextjs-example",
+ "version": "3.0.0-dev",
+ "dependencies": {
+ "@exceptionless/browser": "3.0.0-dev",
+ "@exceptionless/node": "3.0.0-dev",
+ "next": "^16.2.1",
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4"
+ }
+ },
"example/react": {
"name": "react-example",
"version": "3.0.0-dev",
@@ -383,7 +394,6 @@
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz",
"integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==",
- "dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1016,35 +1026,549 @@
"@humanwhocodes/retry": "^0.4.0"
},
"engines": {
- "node": ">=18.18.0"
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@img/colour": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
+ "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true,
- "license": "Apache-2.0",
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
"engines": {
- "node": ">=12.22"
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
+ "url": "https://opencollective.com/libvips"
}
},
- "node_modules/@humanwhocodes/retry": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
- "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
- "dev": true,
- "license": "Apache-2.0",
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
"engines": {
- "node": ">=18.18"
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
}
},
"node_modules/@jridgewell/gen-mapping": {
@@ -1096,6 +1620,152 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@next/env": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.1.tgz",
+ "integrity": "sha512-n8P/HCkIWW+gVal2Z8XqXJ6aB3J0tuM29OcHpCsobWlChH/SITBs1DFBk/HajgrwDkqqBXPbuUuzgDvUekREPg==",
+ "license": "MIT"
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.1.tgz",
+ "integrity": "sha512-BwZ8w8YTaSEr2HIuXLMLxIdElNMPvY9fLqb20LX9A9OMGtJilhHLbCL3ggyd0TwjmMcTxi0XXt+ur1vWUoxj2Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.1.tgz",
+ "integrity": "sha512-/vrcE6iQSJq3uL3VGVHiXeaKbn8Es10DGTGRJnRZlkNQQk3kaNtAJg8Y6xuAlrx/6INKVjkfi5rY0iEXorZ6uA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.1.tgz",
+ "integrity": "sha512-uLn+0BK+C31LTVbQ/QU+UaVrV0rRSJQ8RfniQAHPghDdgE+SlroYqcmFnO5iNjNfVWCyKZHYrs3Nl0mUzWxbBw==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.1.tgz",
+ "integrity": "sha512-ssKq6iMRnHdnycGp9hCuGnXJZ0YPr4/wNwrfE5DbmvEcgl9+yv97/Kq3TPVDfYome1SW5geciLB9aiEqKXQjlQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.1.tgz",
+ "integrity": "sha512-HQm7SrHRELJ30T1TSmT706IWovFFSRGxfgUkyWJZF/RKBMdbdRWJuFrcpDdE5vy9UXjFOx6L3mRdqH04Mmx0hg==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.1.tgz",
+ "integrity": "sha512-aV2iUaC/5HGEpbBkE+4B8aHIudoOy5DYekAKOMSHoIYQ66y/wIVeaRx8MS2ZMdxe/HIXlMho4ubdZs/J8441Tg==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.1.tgz",
+ "integrity": "sha512-IXdNgiDHaSk0ZUJ+xp0OQTdTgnpx1RCfRTalhn3cjOP+IddTMINwA7DXZrwTmGDO8SUr5q2hdP/du4DcrB1GxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.1.tgz",
+ "integrity": "sha512-qvU+3a39Hay+ieIztkGSbF7+mccbbg1Tk25hc4JDylf8IHjYmY/Zm64Qq1602yPyQqvie+vf5T/uPwNxDNIoeg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/@oxc-project/types": {
"version": "0.122.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz",
@@ -1888,6 +2558,15 @@
"vite": "^8.0.0-beta.7 || ^8.0.0"
}
},
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
"node_modules/@testing-library/react": {
"version": "16.3.2",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz",
@@ -2688,6 +3367,18 @@
"node": "18 || 20 || >=22"
}
},
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.10",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.10.tgz",
+ "integrity": "sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ==",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/body-parser": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
@@ -2777,6 +3468,26 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001781",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz",
+ "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
"node_modules/chai": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
@@ -2813,6 +3524,12 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -2984,7 +3701,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "dev": true,
+ "devOptional": true,
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -4416,6 +5133,91 @@
"node": ">= 0.6"
}
},
+ "node_modules/next": {
+ "version": "16.2.1",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.2.1.tgz",
+ "integrity": "sha512-VaChzNL7o9rbfdt60HUj8tev4m6d7iC1igAy157526+cJlXOQu5LzsBXNT+xaJnTP/k+utSX5vMv7m0G+zKH+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@next/env": "16.2.1",
+ "@swc/helpers": "0.5.15",
+ "baseline-browser-mapping": "^2.9.19",
+ "caniuse-lite": "^1.0.30001579",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.6"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "16.2.1",
+ "@next/swc-darwin-x64": "16.2.1",
+ "@next/swc-linux-arm64-gnu": "16.2.1",
+ "@next/swc-linux-arm64-musl": "16.2.1",
+ "@next/swc-linux-x64-gnu": "16.2.1",
+ "@next/swc-linux-x64-musl": "16.2.1",
+ "@next/swc-win32-arm64-msvc": "16.2.1",
+ "@next/swc-win32-x64-msvc": "16.2.1",
+ "sharp": "^0.34.5"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "@playwright/test": "^1.51.1",
+ "babel-plugin-react-compiler": "*",
+ "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@playwright/test": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/next/node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/nextjs-example": {
+ "resolved": "example/nextjs",
+ "link": true
+ },
"node_modules/node-localstorage": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-3.0.5.tgz",
@@ -5070,7 +5872,7 @@
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
- "dev": true,
+ "devOptional": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -5137,6 +5939,51 @@
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
+ "node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -5373,6 +6220,29 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/styled-jsx": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
+ "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
+ "license": "MIT",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
"node_modules/svelte": {
"version": "5.55.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.0.tgz",
@@ -5592,9 +6462,7 @@
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "dev": true,
- "license": "0BSD",
- "optional": true
+ "license": "0BSD"
},
"node_modules/type-check": {
"version": "0.4.0",
diff --git a/package.json b/package.json
index b37f2d6d..0e60eadc 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"version": "3.0.0-dev",
"license": "Apache-2.0",
"scripts": {
- "clean": "rimraf -g packages/*/dist example/*/dist",
+ "clean": "rimraf -g packages/*/dist example/*/dist example/*/.next",
"build": "npm run build --workspaces --if-present",
"watch": "npm run watch --workspaces --if-present",
"lint": "run-s -c lint:eslint lint:prettier",
diff --git a/vitest.config.ts b/vitest.config.ts
index 1c4a84a5..b08faf39 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -58,6 +58,13 @@ export default defineConfig({
"@exceptionless/core": path.resolve(__dirname, "packages/core/src")
}
}
+ },
+ {
+ test: {
+ name: "nextjs-example",
+ root: "example/nextjs",
+ environment: "node"
+ }
}
]
}