PWA Today documentation

pwa-check.yml Configuration Reference

Configure audit profiles, runtime checks, quality gates, and report output.

This document describes the configuration used by:

pwa-check audit https://example.com

For pipeline setup and authentication, see Integrating PWA Today Audits into CI/CD. For direct HTTP integration, see the Runtime Audit API Reference. For provider-specific deployment scripts, see Service Worker Deployment Testing.

Configuration file discovery

The CLI looks in its current working directory for the first available file in this order:

  1. pwa-check.yml
  2. pwa-check.yaml
  3. pwa-check.json

Select another file with:

pwa-check audit --config config/production-audit.yml https://example.com

Paths in reports and the service worker deployment command are resolved relative to the directory in which the CLI runs.

Top-level structure

version: 1

audit:
  profile: standard
  applicationId: example.com
  allowedOrigins: []
  include: []
  exclude: []
  options: {}

qualityGate:
  minimumScore: 90
  failOn:
    - critical
    - high
  failOnWarnings: true

reports:
  json: reports/pwa-audit.json
  junit: reports/pwa-audit.xml
Field Required Description
version Yes Configuration format version. It must be 1.
audit No Check selection and per-check options.
qualityGate No Conditions that determine the CLI exit code.
reports No JSON and JUnit report output paths.

If no configuration file exists, the CLI uses version 1, the standard profile, the API’s default quality gate, and no report files.

version

The only supported value is:

version: 1

The CLI rejects files without version: 1.

audit

audit.profile

Selects the initial set of checks:

audit:
  profile: standard

Supported profiles:

Profile Checks
quick manifest, service-worker-first-installation, service-worker-handlers
standard Everything in quick, plus offline, offline-navigation, service-worker-update, and before-install-prompt
full Every runtime check except service-worker-deployment
custom Only checks listed under include

The default profile is standard.

The hosted Runtime Audit API also applies the customer entitlement. The complimentary trial and Developer plan accept the standard profile with one or more Standard checks selected. Team and Business dashboard configurations may select any check from the Full runtime suite except service-worker-deployment; complete release audits use the exact full profile with service-worker-deployment included. Other profiles remain useful for local checks, but the API returns a structured entitlement error if they do not match the active plan.

Some selected checks require options. If their required options are missing, they return not-applicable. The exception is service-worker-deployment: when explicitly selected, its missing local command is a CLI configuration error.

audit.applicationId

Identifies the Application that owns the audit history:

audit:
  applicationId: example.com

If omitted, the audited hostname is used. An Application ID must:

  • Be the verified Application hostname in the customer console.
  • Match the hostname of the audited URL.
  • Contain only letters, numbers, dots, or dashes.

audit.allowedOrigins

By default, the audit browser can load only the audited PWA origin. Add an origin here only when the PWA needs an essential script, stylesheet, font, image, or API from another host:

audit:
  allowedOrigins:
    - https://cdn.example.com
    - https://api.example.com

Each entry must be a public HTTPS origin without a path or query string. The audit validates and pins each origin before the browser starts, so an entry cannot resolve to a private network address during the audit. Same-origin PWAs do not need this setting. You can configure at most 10 additional origins.

audit.include

Adds checks to a profile:

audit:
  profile: quick
  include:
    - offline

For custom, include defines the entire check set and must contain at least one check:

audit:
  profile: custom
  include:
    - manifest
    - offline

Duplicate check IDs are removed.

audit.exclude

Removes checks after the profile and include list have been combined:

audit:
  profile: full
  exclude:
    - push-notifications

If a check appears in both include and exclude, it is excluded.

Stable check IDs

Check ID Severity Required options
manifest critical None
offline critical None
cache high routes
offline-navigation high series
service-worker-first-installation critical None
service-worker-handlers high None
service-worker-update high None
service-worker-deployment critical Local command; the CLI supplies the API testId
before-install-prompt medium None
offline-request-retry high requests
push-notifications high payload

Unknown check IDs are rejected.

audit.options

Options are grouped by stable check ID:

audit:
  options:
    offline-navigation:
      series:
        - [/, /products, /checkout]

Do not put credentials, authorization headers, cookies, passwords, API keys, private keys, client secrets, or tokens in check options. Sensitive option names are rejected by the API, and the audit configuration is stored with the audit record.

Common browser timeout

Most checks support:

audit:
  options:
    manifest:
      timeout: 20000

timeout is a navigation timeout in milliseconds. The default is 15000. Increasing it can help applications that take longer to reach the browser’s network-idle state.

manifest

audit:
  options:
    manifest:
      timeout: 20000

The check:

  • Loads the page in a browser.
  • Resolves the manifest from the rendered document.
  • Runs the static pwa-check manifest rules.
  • Loads icons and screenshots to verify their actual dimensions.
Option Type Default Description
timeout Number 15000 Page navigation and manifest fetch timeout in milliseconds.

offline

audit:
  options:
    offline:
      offlineUrls:
        - /
        - /products
      expectedSelectors:
        - main
        - h1
      requiredText:
        - Example Store
      minBodyTextLength: 20
      minHtmlLength: 1000
      timeout: 20000

This check loads each URL online, confirms that a service worker controls it, reloads it offline, and compares the online and offline documents.

Option Type Default Description
offlineUrls Array of URLs Audited URL URLs to reload offline. Relative URLs resolve against the audited URL.
expectedSelectors Array of strings [] Selectors that must be present online and offline.
requiredText Array of strings [] Text that must be present in the offline document.
minBodyTextLength Number 20 Minimum acceptable offline body-text length.
minHtmlLength Number 1000 Minimum acceptable offline HTML length.
timeout Number 15000 Navigation timeout in milliseconds.

offline-navigation

audit:
  options:
    offline-navigation:
      series:
        - - /
          - /products
          - /checkout
        - - /
          - /account
      expectedSelectors:
        - main
      requiredText:
        - Example Store
      timeout: 20000

series is required. Each nested array is one navigation sequence. The check visits every URL in the sequence online and then repeats the sequence offline. Relative URLs resolve against the audited URL.

Use multiple sequences to test independent navigation paths:

series:
  - [/, /products, /products/featured]
  - [/, /help, /contact]
Option Type Default Description
series Array of URL arrays Required Online and offline navigation sequences.
expectedSelectors Array of strings [] Selectors expected on each tested page.
requiredText Array of strings [] Text expected on each offline page.
timeout Number 15000 Navigation timeout in milliseconds.

cache

audit:
  options:
    cache:
      routes:
        - url: /
          readySelector: '#home-title'
        - url: /audit/
          readySelector: '#audit-title'
      privateResponseAllowlist:
        - /offline-profile
      growthTolerance: 0
      cacheSettleTimeout: 10000
      cacheQuietPeriod: 1000
      timeout: 20000

routes is required. The audit opens every route twice online, waiting for its readySelector to contain text each time. It verifies that Cache Storage stops growing after the second pass, rejects cached private or no-store responses, and then opens every configured route in a fresh offline tab.

Use a route-specific readySelector that represents rendered page content, not an empty application shell. Relative URLs resolve against the audited URL.

Option Type Default Description
routes Array of { url, readySelector } objects Required Routes to exercise online and cold-start offline.
routes[].url URL Required Relative or absolute URL for the route.
routes[].readySelector Selector string Required Element that must exist and contain text after the route renders.
privateResponseAllowlist Array of paths [] Exact pathnames allowed to cache despite private-response signals.
growthTolerance Number 0 Additional cache entries permitted after the second route pass.
cacheSettleTimeout Number 10000 Maximum time to wait for cache writes to settle after each pass.
cacheQuietPeriod Number 1000 Duration for which the entry count must remain unchanged.
timeout Number 15000 Navigation and render-readiness timeout in milliseconds.

service-worker-first-installation

audit:
  options:
    service-worker-first-installation:
      timeout: 20000

The check starts with a clean browser profile, waits up to 10 seconds for the first service worker to become ready, reloads the page, and verifies that the worker controls it.

Option Type Default Description
timeout Number 15000 Page navigation timeout in milliseconds.

The 10-second serviceWorker.ready limit is fixed separately from the navigation timeout.

service-worker-handlers

audit:
  options:
    service-worker-handlers:
      timeout: 20000

The check resolves the active service worker at runtime, loads its imported scripts, and checks the required handlers:

  • install
  • activate
  • fetch
  • push
  • notificationclick

It also checks lifecycle behavior such as waitUntil, self.skipWaiting(), and self.clients.claim().

Option Type Default Description
timeout Number 15000 Page navigation timeout in milliseconds.

service-worker-update

audit:
  options:
    service-worker-update:
      timeout: 20000

The check installs the current service worker, requests a cache-busted version of its script, and verifies that the browser detects and installs the simulated update.

Option Type Default Description
timeout Number 15000 Navigation and simulated-update timeout in milliseconds.

service-worker-deployment

This check is never selected automatically, including by the full profile. It must appear in include:

audit:
  profile: full
  include:
    - service-worker-deployment

  options:
    service-worker-deployment:
      deploymentTimeout: 900000
      commandTimeout: 900000
      command:
        - ./scripts/deploy-and-wait.sh
      requiredCachedUrls:
        - /
        - /offline
      contentCheckUrls:
        - /
        - /app.js

The CLI first asks the hosted deployment check to capture a baseline. It then runs command, waits for it to finish, signals deployment completion, and waits for the service worker verification result.

See Service Worker Deployment Testing for complete Vercel, Netlify, and AWS Amplify Hosting scripts.

Local-only options:

Option Type Default Description
command Non-empty array of strings Required Executable followed by its arguments.
commandTimeout Number deploymentTimeout Maximum local command duration in milliseconds.

command is executed without a shell. This is correct:

command:
  - ./scripts/deploy-and-wait.sh

Arguments are separate array entries:

command:
  - ./scripts/deploy-and-wait.sh
  - production

Shell syntax is not interpreted inside an entry. Put pipes, redirects, and multiple shell commands inside the script.

Hosted deployment options:

Option Type Default Description
deploymentTimeout Number 600000 Maximum time to establish the baseline, coordinate deployment, and observe the deployed change.
navigationTimeout Number 15000 Navigation and resource-probe timeout.
updateTimeout Number 30000 Maximum time to observe the service worker update after a worker change is detected.
activationGracePeriod Number 1000 Delay before checking activation behavior.
pollInterval Number 3000 Interval between hosted deployment observations.
stableObservations Number 2 Consecutive matching observations required before the deployment is considered stable.
requiredCachedUrls Array of URLs [] URLs that must remain present in Cache Storage after deployment.
contentCheckUrls Array of URLs [] Cached URLs whose response content should be compared across deployment.

All timeout values are milliseconds. The deployment must produce a changed service worker file; otherwise the update cannot be verified.

Do not configure testId manually. The CLI creates the deployment test and replaces the local deployment options with the resulting testId when it creates the aggregate runtime audit.

before-install-prompt

audit:
  options:
    before-install-prompt:
      timeout: 20000

The check observes the beforeinstallprompt event while loading, interacting with, and reloading the page.

Option Type Default Description
timeout Number 15000 Page navigation timeout in milliseconds.

offline-request-retry

audit:
  options:
    offline-request-retry:
      requests:
        - requestUrl: https://example.com/api/messages
          method: POST
          requestBody:
            message: Audit test request
      retryTimeout: 8000
      offlineSettleTime: 1000
      timeout: 20000

The check takes the browser offline, sends every configured request from the page, restores connectivity, and observes whether the service worker retries each request. It passes only when all configured requests are observed offline and retried online.

Option Type Default Description
requests[].requestUrl URL Required One or more requests expected to be queued and retried. Relative URLs resolve against the audited URL.
requests[].method GET or POST Required HTTP method to test.
requests[].requestBody Any JSON value None JSON body for a POST request. It is not allowed for GET.
retryTimeout Number 8000 Time to wait for the retried request after restoring connectivity.
offlineSettleTime Number 1000 Delay after switching the browser offline.
timeout Number 15000 Page navigation timeout in milliseconds.

Use a dedicated test endpoint and test data. The check can cause a real request to reach the configured endpoint.

push-notifications

The check supports synthetic and real delivery.

Synthetic delivery does not contact an application push server:

audit:
  options:
    push-notifications:
      payload:
        title: PWA audit
        message: Synthetic test notification

Real delivery creates a new browser push subscription and calls a customer endpoint:

audit:
  options:
    push-notifications:
      applicationServerKey: YOUR_PUBLIC_VAPID_KEY
      triggerUrl: https://example.com/api/send-audit-push
      payload:
        title: PWA audit
        message: Real test notification
        pushSubscription: $subscription
      observationTimeout: 8000
      timeout: 20000

If the application stores subscriptions separately, configure subscriptionUrl:

push-notifications:
  applicationServerKey: YOUR_PUBLIC_VAPID_KEY
  subscriptionUrl: https://example.com/api/push-subscriptions
  triggerUrl: https://example.com/api/send-audit-push
  payload:
    title: PWA audit
    message: Real test notification
Option Type Default Description
payload String, object, or array Required Push data or the JSON request body sent to triggerUrl.
triggerUrl Absolute URL None Enables real push delivery and receives the trigger request.
applicationServerKey String Required with triggerUrl Public VAPID application server key used to create the subscription.
subscriptionUrl Absolute URL None Optional endpoint that receives the subscription before triggerUrl is called.
observationTimeout Number 8000 Time to observe registration and notification behavior.
timeout Number 15000 Page navigation timeout in milliseconds.

For real delivery, every value equal to the exact string $subscription inside payload is replaced recursively with the generated subscription. If there is no placeholder, triggerUrl receives only the configured payload.

The audit request sends the audited application’s origin in the HTTP Origin header when calling subscriptionUrl and triggerUrl. These endpoints must accept that origin.

The check creates a fresh subscription for the run and unsubscribes it during cleanup.

qualityGate

qualityGate:
  minimumScore: 90
  failOn:
    - critical
    - high

qualityGate.minimumScore

A number from 0 to 100. The default is 90.

The score is:

passed checks / scored checks × 100

Statuses included in the score:

  • passed
  • failed
  • warning

not-applicable, skipped, and error are not scored.

qualityGate.failOn

An array containing any of:

  • critical
  • high
  • medium
  • low

The default is:

failOn:
  - critical
  - high

The quality gate fails when either:

  • The score is below minimumScore.
  • A failed check has a severity listed in failOn.

Warnings do not trigger failOn, although they lower the score because they are scored but not counted as passed.

qualityGate.failOnWarnings

A boolean that defaults to false. When true, any warning causes the quality gate to fail.

Infrastructure errors produce an audit status of failed or partially-completed. The CLI returns its service-error exit code independently of the quality gate.

reports

reports:
  json: reports/pwa-audit.json
  junit: reports/pwa-audit.xml
Field Description
json Writes the complete audit and ordered results as formatted JSON.
junit Writes one JUnit test case for each runtime check.

Directories are created automatically. Paths are relative to the CLI working directory unless absolute paths are used.

Report files are optional and are written after the audit reaches a terminal state. Configure the CI/CD platform to retain them as artifacts.

CLI overrides

These command-line flags override configuration values:

Flag Configuration field
--profile audit.profile
--application audit.applicationId
--include audit.include
--exclude audit.exclude
--minimum-score qualityGate.minimumScore
--fail-on qualityGate.failOn

Examples:

pwa-check audit \
  --profile quick \
  --minimum-score 95 \
  https://example.com
pwa-check audit \
  --include offline,service-worker-update \
  https://example.com

The CLI flags replace the corresponding configured arrays when at least one value is supplied; they do not append to them.

Authenticated audits

For a protected PWA, provide a bearer token or cookies only at runtime. Do not put credentials in pwa-check.yml.

export PWA_AUDIT_AUTH='{"headers":{"authorization":"Bearer token"}}'
pwa-check audit --auth-env PWA_AUDIT_AUTH https://app.example.com

The service encrypts one-time CLI credentials, uses them only for the exact target origin, and expires them after the audit. Cross-origin redirects never receive them. A local --auth-file must not be readable by group or others.

Runtime-only CLI settings do not have pwa-check.yml fields:

Flag or environment variable Default Purpose
--poll-interval 2000 ms Audit and deployment status polling interval.
--audit-timeout 900000 ms Maximum time to wait for the aggregate audit.
--api-url / PWA_TODAY_API_URL https://api.pwa.today API base URL.
--idempotency-key / PWA_TODAY_IDEMPOTENCY_KEY None Reuse one logical audit request safely.
PWA_AUDIT_TOKEN Required Customer access token.
PWA_TODAY_ENVIRONMENT None Environment name included in audit source metadata.

Complete annotated example

version: 1

audit:
  applicationId: shop.example.com
  profile: full

  include:
    - service-worker-deployment

  exclude: []

  options:
    manifest:
      timeout: 20000

    offline:
      offlineUrls:
        - /
        - /products
      expectedSelectors:
        - main
      requiredText:
        - Example Store

    offline-navigation:
      series:
        - [/, /products, /checkout]
        - [/, /account]
      expectedSelectors:
        - main

    cache:
      routes:
        - url: /
          readySelector: '#home-title'
        - url: /products
          readySelector: '#products-title'

    service-worker-first-installation:
      timeout: 20000

    service-worker-handlers:
      timeout: 20000

    service-worker-update:
      timeout: 20000

    service-worker-deployment:
      deploymentTimeout: 900000
      commandTimeout: 900000
      command:
        - ./scripts/deploy-and-wait.sh
      requiredCachedUrls:
        - /
        - /offline
      contentCheckUrls:
        - /
        - /app.js

    before-install-prompt:
      timeout: 20000

    offline-request-retry:
      requests:
        - requestUrl: https://example.com/api/audit-messages
          method: POST
          requestBody:
            message: PWA audit retry test

    push-notifications:
      payload:
        title: PWA audit
        message: Synthetic notification

qualityGate:
  minimumScore: 90
  failOn:
    - critical
    - high
  failOnWarnings: true

reports:
  json: reports/pwa-audit.json
  junit: reports/pwa-audit.xml

Remove options and checks that are not relevant to the application. In particular, only enable checks that create external side effects when dedicated test endpoints and data are available.