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

@happyprime/reglance

v2.3.1

Published

Visual regression at a glance.

Readme

Reglance

Visual regression at a glance. Reglance screenshots a site across viewports, compares each page against a saved baseline, and opens an HTML report of the visual and HTML differences. It installs per-project and is configured with one reglance.json file.

Quick start

  1. Install (downloads a headless Chromium on install):

    npm install @happyprime/reglance --save-dev
  2. Add a reglance.json to the project root. List page paths relative to a default domain:

    {
    	"name": "My Site",
    	"domain": "https://site.test",
    	"paths": {
    		"home": "/",
    		"blog": "/blog",
    		"single-post": "/blog/sample-post"
    	}
    }
  3. Run the workflow:

    npx reglance capture   # screenshot every path (against the good state)
    npx reglance control   # save those captures as the baseline
    # ...make your changes...
    npx reglance capture   # screenshot again
    npx reglance compare   # diff against the baseline and open the report

control is run once to set the baseline; capture + compare are repeated to check changes against it. Output (captures, baseline, report) goes to a self-ignored .reglance/ directory — nothing to add to .gitignore.

reglance.json

| Field | Required | Description | | ------------------- | -------- | --------------------------------------------------------------------------------- | | paths | yes | Map of key → path. A value may be a full URL to point at a different domain. | | domain | capture | Default domain. A bare host (site.test) becomes https://site.test. | | name | no | Label shown in the report. Defaults to the domain host. | | viewports | no | [{ name, width, height, deviceScaleFactor? }]. Defaults to desktop (1920×1080), mobile (390×844). | | output | no | Output directory. Defaults to .reglance. | | pixelmatchOptions | no | pixelmatch options, e.g. { "threshold": 0.1 }. | | timeouts | no | { goto, settle } in ms. goto bounds navigation; settle bounds each post-scroll wait (network idle, then image load/decode). Defaults { goto: 15000, settle: 8000 }. Raise settle for slow, lazy-loading pages. | | blockHosts | no | Hostnames to block requests to during capture, e.g. ["captcha.example.com"]. Each entry also blocks its subdomains. | | imageCache | no | Serve repeat image requests from a local cache during capture. true for a per-run cache, { "persist": true } to keep it across runs. Off by default. |

domain is only needed by capture; control and compare work on the files already captured. See reglance.example.json for a full example.

blockHosts aborts every request to the listed hosts (and their subdomains) before it leaves the browser. Use it for third-party embeds that keep the network busy and stall capture — CAPTCHA widgets, ad tech, analytics — or that render differently on every load and pollute diffs. Captures wait for the network to go idle, so a widget that polls or retries indefinitely will otherwise time out every viewport on pages that embed it. Entries are bare hostnames; "example.org" blocks example.org and sub.example.org alike.

imageCache keeps a capture run from swarming the origin with the same image requests once per viewport per parallel context. Image requests are intercepted in the browser: the first request for a URL is fetched from the origin and stored under .reglance/image-cache/, and every repeat is answered locally — simultaneous requests for the same URL share a single origin fetch. The full URL, query string included, is the cache key, so CDN resize variants (photo.jpg?w=400 vs photo.jpg?w=800) stay distinct. Nothing in the page is rewritten and only images are cached — the HTML, CSS, and JS under test always load from the origin. With true the cache is cleared at the start of every run, so within-run traffic drops with zero risk of a stale image masking a real change. { "persist": true } keeps the cache across runs — useful when re-capturing repeatedly while iterating on CSS — but a changed origin image will then go unnoticed until you clear it with --fresh-images.

A viewport's optional deviceScaleFactor (device pixel ratio) renders the page as it would appear on a higher-density display — use 2 for a retina capture, 3 for some phones. It defaults to 1. Captures sharing a DPR run in one browser context; a new DPR opens a fresh context, so prefer grouping retina and non-retina variants rather than scattering them. Note that a screenshot is twice the pixel dimensions of its counterpart, so changing the deviceScaleFactor of an existing viewport will diff against its controls as fully changed until you re-run reglance control.

A paths value may be a full URL pointing at a different host than domain. This is supported, but capture prints a warning listing such paths so off-domain navigation is a conscious choice — keep configs from trusted sources, since the report renders captured content.

Commands

| Command | Description | | ------------------- | ------------------------------------------------------------------- | | reglance capture | Screenshot every path across all viewports into .reglance/captures. | | reglance control | Promote the latest captures to the baseline (.reglance/controls). | | reglance compare | Diff the latest captures against the baseline and open an HTML report. |

Append path keys to limit a command to specific pages: npx reglance capture home blog.

Options

| Flag | Command | Description | | -------------------------- | ------- | --------------------------------------------------------------------------------- | | --domain=<host> | capture | Override the configured domain for this run. | | --concurrency=<n> | capture | Parallel browser contexts (default: 4). Must be a positive integer. | | --stagger=<ms> | capture | Delay between starting contexts (default: 500). 0 disables staggering. | | --skip-reload | capture | Reuse the page between viewports instead of reloading. | | --fail-on-degraded | capture | Exit non-zero if any page failed to load cleanly (for CI). Default: warn, exit 0. | | --fresh-images | capture | Clear a persistent image cache before capturing (see imageCache). | | --insecure | capture | Ignore TLS certificate errors for non-local hosts (already ignored for .test/localhost). | | --compare-concurrency=<n>| compare | Parallel diff workers (default: CPU count − 1). Lower it for very tall pages. | | --no-open | compare | Don't open the report when finished. | | --config=<path> | any | Path to the config file (default: reglance.json). |

Per-developer domains

domain is the shared default; override it per run so teammates can point at their own local site without editing the config:

npx reglance capture --domain=site2.test

Trustworthy baselines

A baseline is only useful if it reflects pages that actually loaded. reglance guards against silently baselining bad data:

  • If a page never loads cleanly (after retries), capture reports it as degraded instead of treating it as a success. Add --fail-on-degraded to make the run exit non-zero in CI.
  • capture scrolls each page one viewport at a time so every lazy-loaded image is triggered, then waits (bounded by timeouts.settle) for all images to load and decode before screenshotting — and warns per capture when any image was still loading, instead of silently shipping a partial screenshot.
  • control records each promotion in .reglance/controls/manifest.json and warns when it promoted fewer captures than expected (so the untouched controls are now stale). compare warns when the baseline mixes controls from more than one control run.

Output

.reglance/
	captures/   Latest screenshots + HTML snapshots
	controls/   Baseline screenshots + HTML (+ manifest.json)
	compares/   Diff images
	reports/    The report — open reports/index.html
	assets/     Report stylesheet + script
	image-cache/ Cached image responses (only with imageCache enabled)

The report is a single reports/index.html that embeds every result as JSON and renders three views client-side from the URL hash — a triage overview (grouped by page, changed-only by default, keyboard-navigable), a comparison view (swipe, side-by-side, onion skin, diff overlay, blink), and a unified HTML diff. It opens straight from disk with no network access.

Development

npm run lint   # check style
npm run fix    # auto-fix style