GitHub

Configuration

pulse.config.js sets the performance and load thresholds that Pulse enforces across your application. All fields are optional — the defaults match Google's Core Web Vitals "good" band. Configuration here is not about enabling features; it is about deciding where, if anywhere, you need to lower a guaranteed baseline.

Full schema

// pulse.config.js
export default {
  port: 3000,

  lighthouse: {
    // Category scores — 0 to 100. Default: 100 for all four.
    performance:   100,
    accessibility: 100,
    bestPractices: 100,
    seo:           100,

    // Core Web Vitals and timing metrics.
    // Defaults are the Google "good" thresholds.
    lcp: 2500,   // Largest Contentful Paint (ms)
    cls: 0.1,    // Cumulative Layout Shift
    tbt: 200,    // Total Blocking Time (ms)
    fcp: 1800,   // First Contentful Paint (ms)
    si:  3400,   // Speed Index (ms)
    inp: 200,    // Interaction to Next Paint (ms)
  },

  load: {
    duration:    10,
    connections: 10,
    thresholds: {
      rps:    undefined,  // minimum req/s (optional)
      p99:    undefined,  // maximum p99 latency ms (optional)
      errors: 0,
    },
  },

  environments: {
    // Environment names are bespoke — choose whatever suits your project.
    local:   { url: 'http://localhost:3000', default: true },
    staging: {
      url:     'https://staging.myapp.com',
      headers: { Authorization: `Bearer ${process.env.STAGING_TOKEN}` },
      load:       { duration: 30, connections: 50 },
      lighthouse: { performance: 90 },
    },
    production: { url: 'https://myapp.com' },
  },

  routes: {
    // Per-route overrides — merged on top of global lighthouse/load config.
    // Only specify what differs from the global defaults.
    '/dashboard': {
      lighthouse: {
        performance: 85,
        lcp:         4000,
      },
    },
    '/embed': {
      lighthouse: {
        bestPractices: 85,
      },
    },
  },
}

port

FieldTypeDefaultDescription
portnumber3000Port the dev and production servers listen on.

lighthouse

Global Lighthouse thresholds that every page must meet. /pulse-report enforces these after every audit — any page that falls below a threshold is reported as a failure, not a warning.

FieldTypeDefaultDescription
performancenumber100Lighthouse Performance category score (0–100).
accessibilitynumber100Lighthouse Accessibility category score (0–100).
bestPracticesnumber100Lighthouse Best Practices category score (0–100).
seonumber100Lighthouse SEO category score (0–100).
lcpnumber2500Largest Contentful Paint budget (ms).
clsnumber0.1Cumulative Layout Shift budget.
tbtnumber200Total Blocking Time budget (ms).
fcpnumber1800First Contentful Paint budget (ms).
sinumber3400Speed Index budget (ms).
inpnumber200Interaction to Next Paint budget (ms).
Unset fields default to the values above. Setting a field to null removes that check for the project — use sparingly. Raising a threshold is always preferable to disabling it.

routes

Route-specific overrides let you lower a threshold for a specific page without relaxing the global guarantee. Only specify the fields that differ — everything else inherits from the global config.

routes: {
  // This route uses a third-party chart library — relax performance only.
  '/dashboard': {
    lighthouse: {
      performance: 85,
      lcp:         4000,
    },
  },
}
Route keys must exactly match the spec route field, including any leading slash. Dynamic segments are not supported — create a specific override for each route pattern.

load

Load test thresholds enforced by /pulse-load. All fields are optional — omitting a threshold means that check is not enforced.

FieldTypeDefaultDescription
durationnumber10Test duration in seconds.
connectionsnumber10Number of concurrent request chains.
thresholds.rpsnumberundefinedMinimum acceptable requests per second. Unset = no check.
thresholds.p99numberundefinedMaximum acceptable p99 latency (ms). Unset = no check.
thresholds.errorsnumber0Maximum acceptable error count.
load: {
  duration:    30,
  connections: 20,
  thresholds: {
    rps:    100,   // fail if below 100 req/s
    p99:    500,   // fail if p99 exceeds 500ms
    errors: 0,
  },
},

Per-route overrides follow the same pattern as lighthouse:

routes: {
  '/feed': {
    load: { connections: 5, thresholds: { rps: 20 } },
  },
}

Results are saved to .pulse/load-reports/ and displayed in the Load Tests tab of the report dashboard, alongside the Lighthouse Performance tab for the same route.

environments

Named environments let you enforce thresholds against different targets — local, staging, production — from the same config. Thresholds are applied per-environment, so staging and production can have different performance floors.

FieldTypeDescription
urlstringBase URL to test against. If it contains localhost or 127.0.0.1, a local production build is spun up automatically. Remote URLs are tested directly.
defaultbooleanThe environment used when none is explicitly specified by pulse report and pulse load-test.
headersobjectHTTP headers sent with every request to this environment. Useful for authorization tokens on protected staging deployments — read values from process.env rather than hardcoding them.
loadobjectLoad test config overrides for this environment. Same fields as the global load block. Merged on top of global config.
lighthouseobjectLighthouse threshold overrides for this environment. Same fields as the global lighthouse block. Merged on top of global config.
Environment names are fully bespoke — local, staging, production, preview, eu — whatever maps to your project's infrastructure. There are no reserved names.

Threshold merge order: global config → environment override → per-route override.

environments: {
  local:   { url: 'http://localhost:3000', default: true },
  staging: {
    url:     'https://staging.myapp.com',
    headers: { Authorization: `Bearer ${process.env.STAGING_TOKEN}` },
    load:       { duration: 30, connections: 50, thresholds: { rps: 500 } },
    lighthouse: { performance: 90 },
  },
  production: { url: 'https://myapp.com' },
}

CWV default thresholds

The default metric thresholds match the Google "good" band from the Core Web Vitals specification:

MetricDefaultGoogle "good" threshold
LCP2500 ms≤ 2500 ms
CLS0.1≤ 0.1
TBT200 ms≤ 200 ms
FCP1800 ms≤ 1800 ms
SI3400 ms≤ 3400 ms
INP200 ms≤ 200 ms