Skip to content

feat: add webperf-snippets CLI (MVP)#73

Open
nucliweb wants to merge 10 commits intomainfrom
feat/cli-mvp
Open

feat: add webperf-snippets CLI (MVP)#73
nucliweb wants to merge 10 commits intomainfrom
feat/cli-mvp

Conversation

@nucliweb
Copy link
Copy Markdown
Owner

@nucliweb nucliweb commented Apr 29, 2026

Summary

  • Adds a headless CLI that runs curated WebPerf Snippets via Playwright, enabling Core Web Vitals diagnosis and CI budget gating without manual DevTools copy-paste.
  • Root package renamed to webperf-snippets-docs (private, no external impact); cli/ added as npm workspace with name: webperf-snippets.
  • Zero non-peer deps — only requires Node ≥ 20.12 and Playwright as a peer dependency.

Available snippets

Alias Snippet Category
LCP Largest Contentful Paint Core Web Vitals
CLS Cumulative Layout Shift Core Web Vitals
LCP-Subparts LCP Subparts breakdown Core Web Vitals
fonts Fonts Preloaded, Loaded, and Used Above The Fold Loading

The default workflow runs LCP + CLS and auto-enqueues LCP-Subparts if LCP exceeds 2.5s.

What it does

# Default workflow: LCP + CLS, auto-enqueues LCP-Subparts if LCP > 2.5s
npx webperf-snippets https://example.com

# JSON output for CI pipes
npx webperf-snippets https://example.com --json

# Single snippet by alias
npx webperf-snippets https://example.com --snippet LCP-Subparts
npx webperf-snippets https://example.com --snippet fonts

# Budget gating — exits 1 on violation
npx webperf-snippets https://example.com --budget-lcp 2500 --budget-cls 0.1

Key implementation detail

Chrome does not expose largest-contentful-paint or layout-shift entries via performance.getEntriesByType() without a buffered observer running before the entries are emitted. The runner installs an addInitScript shim before navigation that captures entries via observers and patches getEntriesByType so existing snippets work unmodified.

This is also a real bug in the snippets' // Synchronous return for agent paths — tracked and fixed in a separate PR.

Files added

File Purpose
cli/package.json Package config, bin, peer dep
cli/src/bin.js CLI entry, util.parseArgs, exit codes 0/1/2
cli/src/runner.js Playwright launch, warmup shim, snippet evaluator
cli/src/load-snippet.js Resolves snippets by name/path
cli/src/workflows/cwv.js Core Web Vitals workflow definition
cli/src/decision-tree.js Declarative follow-up rules
cli/src/reporters/human.js Colour table via util.styleText
cli/src/reporters/json.js Raw JSON output
cli/README.md Usage, options, CI example, roadmap, known limitations

Test plan

  • node cli/src/bin.js --help prints usage
  • node cli/src/bin.js https://web.dev returns green LCP + CLS with element info
  • node cli/src/bin.js https://web.dev --json returns valid JSON with all fields
  • node cli/src/bin.js https://web.dev --snippet LCP-Subparts shows sub-part breakdown
  • node cli/src/bin.js https://web.dev --snippet fonts shows loaded/used-above-fold font tables
  • node cli/src/bin.js https://web.dev --budget-lcp 100 exits 1 with violation on stderr
  • Lower decision-tree threshold temporarily → confirm LCP-Subparts fires automatically with reason line

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
webperf-snippets Ready Ready Preview, Comment May 1, 2026 6:45am
webperf-snippets-u6am Ready Ready Preview, Comment May 1, 2026 6:45am

Adds a headless CLI that runs curated WebPerf Snippets via Playwright,
enabling Core Web Vitals diagnosis and CI budget gating without manual
DevTools copy-paste.

- npx webperf-snippets <url> runs LCP + CLS with human-readable output
- --json, --snippet, --budget-lcp/cls, --headed, --wait flags
- Decision tree: LCP > 2.5s auto-enqueues LCP-Sub-Parts
- Runner shims performance.getEntriesByType for LCP/layout-shift entries
  (Chrome does not expose these via the API without a buffered observer)
- Zero non-peer deps, requires Node >= 20.12, Playwright as peer dep
- Root package renamed to webperf-snippets-docs; workspace added at cli/
Replace the hardcoded desktop viewport with named presets (mobile, tablet,
desktop). Mobile (375×812) is now the default, matching real-world usage.
The --viewport flag lets callers select a preset from the CLI.
Add Vitest as dev dependency with three test layers:
- Unit tests for decision-tree, reporters (JSON and human), and viewport presets
- E2E tests using Playwright against a local HTTP server to verify LCP and
  CLS snippets return valid results on a real browser session
Publish to npm on cli-v* tags via publish-cli.yml. The workflow runs
the full test suite (unit + E2E) before publishing. Access is controlled
via GitHub tag protection rules on the cli-v* pattern.
Adds --snippet fonts as a short alias for the Fonts-Preloaded-Loaded-and-used-above-the-fold snippet.
Reporter now shows loaded fonts table (with font-display warnings for block/auto) and used-above-fold
table, matching the detail level of the browser console output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant