Six audits in a row, six sites blaming the framework, and not once was the framework the problem. Here is what was actually eating the budget.
Every one of these projects arrived with the same sentence attached: “we built it on Next.js so it should be fast.” The framework gives you a good starting position. It does not stop you from shipping a 2.4 MB hero image, four analytics scripts loaded in the head, and a font stack that blocks first paint for a second and a half.
1. The images nobody looked at
On four of six projects, images accounted for more than 70% of the transferred bytes on the landing page. In three cases the CMS was serving originals straight from the media library, and the responsive component had been swapped out at some point for a plain tag because “it was easier for the content team.”
Convenience for the content team is a real requirement. It just needs to be solved in the pipeline, not by turning optimisation off.
The fix is boring and it works: resize on upload, serve modern formats, set explicit dimensions so nothing shifts, and lazy-load anything below the fold. Median LCP across those four sites dropped from 4.1s to 1.6s without a single component being rewritten.
2. Third-party scripts, loaded like it is 2014
Tag managers are where performance goes to die quietly. One site was loading a chat widget, two heatmap tools, a retargeting pixel and a cookie banner — all synchronously, all before anything the visitor came for.
Nobody in the business could name the last time anyone opened the heatmap tool. Deleting two scripts is not an engineering decision, it is a conversation. Have the conversation.
3. Rendering strategy chosen by default
Pages that change twice a year were being server-rendered on every request. Pages with live availability were statically cached. Both of those are one line of configuration and both were simply never revisited after the first sprint.
Go through the route list once a quarter with the person who knows how often each page's content actually changes. It takes an hour and it is the highest-leverage hour in the whole audit.
4. Fonts that block the first paint
Three of the six were loading four weights of two families from a third-party origin, with no display strategy set. That is a connection, a DNS lookup and a render block before a single word appears.
Self-host, subset to the characters you actually use, and set a swap behaviour. Two weights is almost always enough, and the design rarely notices the third one leaving.
What this means for your next build
None of these are framework problems and none of them are difficult. They accumulate because performance is treated as an engineering task at the end rather than a design constraint at the start — and by the end, the expensive decisions have already been made.
Put a byte budget next to the hero on the day it is designed. It changes the conversation from “can we make this faster” to “is this worth what it costs”, which is the only version of the conversation that ever works.
Want this run on your site?
A fixed-fee performance audit, delivered in a week.