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

@esportscz/sentry-react

v0.6.0

Published

Opinionated GlitchTip/Sentry bootstrap for Vite React SPAs

Readme

@esportscz/sentry-react

Opinionated GlitchTip/Sentry bootstrap for Vite React SPAs. Provides company-wide defaults, standard tags, and a minimal API so every project initializes Sentry the same way.

Installation

pnpm add @esportscz/sentry-react

Quick start

// src/sentry.ts
import { initSentry } from '@esportscz/sentry-react'

initSentry({
  viteEnv: import.meta.env,
  service: 'my-app',
  project: 'my-project',
})
// src/main.tsx
import { SentryErrorBoundary } from '@esportscz/sentry-react'
import './sentry'
import App from './App'

createRoot(document.getElementById('root')!).render(
  <SentryErrorBoundary fallback={<p>Something went wrong.</p>}>
    <App />
  </SentryErrorBoundary>,
)
// anywhere in app code
import { captureError } from '@esportscz/sentry-react'

try {
  await saveOrder(payload)
} catch (error) {
  captureError(error, {
    feature: 'checkout',
    action: 'save-order',
    level: 'warning',
    tags: { section: 'payment' },
    extra: { orderId: payload.id },
  })
}
// React Router errorElement
import { useEffect } from 'react'
import { useRouteError } from 'react-router-dom'
import { captureRouteError } from '@esportscz/sentry-react'

export function ErrorPage() {
  const error = useRouteError()

  useEffect(() => {
    captureRouteError(error, {
      path: window.location.pathname,
      source: 'render',
    })
  }, [error])

  return <p>Something went wrong.</p>
}

Environment variables

All values can be passed explicitly via SentryConfig or resolved automatically from Vite env variables. Explicit config always takes priority.

| Variable | Purpose | Fallbacks | | --------------------------- | ------------------------ | -------------------------------------- | | VITE_SENTRY_DSN | GlitchTip/Sentry DSN | | | VITE_SENTRY_ENABLED | Enable/disable reporting | Enabled when DSN is present | | VITE_SENTRY_ENVIRONMENT | Environment name | VITE_APP_ENV, MODE, "production" | | VITE_SENTRY_RELEASE | Release/version string | VITE_APP_VERSION | | VITE_GIT_COMMIT | Git commit SHA | VITE_BITBUCKET_COMMIT |

Config reference

interface SentryConfig {
  dsn?: string                          // GlitchTip/Sentry DSN
  enabled?: boolean                     // Kill switch (default: true when DSN present)
  environment?: string                  // Environment name (default: "production")
  release?: string                      // Release version
  service?: string                      // Service tag for identifying the app
  project?: string                      // Project tag for company grouping
  stack?: string                        // Stack tag (default: "react")
  gitCommit?: string                    // Git commit SHA tag
  logPageContext?: boolean              // Stamp router.path tag and contexts.page (default: true)
  sampleRate?: number                   // Error sample rate, 0–1 (default: 1)
  tracesSampleRate?: number             // Performance trace sample rate, 0–1; enables tracing when set
  sendDefaultPii?: boolean              // Include default PII (default: false)
  tanstackRouter?: unknown              // TanStack Router instance for automatic tracing
  dropEnvironments?: string[]           // Environments where init is skipped
  ignoreErrors?: Array<string | RegExp> // Error messages to ignore
  denyUrls?: Array<string | RegExp>     // Script URLs to ignore
  allowUrls?: Array<string | RegExp>    // Script URLs to allow
  beforeSend?: BrowserOptions['beforeSend'] // Custom event hook
  viteEnv?: Record<string, unknown>     // import.meta.env for automatic resolution
}

Production-safe defaults

When no explicit value is provided, the wrapper applies these defaults:

  • environment"production"
  • sampleRate1 (capture all errors)
  • sendDefaultPiifalse (no personal data)
  • stack"react"

Performance tracing is off by default. Set tracesSampleRate to enable browser tracing and control the sample rate.

TanStack Router tracing

For TanStack Router apps, install @tanstack/react-router version 1.64.0 or later. Create the router first, initialize Sentry with it, and mount the router afterwards. This uses Sentry's router-aware tracing integration; do not add manual router subscriptions or navigation spans.

import { createRoot } from 'react-dom/client'
import { RouterProvider } from '@tanstack/react-router'
import { initSentry } from '@esportscz/sentry-react'
import { router } from './router'

initSentry({
  viteEnv: import.meta.env,
  project: 'my-project',
  tanstackRouter: router,
  tracesSampleRate: 0.1,
})

createRoot(document.getElementById('root')!).render(<RouterProvider router={router} />)

Standard tags

Every initialized project gets these tags on all events:

| Tag | Source | | ------------- | ------------------------------------------------- | | service | config.service | | project | config.project | | stack | config.stack or "react" | | environment | Resolved environment | | release | Resolved release | | git.commit | config.gitCommit or VITE_GIT_COMMIT / VITE_BITBUCKET_COMMIT |

Per-event location data

Location data is split between tags (for filtering) and contexts (for event details):

| Data | Tag | Context | | ---- | --- | ------- | | Pathname / route path | router.path | contexts.page.path or contexts.route.path | | Sanitized page URL | — | contexts.page.url (no query string or hash) | | Route id, source | — | contexts.route.route_id, contexts.route.source | | Route params, status | — | extra data (router.params, etc.) |

Every event gets a fresh contexts.page object at send time and a router.path tag from the current pathname — no manual sync needed after SPA navigation.

When captureRouteError is used, route metadata is attached as both tags and contexts.route. The router.path tag uses the route pattern from context (e.g. /orders/:id) and is not overwritten by the browser pathname.

Set logPageContext: false to disable automatic router.path tagging and contexts.page stamping.

API

initSentry(config?): boolean

Initializes Sentry with company defaults. Returns true if initialized, false if skipped (missing DSN, disabled, or dropped environment). Safe to call multiple times — subsequent calls return true without re-initializing.

isInitialized(): boolean

Returns whether Sentry has been initialized.

setTag(key, value): void

Sets a custom tag. If called before initSentry, the tag is stored and forwarded once Sentry initializes. Empty, null, or undefined values are ignored.

getTags(): Record<string, string | number | boolean>

Returns a copy of all tracked tags.

clearTag(key): void

Removes a tracked tag. If called after initSentry, also clears it on the Sentry scope.

setUser(user): void

Sets the Sentry user context. Accepts a SentryUser object or null to clear. If called before initSentry, the user is stored and forwarded once Sentry initializes.

getUser(): SentryUser | null

Returns a copy of the current user context.

SentryErrorBoundary

Re-export of @sentry/react's ErrorBoundary component. Use it to wrap your app and capture React rendering errors.

captureError(error, context?): string | undefined

Use this when your app catches an error anywhere outside React rendering and still wants to report it.

type SentryTagValue = string | number | boolean
type CaptureErrorLevel = 'error' | 'warning' | 'fatal'

interface CaptureErrorContext {
  feature?: string
  action?: string
  level?: CaptureErrorLevel
  tags?: Record<string, SentryTagValue | null | undefined>
  extra?: Record<string, unknown>
}

Behavior:

  • Accepts unknown and normalizes non-Error values before capture
  • Applies feature, action, and tags as event-scoped tags
  • Applies extra as event-scoped extra data
  • Returns the Sentry event id when available
  • Safely returns undefined when Sentry has not been initialized or was intentionally skipped

captureRouteError(error, context?): string | undefined

Use this inside React Router errorElement flows and pass it whatever useRouteError() returned.

interface CaptureRouteErrorContext {
  path?: string
  source?: 'loader' | 'action' | 'render'
  routeId?: string
  params?: Record<string, string | undefined>
  captureErrorResponses?: 'server-errors' | 'all' | 'none'
}

Default route-error policy:

  • Thrown Error values are reported
  • Unknown thrown values are normalized and reported
  • ErrorResponse values with status >= 500 are reported
  • ErrorResponse values with status 400-499, especially 404, are skipped by default
  • Set captureErrorResponses: 'all' to report all ErrorResponse values
  • Set captureErrorResponses: 'none' to skip all ErrorResponse values

Router metadata is attached under contexts.route, with only router.path as a tag for filtering:

  • router.path / contexts.route.path — route pattern or path from captureRouteError context (e.g. /orders/:id)
  • contexts.route.route_id, contexts.route.source — detail metadata, context only

Route params are attached as extra data under router.params, not as tags.

Recommended integration patterns

Use the pattern that matches how the SPA handles errors.

1. React Router data router apps

Use captureRouteError(...) inside route errorElement components for loader/action/render failures in router flows.

// routes/ErrorPage.tsx
import { useEffect } from 'react'
import { useRouteError } from 'react-router-dom'
import { captureRouteError } from '@esportscz/sentry-react'

export function ErrorPage() {
  const error = useRouteError()

  useEffect(() => {
    captureRouteError(error, {
      path: '/orders/:id',
      routeId: 'order-details',
      source: 'loader',
    })
  }, [error])

  return <p>Something went wrong.</p>
}

Use captureError(...) for caught errors in app code. Add SentryErrorBoundary only if you also want a general React error boundary outside router-managed error flows.

2. Plain BrowserRouter apps with Route components

If the app does not use loader/action errorElement flows, wrap the app in SentryErrorBoundary and use captureError(...) for caught async or business-logic errors.

// src/main.tsx
import { BrowserRouter } from 'react-router-dom'
import { SentryErrorBoundary } from '@esportscz/sentry-react'
import './sentry'
import App from './App'

createRoot(document.getElementById('root')!).render(
  <SentryErrorBoundary fallback={<p>Something went wrong.</p>}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </SentryErrorBoundary>,
)

This setup captures React render crashes through the boundary and still gives every outgoing event a fresh router.path tag and contexts.page data.

Disabling Sentry

Three ways to prevent initialization:

  1. Don't set VITE_SENTRY_DSNinitSentry returns false and does nothing
  2. Set enabled: false (or VITE_SENTRY_ENABLED=false)
  3. Use dropEnvironments to skip specific environments:
    initSentry({
      viteEnv: import.meta.env,
      service: 'my-app',
      dropEnvironments: ['development', 'test'],
    })