Vitals Desk

Drop the Lighthouse report or the HAR. The browser bands and budgets it; the model says what to fix first.

Back to SkillSafe
Or pick a file — read locally, nothing uploads until you run. A Lighthouse report is often several megabytes; that is fine — the file is parsed in full outside the edit box, and only the derived summary ever travels.
I don’t have a capture yet — how do I get one?

Three ways, cheapest first. Put the page address in Page audited below and these fill themselves in. Nothing here leaves your browser.

1. No tooling at all — PageSpeed Insights

Google runs Lighthouse for you and shows real-user field data alongside it. Run it, then use the page’s own JSON export — or call the API directly and drop the whole response here, wrapper and all; it is recognised as a PageSpeed response automatically.

Open PageSpeed Insights for this page


          

2. Lighthouse on your machine

The most detailed capture, and the only one that carries code coverage. It must be --output=json: a Lighthouse HTML report cannot be read here.


          

3. A HAR, from the browser you already have open

No install needed, and it is the right capture when the question is about bytes, caching or third parties rather than about paint.

  1. Open DevTools on the page, go to the Network panel.
  2. Tick Disable cache, then reload the page and let it settle.
  3. Right-click any row → Save all as HAR (with content).
  4. Drop the .har file on the box above.

A HAR records the network, not the rendering, so it carries no LCP, CLS or INP. Type those into the advanced panel below if you have them and they will be banded with everything else.

Adds a stated 40 KB script allowance for the runtime — never a hidden multiplier.
Roughly where a page has to sit to hold the good band on a mid-range Android.
Your own budget, and metrics the capture did not carry

An explicit budget replaces the preset for that field and cancels every adjustment above it — it is never added to them. Leave a box blank to keep the derived value. Sizes are in KB on the wire.

A HAR records the network, not the rendering, so it carries no LCP, CLS or INP. If you have those numbers from the field or from a separate run, type them here and they will be banded with everything else. A value under 60 without a unit is read as seconds.

How it works

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.

1

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.

2

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.

3

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.

The twenty-three findings, and the fields each one is allowed to read

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.