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

pr-doctor

v0.0.11

Published

CLI that gates PRs by pixel-comparing a running app against Figma design baselines

Downloads

1,715

Readme

pr-doctor

CLI + thin GitHub Action that gates PRs by pixel-comparing a running app against Figma design baselines.

Unlike visual-regression tools (Lost Pixel, Percy, Chromatic) that compare implementation now vs implementation before and need humans to approve screenshot baselines, pr-doctor treats Figma as the source of truth. A designer edit updates the baseline; there is no “approve this PNG” ritual.

v1 scope: pull → capture → compare → report; optional AI fix loop; optional E2E session video. No SaaS, no review web UI, no cloud baseline store.

Requirements

  • Node.js ≥ 20
  • Chromium (via Playwright; install with npx playwright install chromium if needed)
  • Figma access token with file_content:read (and ideally file_metadata:read for cheap version polling)

Install

npm install -D pr-doctor
# or run without install:
npx pr-doctor@latest check

Quickstart

  1. Configprdoctor.config.json at the repo root (or .mjs / .js with a default export):
{
  "figma": {
    "fileKey": "YOUR_FIGMA_FILE_KEY"
  },
  "capture": {
    "serve": {
      "command": "npm run preview",
      "url": "http://127.0.0.1:4173",
      "readyTimeoutMs": 60000
    }
  },
  "regions": [
    {
      "name": "primary-cta",
      "figmaNode": "12:34",
      "path": "/",
      "selector": "[data-testid=primary-cta]",
      "viewport": { "width": 1280, "height": 720 }
    }
  ],
  "compare": {
    "threshold": 0.1,
    "maxDiffPixelRatio": 0.01,
    "scale": 2,
    "background": "#ffffff"
  },
  "report": {
    "comment": true,
    "media": "auto"
  }
}

Secrets never go in config. figmaNode accepts a bare node id (12:34 / 12-34), fileKey:nodeId, or a full Figma URL.

  1. Env

| Variable | Used by | Notes | |---|---|---| | FIGMA_ACCESS_TOKEN | pull / check | PAT or plan access token; Dev or Full seat on the plan that owns the files (View/Collab seats hit ~6 image exports/month and are unusable for CI) | | GITHUB_TOKEN | report / CI comment | default in Actions | | PRDOCTOR_API_KEY | fix | OpenRouter-compatible key | | PRDOCTOR_MODEL | fix | model id for the agent |

Figma rate limits (Tier 1 image export): on the order of 10–20/min depending on seat. pr-doctor caches baselines by file version (cheap meta call each run) and only re-exports when the version changes. On 429 it honors Retry-After once, then falls back to cache (warn) or exits 3.

  1. Run
export FIGMA_ACCESS_TOKEN=…
prdoctor check

Artifacts land in .prdoctor/run/<region>/{design,actual,diff}.png and .prdoctor/run/score.json.

Commands

| Command | Does | Exit codes | |---|---|---| | prdoctor pull | Fetch Figma baselines for all (or --region) regions; version cache | 0 · 2 config · 3 Figma/API | | prdoctor check | pull (unless --no-pull) → serve/attach → capture → compare → artifacts (+ PR comment in CI) | 0 pass · 1 over tolerance · 2 config · 3 env/infra | | prdoctor fix | check; on fail, agent edits within fix.boundary, recheck ≤ maxRounds | 0 fixed/pass · 1 still failing · 2/3 | | prdoctor e2e | Run configured Playwright specs with video; stage under .prdoctor/run/e2e/ | 0 · 1 test fail · 3 env | | prdoctor report | (Re)post PR comment from existing artifacts | 0 · 3 |

Flags of note:

  • check --no-pull — use cached .prdoctor/baseline/ only
  • check --region <name> / pull --region <name>
  • check --at <versionId> / pull --at <versionId> — pin Figma file version
  • fix --push — push fix commits (CI)
  • report --dry-run — print markdown without posting

Global: --config <path>, --cwd <path>.

Exit codes (uniform)

| Code | Meaning | |---|---| | 0 | Pass | | 1 | Quality gate failed (diff over tolerance, or e2e test fail) | | 2 | User/config error (bad config, size-mismatch design vs capture, missing token when required as config-class) | | 3 | Environment / infra (Figma API, browser, network, serve timeout) |

A Figma outage or 429 is exit 3, not a red visual gate. Size mismatch is exit 2 — no silent resize.

score.json shape: { regions: [{ name, diffPixelRatio, pass, dims, figmaFileVersion? }], pass } — real ratios only, no display inflation.

Media modes (PR comments)

Controlled by report.media (default auto):

| Mode | Behavior | When | |---|---|---| | auto | public repo → branch; private → artifact | default | | branch | push media to orphan branch prdoctor-media; inline via raw URLs | public repos only for reliable inline images | | artifact | scores table + link to Actions artifact (no true inline images) | private repos, zero setup | | s3 | upload to S3/R2; embed signed URLs (default TTL 7d) | private repos wanting inline |

Private-repo honesty: GitHub’s image proxy fetches raw.githubusercontent.com unauthenticated, so branch-hosted images break in private repos. There is no supported bot API for PR-comment image attachments. Use artifact (default via auto) or s3 for private repos.

Fix loop

{
  "fix": {
    "enabled": true,
    "maxRounds": 2,
    "boundary": ["src/components/**"]
  }
}
export PRDOCTOR_API_KEY=… PRDOCTOR_MODEL=…
prdoctor fix          # local
prdoctor fix --push   # CI: push commits with PR-Doctor-Fix: trailer
  • Edits outside boundary are rejected.
  • Hard gate: a push that still fails tolerance exits 1 (not “soft green”).
  • Re-entry: workflows should skip the fix stage when the head commit message contains PR-Doctor-Fix: (the composite action does this).

E2E video

{
  "e2e": {
    "enabled": true,
    "specs": "e2e/**/*.spec.ts"
  }
}

Runs the repo’s Playwright specs with video on; stages webm (+ gif/mp4 when ffmpeg is available). E2E failure is exit 1. Teams without specs leave e2e unset / disabled.

GitHub Action

Thin wrapper: npx pr-doctor@<version> — pin version for reproducibility.

# .github/workflows/pr-doctor.yml
name: PR Doctor
on:
  pull_request:
    types: [opened, synchronize, reopened]

concurrency:
  group: pr-doctor-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  visual-gate:
    runs-on: ubuntu-latest
    permissions:
      contents: write   # fix --push / media branch
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: 1infra/1doctor/action@main   # or path to this action/
        with:
          figma-token: ${{ secrets.FIGMA_ACCESS_TOKEN }}
          github-token: ${{ secrets.GITHUB_TOKEN }}
          # config: prdoctor.config.json
          fix: "false"
          e2e: "false"
          version: latest
          # api-key / model — only if fix: "true"

Action steps: re-entry guard → check → optional fix --push on exit 1 → optional e2e on success → best-effort report → always upload .prdoctor/run artifact.

Troubleshooting

| Symptom | Cause / fix | |---|---| | 403 / “token expired or invalid” | PATs expire ≤90 days. Regenerate FIGMA_ACCESS_TOKEN. On Org/Enterprise prefer a plan access token not tied to one employee. | | 429 rate limit | Dev/Full seat required; View/Collab is unusable. Cache by file version reduces Tier-1 spend. Wait / Retry-After, or commit .prdoctor/baseline/ as offline fallback (warn path). | | size-mismatch (exit 2) | Design PNG dims ≠ capture dims. Align Figma frame size, scale / deviceScaleFactor, and region selector/viewport. Silent crop/resize is refused so layout bugs stay visible. | | Gate red, tiny AA/text diffs | Expected Figma-vs-Chromium differences; tune compare.threshold and maxDiffPixelRatio. Bit-identity is a non-goal. | | Dynamic content noise | Use region mask selectors and waitFor; capture already sets reducedMotion: reduce. | | Preview never ready (exit 3) | Raise capture.serve.readyTimeoutMs; check serve logs (timeout includes last output lines). | | Private PR images broken | media: branch cannot inline in private repos. Use auto/artifact or s3. |

License

MIT