Nothing to hand? Load the — a marketing page whose hero is a 1.4 MB JPEG, whose CSS blocks the parser and whose three analytics tags own a third of the bytes — or the , a docs page already inside every threshold with nothing to report. Both replay a saved run for free.
Everything measurable is measured before anything is sent
Five capture formats are told apart and normalised into one shape: a Lighthouse JSON report, a PageSpeed Insights response, a HAR, a delimited resource table, or a handful of metric readings typed one per line. From there the vitals are banded against the published good and poor thresholds with the gap to good stated, the weight is tallied per resource type in both wire and decoded bytes so an uncompressed response is visible as such, and the whole thing is graded on what the capture could not show — because a HAR has no LCP and a resource table has no code coverage, and an audit that hides its own blind spots is worse than one that admits them.
A budget you can argue with, and a savings total that cannot double count
The budget starts from a page-type preset and every adjustment is its own line with its own delta and its own reason, so a reviewer can reject one without re-deriving the rest. Type your own target and it replaces the preset for that field and cancels the adjustments above it — adding an override to a derived base is how a budget silently doubles, and the page asserts the exclusivity rather than assuming it. The savings ledger is built the same way: rules run in a fixed precedence order and each resource is removed from the pool the moment a rule claims it, so no file is counted by two rules. Cache savings live in their own ledger, because a byte saved on the second visit was not also saved on this one.
The metered pass is attribution, and it is allowed to disagree
Twenty-three findings are matched against the capture, and each one reads only the fields it is about — the image rule never inspects a script's bytes and the cache rule never inspects a mime type, because a detector that reads the whole record produces findings nobody can defend. What the arithmetic cannot do is say which of them is the cause: a 900 KB hero and 300 ms of blocking CSS are both real, but if TTFB alone is 1.9 s then neither is why the paint lands at 4 s. So the model is asked to attribute, to write the fix for the stack you described, to rank the work by impact against effort, and to return a verdict on every finding — including “false positive”, which is often the right answer: an SVG sprite counted as an image, or a deliberately uncached personalised fragment. Audits are saved to your account, so the next capture is diffed against this one.
This is analysis of a capture you supply. Vitals Desk never fetches your page. Core Web Vitals thresholds are the published bands, but the budget presets, the savings estimates and the severity of each finding are this app's stated conventions rather than anyone's standard, and an estimated saving is arithmetic on one capture rather than a promise about your users. Measure again on real devices after every change. A derived work of @sickn33/web-performance-optimization, whose measure-identify-prioritise-implement-verify loop, Core Web Vitals targets and performance checklist are what this app measures against.