jacquardSnapshot

← snapshot

1280 bytes
"use client";

import { useReportWebVitals } from "next/web-vitals";

const KNOWN = new Set(["CLS", "FCP", "INP", "LCP", "TTFB"]);

/**
 * Relays Core Web Vitals to jac-serve, which re-emits them as the
 * `web_vitals` event shape the s10 console's Performance page groups by
 * page (`context.pathname`). Uses Next's built-in reporting hook rather
 * than a new dependency — it already wraps the standard `web-vitals`
 * library. Best-effort: a failed beacon is dropped, never retried or
 * surfaced, matching the shipper's own silent-on-failure invariant.
 */
export function WebVitalsReporter() {
  useReportWebVitals((metric) => {
    if (!KNOWN.has(metric.name)) return;
    const body = JSON.stringify({
      name: metric.name,
      value: metric.value,
      pathname: window.location.pathname,
    });
    const sent =
      "sendBeacon" in navigator &&
      navigator.sendBeacon("/api/telemetry/web-vitals", new Blob([body], { type: "application/json" }));
    if (!sent) {
      fetch("/api/telemetry/web-vitals", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body,
        keepalive: true,
      }).catch(() => {
        // best-effort — a dropped metric is not worth surfacing
      });
    }
  });
  return null;
}