npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

featurely-error-tracker

v1.1.0

Published

Advanced error tracking SDK for Featurely with breadcrumbs, device info, and complete context

Readme

featurely-error-tracker

⚠️ CRITICAL UPDATE (v1.0.23): Fixes infinite error reporting loop. If you're experiencing error spam or rapid-fire API requests, update immediately. See FIXES.md for details.

Advanced error tracking SDK for JavaScript and TypeScript. Automatically captures unhandled errors and promise rejections with full context: breadcrumbs, device info, network conditions, and performance metrics. Errors appear in the Featurely dashboard with stack traces and reproduction context.

Installation

npm install featurely-error-tracker

Required API key permission: errors:write

Quick Start

import { ErrorTracker } from "featurely-error-tracker";

const tracker = new ErrorTracker({
  apiKey: "ft_live_your_api_key_here",
  environment: "production",
  appVersion: "1.0.0",
});

tracker.install(); // registers window.onerror + unhandledrejection
tracker.setUser(user.id, user.email); // call after login

Configuration

ErrorTrackerConfig

| Option | Type | Default | Description | | ---------------- | ----------------------------------------------- | ------------------------------------------------- | ----------------------------------------- | | apiKey | string | required | API key with errors:write permission | | environment | "development" \| "staging" \| "production" | — | Environment tag attached to every error | | appVersion | string | — | Application version string | | releaseId | string | — | Release identifier (e.g. git commit hash) | | apiUrl | string | "https://www.featurely.no/api/public/v1/errors" | Custom API endpoint | | maxBreadcrumbs | number | 50 | Maximum breadcrumbs retained per session | | enabled | boolean | true | Master on/off switch | | validateApiKey | boolean | true | Validate API key format on init | | sampleRate | number | 1.0 | Fraction of errors to send (0.0–1.0) | | beforeSend | (event: ErrorPayload) => ErrorPayload \| null | — | Mutate or drop events before sending | | onError | (error: Error) => void | — | Called when the SDK itself fails | | toast | ToastConfig | see below | In-page error toast notifications | | performance | PerformanceConfig | see below | Web Vitals and page load tracking | | offline | OfflineConfig | see below | Queue errors when the user is offline | | privacy | PrivacyConfig | see below | PII scrubbing |

ToastConfig

| Option | Type | Default | Description | | ------------------- | --------------- | ------------- | -------------------------------------------- | | enabled | boolean | false | Show toast notifications for errors | | position | ToastPosition | "top-right" | Toast anchor position | | duration | number | 5000 | Auto-dismiss delay in ms (0 = never) | | showOnAutoCapture | boolean | true | Show toast for automatically captured errors |

ToastPosition: "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right"

PerformanceConfig

| Option | Type | Default | Description | | ---------------- | --------- | ------- | ----------------------------------------- | | enabled | boolean | false | Enable performance monitoring | | trackWebVitals | boolean | true | Track LCP and FCP via PerformanceObserver | | sendWithErrors | boolean | true | Attach performance data to error reports |

OfflineConfig

| Option | Type | Default | Description | | -------------- | ---------------------------- | ---------------- | ---------------------------------------------- | | enabled | boolean | false | Queue errors when offline | | maxQueueSize | number | 50 | Maximum queued errors before oldest is dropped | | storage | "localStorage" \| "memory" | "localStorage" | Queue persistence strategy |

PrivacyConfig

| Option | Type | Default | Description | | ------------------ | ---------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | | scrubPII | boolean | false | Auto-redact emails, credit cards, SSNs, phone numbers, and IP addresses | | scrubQueryParams | string[] | ["token","apiKey","key","password","secret","api_key","access_token"] | URL query params to redact | | customPatterns | RegExp[] | [] | Additional patterns to redact |

Methods

tracker.install(): void

Registers window.onerror, unhandledrejection, navigation tracking, click tracking, console error interception, and fetch tracking. Call once at app startup.

tracker.uninstall(): void

Removes all registered event listeners and resets installed state.

tracker.reportError(error, severity?, context?): Promise<void>

Manually report an error.

| Parameter | Type | Default | | ---------- | ------------------------------------------- | ---------- | | error | Error | required | | severity | "low" \| "medium" \| "high" \| "critical" | "medium" | | context | Record<string, unknown> | — |

tracker.setUser(userId?, email?): void

Associate a user with all subsequent error reports. Call after login.

tracker.clearUser(): void

Clear user context. Call after logout.

tracker.addBreadcrumb(data): void

Manually add a breadcrumb. Type must be one of: "navigation" | "click" | "input" | "http" | "console" | "custom".

tracker.trackPerformance(name, value?): void

Record a custom performance mark. Requires performance.enabled: true.

tracker.showToast(options): void

Show an in-page toast notification. Requires toast.enabled: true.

tracker.showToast({
  message: "Saved successfully",
  style: "success", // "error" | "warning" | "success" | "info"
  position: "top-right",
  duration: 3000,
  closable: true,
});

tracker.getSessionId(): string

Returns the current session ID generated at construction.

tracker.isTrackerInstalled(): boolean

Returns true if install() has been called and not yet undone by uninstall().

Examples

Basic setup

import { ErrorTracker } from "featurely-error-tracker";

const tracker = new ErrorTracker({
  apiKey: process.env.FEATURELY_API_KEY!,
  environment: process.env.NODE_ENV as "development" | "production",
  appVersion: "2.1.0",
});
tracker.install();

Manual error reporting

try {
  await fetchUserData(userId);
} catch (error) {
  await tracker.reportError(error as Error, "high", {
    userId,
    action: "fetch_user_data",
  });
}

Toast notifications

const tracker = new ErrorTracker({
  apiKey: process.env.FEATURELY_API_KEY!,
  environment: "production",
  appVersion: "1.0.0",
  toast: {
    enabled: true,
    position: "top-right",
    duration: 5000,
    showOnAutoCapture: true,
  },
});
tracker.install();

PII scrubbing + beforeSend

const tracker = new ErrorTracker({
  apiKey: process.env.FEATURELY_API_KEY!,
  environment: "production",
  appVersion: "1.0.0",
  privacy: {
    scrubPII: true,
    scrubQueryParams: ["token", "apiKey", "password"],
    customPatterns: [/api[_-]?key/gi],
  },
  beforeSend: (event) => {
    if (event.url?.includes("/internal")) return null; // drop
    return event;
  },
  sampleRate: 0.5, // send only 50% of errors
});
tracker.install();

React / Next.js App Router

"use client";
import { useEffect } from "react";
import { ErrorTracker } from "featurely-error-tracker";

let tracker: ErrorTracker | null = null;

export function ErrorTrackerProvider({
  children,
  user,
}: {
  children: React.ReactNode;
  user?: { id: string; email: string };
}) {
  useEffect(() => {
    if (!tracker) {
      tracker = new ErrorTracker({
        apiKey: process.env.NEXT_PUBLIC_FEATURELY_API_KEY!,
        environment: process.env.NODE_ENV as "development" | "production",
        appVersion: process.env.NEXT_PUBLIC_APP_VERSION ?? "1.0.0",
      });
      tracker.install();
    }
    if (user) tracker.setUser(user.id, user.email);
    return () => {
      tracker?.uninstall();
      tracker = null;
    };
  }, [user]);

  return <>{children}</>;
}

Environment Support

| Environment | Supported | Notes | | ----------------------- | --------- | --------------------------------------------------------------------------- | | Browser | ✅ | Full support — window.onerror, unhandledrejection, Web Vitals, toast UI | | Node.js | ✅ | Manual reportError() and breadcrumbs; no DOM features or Web Vitals | | React Server Components | ✅ | Use reportError() server-side; skip install() | | Edge / Workers | ⚠️ | Manual reporting only; no global handlers |

Ships as CJS + ESM with TypeScript declarations.

Framework Integrations

React / Next.js App Router

Use a singleton pattern to avoid re-installing global handlers on re-renders:

"use client";
import { useEffect } from "react";
import { ErrorTracker } from "featurely-error-tracker";

let tracker: ErrorTracker | null = null;

export function ErrorTrackerProvider({
  children,
  user,
}: {
  children: React.ReactNode;
  user?: { id: string; email: string };
}) {
  useEffect(() => {
    if (!tracker) {
      tracker = new ErrorTracker({
        apiKey: process.env.NEXT_PUBLIC_FEATURELY_API_KEY!,
        environment: process.env.NODE_ENV as "development" | "production",
        appVersion: process.env.NEXT_PUBLIC_APP_VERSION ?? "1.0.0",
      });
      tracker.install();
    }
    if (user) tracker.setUser(user.id, user.email);
    return () => {
      tracker?.uninstall();
      tracker = null;
    };
  }, [user]);

  return <>{children}</>;
}

Security & Privacy

privacy.scrubPII: true — Auto-redacts emails, credit card numbers, SSNs, phone numbers, and IP addresses from all payloads before sending.

privacy.scrubQueryParams — Redacts sensitive URL query parameters. Default list: token, apiKey, key, password, secret, api_key, access_token.

privacy.customPatterns: RegExp[] — Additional patterns for proprietary identifiers.

beforeSend hook — Inspect, mutate, or drop any event before it is sent. Return null to discard.

beforeSend: (event) => {
  if (event.url?.includes("/internal")) return null;
  return event;
};

sampleRate: 0.0–1.0 — Send only a fraction of errors in high-traffic environments.

Debugging / Local Development

const tracker = new ErrorTracker({
  apiKey: process.env.FEATURELY_API_KEY!,
  environment: "development",
  appVersion: "1.0.0",
  enabled: process.env.NODE_ENV === "production", // disable in tests/CI
  toast: {
    enabled: true, // show a toast for every captured error
    position: "bottom-right",
  },
  sampleRate: 1.0, // capture all errors locally
});
tracker.install();

TypeScript

All public types are exported from the package entry point:

import type {
  ErrorTrackerConfig, // Full constructor config
  ToastConfig, // toast sub-config
  PerformanceConfig, // performance sub-config
  OfflineConfig, // offline queue sub-config
  PrivacyConfig, // PII scrubbing sub-config
  ToastOptions, // options for showToast()
  ErrorPayload, // event object passed to beforeSend
  ToastPosition, // "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right"
  ToastStyle, // "error" | "warning" | "success" | "info"
} from "featurely-error-tracker";

Named error classes: InvalidApiKeyError, ConfigurationError.

Troubleshooting

Safari IndexedDB Crashes

Safari on iOS can terminate IndexedDB connections when:

  • The browser is backgrounded
  • Memory pressure occurs
  • Private browsing mode is active

SDK Behavior (v1.0.23+): The SDK now handles these gracefully with:

  • Circuit breaker to prevent infinite loops
  • Exponential backoff (1s → 2s → 4s ... up to 60s) on API failures
  • Silent failure after logging to console

Your App Should:

// Listen for IndexedDB connection drops
db.addEventListener("close", () => {
  console.warn("IndexedDB connection closed");
  // Fall back to localStorage or re-establish connection
});

db.addEventListener("error", (event) => {
  console.error("IndexedDB error:", event);
  event.preventDefault(); // Don't let it crash your app
});

Error Spam / Infinite Loops

Symptoms: Hundreds of error reports in seconds, console spam with "[ERROR TRACKER] SDK Error"

Fix: Update to v1.0.23 or later:

npm install featurely-error-tracker@latest

See FIXES.md for details on the circuit breaker and exponential backoff fixes.

API Rate Limiting (429)

The SDK automatically backs off when receiving 429 responses:

  • 1st failure: waits 1 second
  • 2nd failure: waits 2 seconds
  • 3rd failure: waits 4 seconds
  • Capped at 60 seconds maximum

Check console for: [Featurely] Failed to report error: 429 → Backoff: waiting XXXXms

Network/CSP Errors

If you see "NetworkError" or "Failed to fetch" in console:

  1. Check CSP: Add Featurely to your Content-Security-Policy:

    <meta
      http-equiv="Content-Security-Policy"
      content="connect-src 'self' https://www.featurely.no"
    />
  2. Check CORS: Ensure your domain is allowed in your Featurely project settings

  3. Check the browser's network tab for blocked requests

Resources