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

@withpanache/nextjs

v0.13.0

Published

Next.js plugin for Panache monitoring. Collects dependency manifests at build time and applies security defaults.

Readme

@withpanache/nextjs

Next.js plugin for Panache. Monitors your app's security, performance, and dependencies with zero config.

What it does

  • Security headers : applies production-ready defaults (CSP, HSTS, X-Frame-Options, Permissions-Policy, etc.) with full TypeScript autocomplete for customization
  • Dependency monitoring : collects your dependency tree at build time and pushes it to Panache for vulnerability tracking
  • Zero impact : headers are injected at config level (no middleware), manifest push runs in a detached subprocess (never blocks your build)

Install

npm install @withpanache/nextjs
# or
pnpm add @withpanache/nextjs
# or
yarn add @withpanache/nextjs

Requires Next.js 14 or later.

Quick start

// next.config.ts
import { withPanache } from "@withpanache/nextjs"

export default withPanache({
  // your existing Next.js config
})

That's it. Your app now has security headers and X-Powered-By is disabled.

To enable dependency monitoring, add your site token:

export default withPanache(
  { /* next config */ },
  { token: process.env.PANACHE_SITE_TOKEN }
)

Or set the PANACHE_SITE_TOKEN environment variable (the plugin picks it up automatically).

Options

interface PanacheOptions {
  /** Site token from the Panache dashboard. Also reads PANACHE_SITE_TOKEN env var. */
  token?: string
  /** Ingest API URL. Default: "https://withpanache.dev/api/v1/ingest" */
  apiUrl?: string
  /** Security headers. true = all defaults, false = skip, object = customize. Default: true */
  security?: boolean | SecurityHeadersConfig
  /** Project default branch (mirrors sites.default_branch in the dashboard). Default: "main" */
  defaultBranch?: string
  /** CSP violation monitoring. Disabled unless a token is provided. */
  cspMonitoring?: CspMonitoringConfig
}

Security headers

By default, withPanache injects the following headers on all routes:

| Header | Default value | |---|---| | Strict-Transport-Security | max-age=63072000; includeSubDomains | | Content-Security-Policy | default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; frame-ancestors 'self' | | X-Content-Type-Options | nosniff | | X-Frame-Options | SAMEORIGIN | | Referrer-Policy | strict-origin-when-cross-origin | | Permissions-Policy | camera=(), microphone=(), geolocation=() |

These defaults are permissive enough for most Next.js apps while passing Panache's security checks.

Customizing headers

Pass a SecurityHeadersConfig object to override or disable individual headers:

export default withPanache(nextConfig, {
  security: {
    // Disable HSTS (e.g. behind a reverse proxy that handles it)
    strictTransportSecurity: false,

    // Custom referrer policy
    referrerPolicy: "no-referrer",

    // Stricter X-Frame-Options
    xFrameOptions: "DENY",
  },
})

Set security: false to disable all security headers (Panache will still monitor your app if a token is provided).

CSP with typed directives

CSP can be configured as a raw string or as a typed object with autocomplete:

export default withPanache(nextConfig, {
  security: {
    contentSecurityPolicy: {
      // Your sources are added to the defaults, no need to repeat 'self'
      "script-src": ["https://cdn.example.com"],
      "connect-src": ["https://api.example.com", "https://analytics.example.com"],
      "img-src": ["https://images.example.com"],
    },
  },
})

When using the object form, your sources are added to the defaults (deduplicated). You don't need to repeat 'self' or other default values. Directives you don't mention keep their default values entirely.

To replace a specific directive instead of extending it, use the replace() helper:

import { withPanache, replace } from "@withpanache/nextjs"

export default withPanache(nextConfig, {
  security: {
    contentSecurityPolicy: {
      "script-src": ["https://cdn.example.com"],                     // extends defaults
      "connect-src": replace(["'self'", "https://api.example.com"]), // replaces defaults
    },
  },
})

To fully replace the entire CSP, pass a raw string:

export default withPanache(nextConfig, {
  security: {
    contentSecurityPolicy: "default-src 'none'; script-src 'self'",
  },
})

Permissions-Policy with typed features

Same pattern as CSP. Object form adds to defaults, string form replaces:

export default withPanache(nextConfig, {
  security: {
    permissionsPolicy: {
      // Merge with defaults (camera, microphone, geolocation remain disabled)
      fullscreen: ["self"],
      payment: [],
    },
  },
})

How merging works

  • If you already define a headers() function in your Next.js config, Panache appends its headers to your catch-all route (/(.*)) without overriding any header you've set.
  • If you don't have a headers() function, Panache creates one.
  • Your headers always take priority. Panache never overwrites an existing header.

Dev mode

In development (NODE_ENV !== "production"), the default CSP includes 'unsafe-eval' in script-src because React's development build requires it. This is automatically removed in production builds.

CSP monitoring

When a CSP token is provided, the plugin attaches a Reporting-Endpoints header pointing at Panache's report ingest service. Browsers POST Content-Security-Policy violations directly to Panache, which aggregates them hourly into per-source observations in the dashboard. Useful for catching third-party drift, misconfigured CSP rules, and rogue scripts.

Enable

Generate a CSP token in the Panache dashboard (Site settings → CSP monitoring), then set the env var :

PANACHE_CSP_TOKEN=pncsp_<32 hex chars>

The plugin picks it up automatically. No code change needed beyond having withPanache(...) already wrapping your config.

Alternatively, pass it explicitly :

export default withPanache(nextConfig, {
  cspMonitoring: { token: process.env.PANACHE_CSP_TOKEN },
})

Learning Mode

Existing sites usually need a discovery period before enforcing CSP. Learning Mode emits Content-Security-Policy-Report-Only instead of Content-Security-Policy, so violations are reported but not blocked :

PANACHE_CSP_LEARNING_MODE=1

Or via plugin options :

export default withPanache(nextConfig, {
  cspMonitoring: {
    token: process.env.PANACHE_CSP_TOKEN,
    learningMode: true,
  },
})

Truthy values for the env var : 1, true, yes (case-insensitive). Anything else, including absence, defaults to enforce mode.

Once you've used the dashboard observations to pin down the legitimate third parties for your site, drop Learning Mode and the same CSP becomes enforced.

Branch-aware reports

Reports include the branch detected from your CI environment (GITHUB_REF_NAME, CI_COMMIT_BRANCH, VERCEL_GIT_COMMIT_REF, etc., or local git branch --show-current). Non-default branches send ?b=<branch> on the report URL so observations are partitioned per branch in the dashboard. Set defaultBranch if your default isn't main :

export default withPanache(nextConfig, {
  defaultBranch: "develop",
  cspMonitoring: { token: process.env.PANACHE_CSP_TOKEN },
})

Self-hosted endpoint

For self-hosted Panache deployments, override the report endpoint base URL :

PANACHE_CSP_ENDPOINT=https://csp.your-panache-domain.com

Or :

export default withPanache(nextConfig, {
  cspMonitoring: {
    token: process.env.PANACHE_CSP_TOKEN,
    endpoint: "https://csp.your-panache-domain.com",
  },
})

How it interacts with security.contentSecurityPolicy

CSP monitoring composes with the existing CSP header logic :

  • The report-to panache directive is appended to whatever CSP you have (default, custom object, or raw string).
  • A matching Reporting-Endpoints: panache="<endpoint>/<token>" header is set automatically.
  • If you set security: false, CSP monitoring is also disabled (the plugin won't attach any headers).

Dependency monitoring

During next build, the plugin:

  1. Detects your package manager (pnpm, npm, yarn classic, yarn berry)
  2. Collects the full dependency tree with versions
  3. Pushes it to the Panache API in a detached subprocess

This runs in the background and never blocks or slows down your build. If the push fails (no network, invalid token), it fails silently.

Supported package managers

  • pnpm
  • npm
  • yarn (classic and berry)
  • bun (detection only, not yet supported)

CI/CD detection

The plugin automatically detects git SHA, branch, and preview URL from common CI environments:

  • Git SHA : GITHUB_SHA, CI_COMMIT_SHA, VERCEL_GIT_COMMIT_SHA, CF_PAGES_COMMIT_SHA, COMMIT_REF, or local git rev-parse HEAD
  • Branch : GITHUB_REF_NAME, CI_COMMIT_BRANCH, VERCEL_GIT_COMMIT_REF, CF_PAGES_BRANCH, BRANCH, or local git branch --show-current
  • Preview URL : VERCEL_URL, CF_PAGES_URL, DEPLOY_URL

TypeScript

All types are exported for use in your config:

import type {
  PanacheOptions,
  SecurityHeadersConfig,
  CspDirectives,
  CspDirectiveName,
  CspSourceValue,
  CspMonitoringConfig,
  PermissionsPolicyDirectives,
  PermissionsPolicyFeature,
  ReferrerPolicy,
} from "@withpanache/nextjs"

License

MIT