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

@tracelane/playwright

v0.1.0-alpha.9

Published

Playwright reporter + auto-fixture that writes a self-contained replayable HTML report on failed tests — or every test in `all` mode (rrweb + console + failed-network). No SaaS.

Readme

@tracelane/playwright

The recorder for your Playwright tests. When a test fails, you get one HTML file you can email — media inlined, so it replays the whole session like a video the moment someone double-clicks it. No server, no unzip, no show-trace, no toolchain. Under the hood it's rrweb continuous DOM replay (not discrete snapshots) across every navigation, plus the console and failed-network panels. Apache-2.0. No SaaS, no dashboard, no signup, no cloud.

Why one file matters. A trace.zip can't be double-clicked — it needs npx playwright show-trace or the hosted web viewer over http(s)://. The built-in HTML reporter is a server-served folder (show-report); open it over file:// and you get a blank screen. tracelane's artifact is a single .html with all media inlined — drop it in a bug ticket, email it, archive it, and it still replays standalone. (Plenty of reporters write "a single HTML file"; the part that's specific here is the fully-inlined media plus rrweb continuous session replay, so the file plays back like a screen recording with no dependencies.)

npm downloads license CI OpenSSF Scorecard types node status: alpha

Docs: https://tracelane.cubenest.in

Install

npm install --save-dev @tracelane/playwright

@playwright/test (>= 1.40) is a peer dependency — you already have it. Requires Node >= 22.

Wire it (two edits)

1. Register the reporter in playwright.config.ts:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  reporter: [
    ['list'],
    ['@tracelane/playwright', { mode: 'failed', outDir: './tracelane-reports' }],
  ],
});

2. Use tracelane's test/expect in your specs (a drop-in for @playwright/test):

import { test, expect } from '@tracelane/playwright/fixture';

test('checkout', async ({ page }) => {
  await page.goto('/checkout');
  await expect(page.getByRole('heading')).toHaveText('Order complete');
});

That's it. The fixture is auto — every test in files that import this test is recorded; nothing else to wire per-test.

Run your suite. On a failing test you get one .html file at ./tracelane-reports/<spec>--<title>--<project>-<ts>.html. Double-click it — it opens in any browser, fully offline, with every asset inlined (nothing fetched, nothing to unzip, no local server). Scrub the run as a rrweb continuous DOM replay, inspect the console + failed-network panels, drop it into a bug ticket, archive it forever.

How it works

  • The fixture owns the recording — and keeps it going across navigations, so the replay is one continuous session, not a set of per-page snapshots. It is the only place with a live page + testInfo, so it injects the rrweb bundle via context.addInitScript AND hooks page.on('framenavigated') to call recorder.reinject on every main-frame navigation (each navigation emits a tracelane.nav boundary marker in the replay). It starts the recorder before your test body, and — after it — builds + writes the report. It reuses @tracelane/core's recorder and @tracelane/report's HTML builder.
  • The reporter owns config only: it validates options at startup and bridges them to the fixture via TRACELANE_* env vars. By design it never touches page, prints nothing, and produces no end-of-run summary (the fixture writes the per-test reports).
  • Network capture is captured in-page by the framework-agnostic rrweb/network@1 plugin — it works on every browser (Chromium, Firefox, WebKit) with no CDP, because it wraps fetch/XHR and reads PerformanceObserver entries from inside the page. Privacy-first: only URL/method/status/timing (headers + bodies off). On Chromium tracelane additionally uses CDP to enrich the panel with authoritative HTTP status for failed responses (4xx/5xx) and true no-response failures (CORS/DNS/offline/abort); the report merges the CDP rows over the in-page rows for the same request (real status wins). Off entirely when capture.network is false.
  • Parallel-safe: report filenames are namespaced by the Playwright project name and carry a millisecond timestamp. Different projects are isolated by name; parallel workers within one project share the project-name segment and rely on the timestamp (plus spec + title) to stay distinct.
  • Coexists with Playwright's own trace — keep trace: 'on-first-retry' if you like; tracelane writes a separate, self-contained artifact.

Options

| Option | Type | Default | Notes | | --- | --- | --- | --- | | mode | 'failed' \| 'all' | 'failed' | 'failed' writes a report only on failure; 'all' writes one for every test. Env: TRACELANE_MODE. | | outDir | string | './tracelane-reports' | Where reports are written. Env: TRACELANE_OUT_DIR. | | capture.rrweb | boolean | true | Record the rrweb session. When false, no recorder starts and no report is written at all. Env: TRACELANE_CAPTURE_RRWEB. | | capture.network | boolean | true | Network capture: the in-page rrweb/network@1 plugin on all browsers, plus CDP enrichment (authoritative status + no-response failures) on Chromium. Env: TRACELANE_CAPTURE_NETWORK. Supersedes the deprecated top-level captureNetwork. | | capture.console | boolean | true | Capture console.* via the rrweb console plugin. When false the console plugin patches nothing ({ level: [] }). Env: TRACELANE_CAPTURE_CONSOLE. | | capture.networkOptions | NetworkRecordOptions | plugin defaults | Forwarded to the in-page network plugin (recordHeaders, recordBody, payloadHostDenyList, …). Defaults are privacy-first (headers + bodies off). Ignored when capture.network is false. Function-valued props (maskRequestFn, maskResponseFn) are NOT supported via reporter config — see below. Env: TRACELANE_NETWORK_OPTIONS (JSON). | | consolePluginOptions | ConsolePluginOptions | plugin defaults | Forwarded to the in-page console plugin. Env: TRACELANE_CONSOLE_OPTIONS (JSON). | | security | boolean | true | Advisory security-hygiene signals in the report. false disables both the [tracelane.sec] capture and the report-side analysis (the report omits the "Security hygiene (advisory)" section). Env: TRACELANE_SECURITY. | | report.footer | boolean | true | Render the report's "Generated by tracelane" footer. false suppresses it. Env: TRACELANE_FOOTER. | | drainIntervalMs | number | 500 (core default) | Node-side drain poll interval. Env: TRACELANE_DRAIN_INTERVAL_MS. | | cooldownMs | number | 250 (core default) | Re-injection cooldown guard (suppresses double-init on hash/HMR navigation). Env: TRACELANE_COOLDOWN_MS. | | captureNetwork | boolean | true | Deprecated — use capture.network. Kept for back-compat; capture.network wins when both are set. Env: TRACELANE_CAPTURE_NETWORK. |

The options type is published — import type { TraceLaneOptions } from '@tracelane/playwright'.

The options→env bridge. The Playwright fixture runs in a separate worker process and reads its configuration only from TRACELANE_* env vars. The reporter bridges its constructor options to those env vars at startup — but only when the env var is not already set, so an explicit env var (or CLI value) always wins. Boolean/number options bridge as strings; capture.networkOptions and consolePluginOptions bridge as JSON strings.

Mask functions are not supported via reporter config (worker-process limitation). Because options cross to the fixture worker as env-var strings, the JSON bridge for capture.networkOptions cannot carry function-valued props — maskRequestFn / maskResponseFn are silently dropped (JSON.stringify strips them). Use only JSON-serializable masking options (recordHeaders, recordBody, payloadHostDenyList, …) when configuring through the reporter.

Security hygiene (advisory)

By default the report includes an advisory security-hygiene section derived from privacy-safe main-document response metadata captured on Chromium ([tracelane.sec] — security-header presence + cookie-flag hygiene; never header or cookie values). Set security: false to disable both the capture and the report-side analysis.

You can silence known-acceptable signals by committing a tracelane.security.suppress.json file in the project working directory; it's loaded at report-write time (a missing/malformed file never throws — it degrades to no suppressions):

{
  "suppressions": [
    { "signal": "missing-csp", "evidence": "https://app.test" },
    { "signal": "insecure-cookie" }
  ]
}

It carries only advisory { signal?, evidence? } rules — no secrets — so reading it from the working directory is safe.

What this is NOT

  • Not a SaaS. There is no upload, no signup, no dashboard, no telemetry. The artifact is a single HTML file on your filesystem — and unlike reporters that link screenshots/video by relative path, every asset is inlined, so the file keeps replaying even when it's moved or emailed on its own.
  • Not a replacement for Playwright's trace viewer. The trace viewer is the deeper local-debugging tool; tracelane is for the handoff — a double-clickable file:// replay (media inlined, no local server, no show-trace/show-report step) you can hand to anyone with a browser. The capture model differs too: Playwright records discrete per-action snapshots, tracelane records a continuous rrweb session.

Limitations

Content-Security-Policy: rrweb capture requires in-page script evaluation. If a page's CSP blocks 'unsafe-eval', capture degrades gracefully — the test still runs and completes normally, a warning is logged, but no replay is recorded for that page.

Cross-origin navigations: buffered rrweb events are rescued across same-origin hard navigations via a pagehidesessionStorage flush. Cross-origin hard navigations are a known edge case — sessionStorage is per-origin, so events buffered immediately before a cross-origin navigation may be lost.

License

Apache-2.0. See NOTICE for bundled third-party software (the rrweb fork + console plugin).

For the privacy/security posture of the capture (what is and isn't recorded, masking, and the advisory security-hygiene signals), see the security notes.

Full version history: CHANGELOG.

Related packages

Part of the tracelane stack: