Background
Telebari is a regional TV broadcaster based in Bari. Its website, built with WordPress, publishes news every day on crime, politics, sport and current affairs from the region, with an archive that keeps growing. It is the typical profile of a publishing site: many pages built on a few templates, traffic peaks tied to breaking news and readers who mostly arrive from smartphones, often from social media and Google Discover.
The site ran on a LiteSpeed server with the LSCache plugin, which handled both page caching and front-end optimizations: CSS combining and asynchronous loading, automatic style generation, font and image optimization. A convenient setup, but one in which many decisions were left to automatic processing, page by page.
What the data said
In real-user data the mobile Core Web Vitals were failing, with an LCP at the 75th percentile of around 3.6 seconds and a CLS of 0.24. Lab tests on mobile confirmed the picture: First Contentful Paint at 3.2 seconds, Largest Contentful Paint at 6.4 seconds, Total Blocking Time at 540 milliseconds, Cumulative Layout Shift at 0.31 and Speed Index at 5.1 seconds.
Beyond the numbers, the problem was visible to the naked eye. When a page opened, the content first appeared unstyled, or with partial styles, and then rearranged itself: menus, headers and news blocks changed shape and position with an obvious flicker. An unpleasant glitch for readers and out of keeping with the image of a news outlet.
The diagnosis
The analysis traced the flicker and the CLS to a few causes that added up:
- CSS loaded asynchronously without adequate critical CSS: the page was painted with incomplete styles and recomposed when the rest of the CSS arrived;
- heavy, unoptimized web fonts, which replaced the fallback fonts with different metrics and made text shift once loaded;
- elements without reserved space, such as images, banners and blocks loaded later;
- critical resources discovered late: the main image and the fonts were requested only after the CSS was parsed, delaying LCP.
Server-side work
The first step was to move page caching from the plugin to the server. The site was migrated from LiteSpeed with LSCache to NGINX with Varnish Cache in front, with targeted invalidation: when an article is published or updated, only that article, the home page and the categories involved are purged, not the whole site. The most-read pages always stay in cache, archive pages enter it on the first visit, and the server response became fast and predictable even during traffic peaks.
Application-side work
On the front end we gave up the automatic optimizations and worked by hand, template by template:
- Critical CSS generated and verified for the home page, categories and articles, inlined in the head, with the rest of the CSS loaded without blocking rendering and without visible recomposition;
- font subsetting, reducing the files to the characters actually needed and aligning the fallback font metrics, so that the swap no longer shifts the text;
- targeted preload and preconnect, only for truly critical resources such as the main image and the fonts, and for the origins they depend on;
- reserved space for images, banners and blocks loaded later.
Results
Comparison of the lab tests on mobile, before and after the work:
| Metric (lab, mobile) | Before | After |
|---|---|---|
| First Contentful Paint | 3.2 s | 1.4 s |
| Largest Contentful Paint | 6.4 s | 2.6 s |
| Total Blocking Time | 540 ms | 130 ms |
| Cumulative Layout Shift | 0.31 | 0.001 |
| Speed Index | 5.1 s | 1.4 s |
CLS is practically zero and the flicker when pages open has disappeared: the content appears already in its final shape. The loading time of the main element has more than halved and the main thread is far less busy. What it took was not a more powerful plugin, but moving the cache to the server level and making a few targeted optimizations, template by template.
How we maintain the result
Critical CSS needs updating when a page template changes, not when an article is published: that is why it is tied to theme releases and verified with every change. Lab tests on the main pages are repeated with every release, and real-user data is followed over time, knowing that the Chrome UX Report reflects improvements with a rolling 28-day window.