Docs

Next.js Plugin

Security headers and dependency monitoring for Next.js. One wrapper, zero config.

Installation

Install the plugin with your package manager of choice:

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

Quick start

Wrap your Next.js config with withPanache. That's it: your app now has production-ready security headers and X-Powered-By is disabled.

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

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

Security headers

By default, withPanache injects the following headers on all routes. These are permissive enough for most Next.js apps while passing Panache's security checks.

HeaderDefault value
Strict-Transport-Securitymax-age=63072000; includeSubDomains
Content-Security-Policydefault-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'
X-Content-Type-Optionsnosniff
X-Frame-OptionsSAMEORIGIN
Referrer-Policystrict-origin-when-cross-origin
Permissions-Policycamera=(), microphone=(), geolocation=()

Customizing headers

Pass a security object to override or disable individual headers. Set a header to false to skip it entirely.

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

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

    // Stricter framing
    xFrameOptions: "DENY",
  },
})

Content Security Policy

CSP can be configured as a typed object or a raw string. 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. To replace a specific directive instead of extending it, use the replace() helper. String form: fully replaces the entire default CSP. All forms have full TypeScript autocomplete for directive names and source values.

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

export default withPanache(nextConfig, {
  security: {
    contentSecurityPolicy: {
      // Extends: sources are added to the defaults
      "script-src": ["https://cdn.example.com"],
      // Replaces: this directive fully overrides the default
      "connect-src": replace(["'self'", "https://api.example.com"]),
    },
  },
})

// String form: replaces the entire CSP
export default withPanache(nextConfig, {
  security: {
    contentSecurityPolicy: "default-src 'none'; script-src 'self'",
  },
})

Permissions Policy

Same pattern as CSP. Object form adds to defaults, string form replaces. An empty array disables the feature.

export default withPanache(nextConfig, {
  security: {
    permissionsPolicy: {
      // Merge with defaults (camera, microphone, geolocation stay 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. In development, the default CSP includes 'unsafe-eval' in script-src because React's development build requires it. This is automatically removed in production.

Dependency monitoring

During next build, the plugin detects your package manager, collects the full dependency tree, and pushes it to Panache for vulnerability tracking. This runs in a detached subprocess and never blocks or slows down your build. If it fails, it fails silently. Supported package managers: pnpm, npm, yarn (classic and berry). To enable it, add your site token:

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

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, or local git. Branch: GITHUB_REF_NAME, CI_COMMIT_BRANCH, VERCEL_GIT_COMMIT_REF, CF_PAGES_BRANCH, or local git. Preview URL: VERCEL_URL, CF_PAGES_URL, DEPLOY_URL. No configuration needed. If the environment variables are present, they are used automatically.

All options

The full options reference:

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
}

TypeScript

All types are exported for use in your config:

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

Need help?

If you have questions about the plugin or need assistance, reach out at hello@withpanache.dev