Website Speed Optimization: Images, Fonts, JavaScript and Core Web Vitals
web.dev and Chrome’s documentation are the primary references for Core Web Vitals. This article does not include a Lighthouse run of ToolUpa. A target is not a result. ToolUpa’s budget planner uses your kilobyte estimates unless you paste a report you actually ran.
Website speed work fails in two opposite ways. Teams invent a 98 Lighthouse score in a sales deck. Or they tune micro-CSS while a 4 MB hero PNG ships on every article. A better approach is a budget: how many kilobytes of images, fonts, CSS, JavaScript and other assets you are willing to send, then a checklist that attacks the usual wastes. Measure later, with a real lab or field tool, and label those numbers as measured.
Web Performance Budget Planner adds the estimates you type, compares them to a budget, and explains a pasted PageSpeed Insights snippet only when it recognizes metric labels. It will not invent a Performance score. Optional PageSpeed API integration is not enabled because this static host has nowhere safe to keep a server-side key.
Budgets are agreements, not vibes
A budget might be 700 KB of compressed transfer for an article template: 400 images, 80 fonts, 60 CSS, 180 JS, 40 other. If the hero screenshot is 1.2 MB, you are already over before fonts load. Write the budget down. The planner’s sample uses those numbers so you can see an over/under total. Change them to match your host and your design.
| Bucket | Typical waste | First fix |
|---|---|---|
| Images | One huge PNG for all viewports | srcset/sizes, modern formats, width attributes |
| Fonts | Four families, seven weights | Two weights, font-display, subset |
| CSS | Unused framework | Delete unused, avoid huge icon packs |
| JavaScript | Analytics plus carousel plus chat | Load only what the page calls |
Images
Send the width you show. A 2400px photograph in a 560px column is a budget hole. Use width and height attributes to reduce layout shift. Lazy-load below-the-fold images. Do not lazy-load the LCP image; that delays the largest contentful paint on purpose. web.dev’s image guidance is the long form. ToolUpa articles use SVG for the favicon and avoid hero stock photos for this reason.
If the image is a YouTube thumbnail you are auditing, that is a different job: readability at stamp size. See YouTube Thumbnail Design. Compressing a thumbnail until the face smears is not optimization. It is damage.
Fonts
Self-host if you can control caching. If you use a third-party font CDN, you accept extra connections. Limit families. Fraunces plus Source Sans is already a cost on ToolUpa; that is a design choice, not a requirement for your site. font-display: swap avoids invisible text. System fonts are faster and less distinctive. Choose knowingly.
JavaScript and CSS
Defer scripts that are not needed for first paint. Do not ship a full framework to power a contact mailto link. Remove unused libraries. Render-blocking CSS should be the CSS you actually use, not a 200 KB kit for components you deleted. Compression (gzip or Brotli) is a host setting. A budget planner cannot see whether your host compresses. The checklist still reminds you to turn it on.
Core Web Vitals, labelled correctly
As of Chrome’s public documentation, the Core Web Vitals set has included Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint (which succeeded First Input Delay). Thresholds are published on web.dev and can change. This article will not reprint a number that might be stale. Look up the current thresholds when you report to a client. Paste the metric lines you actually captured into the planner if you want them next to your KB budget. If the paste has no labels, the planner says so.
Lab data (Lighthouse, PageSpeed lab) is not field data (CrUX). Do not present a local Lighthouse run as “what users see in France on 4G.” If you did not run a test, you do not have a score. ToolUpa’s README and this paragraph exist so nobody “fills in 95” for a static site that was never measured in this environment.
Caching
Hashed static assets can live a long time at the CDN. HTML should be shorter-lived if you update articles. That is a host configuration. Netlify, Cloudflare Pages and similar hosts document cache headers. Do not claim a cache policy this repo cannot enforce on toolupa.com until the host is chosen.
Worked example
You estimate 400 + 80 + 60 + 180 + 40 = 760 KB against a 700 KB budget. The planner shows 60 KB over. You replace a PNG screenshot with a 90 KB WebP and drop a unused chart library worth 120 KB. New estimate: 550 KB. Then you run PageSpeed yourself, paste “Largest Contentful Paint 2.4 s” if that is what the report said, and keep that line labelled as paste. You still do not write “ToolUpa scores 100” on a homepage.
How to talk about speed without lying in a sales deck
If you have not run Lighthouse, PageSpeed Insights or another lab tool against a URL, you do not have a lab score. If you have not looked at CrUX or another field source, you do not have a field score. Saying “we optimized Core Web Vitals” after compressing one PNG is a category error. Say what you changed: “hero image 1.2 MB to 180 KB WebP, removed unused chart library.” Those sentences are testable.
When you do run a lab test, record the conditions: which URL, which device emulation, which location, which date. Paste the metric lines into the budget planner if you want them next to estimates, and keep the paste labelled as paste. Do not average three runs in your head and write a single invented 97.
ToolUpa itself is a static Vite site with web fonts. That has a cost. This article will not claim a Lighthouse number for it because this environment did not produce a measured report to cite. That sentence is the standard you should use on client sites too.
Third-party scripts are usually the silent budget killer
Chat widgets, tag managers, heatmaps and “just one more” A/B tool arrive as small decisions and leave as hundreds of kilobytes plus main-thread work. Before you add one, add its estimated KB to the planner. If the total crosses the budget, something else must leave. “Marketing needed it” is not a byte exemption.
Load third parties after the page is usable when you can. Never block the LCP image on a survey dialog. If a script is only for logged-in staff, do not ship it to public article pages. The unused-scripts checklist item exists for this political fight, not only for leftover jQuery.
Ads, if you add them later, must stay visually separate from tool buttons and must not sit on empty result states. That is a policy choice as well as a performance choice: extra scripts cost KB and attention. ToolUpa pages do not include ads in Part 1 or Part 2.
Checklist
- Write a KB budget per template.
- Responsive images, dimensions set, LCP image not lazy-loaded.
- Fewer font files.
- Defer non-critical JS; delete unused scripts.
- Enable compression at the host.
- Cache hashed assets.
- Report only measured CWV, with lab vs field named.
FAQ
Why is there no live PageSpeed button?
The API needs a secret stored off the client. This static build will not put a key in JavaScript.
Is a 700 KB budget official?
No. It is an example. Set a budget that matches your product and network reality.
Will passing the checklist rank me?
Speed is one factor among many. Google’s documentation discusses page experience; it does not sell a guarantee.