A 100 on mobile PageSpeed is rare. Not unicorn rare. More like ten-thousand-saw-something-and-thought-it-was-an-eagle rare. I have personally run PageSpeed Insights on more than two hundred small business websites in the last month as part of pre-pitch research, and exactly one of them scored 100 on mobile. It was the one I built.
That fact makes for a useful headline, but the more interesting question is structural. Why is the number so hard to reach on mobile when desktop 100s are common enough to be unremarkable? And once you reach it, what does the score actually buy you?
This is a working teardown of how a five-location lice treatment business in Texas got there, what the modern web stack does to your odds before you write a single line of code, and where the metric quietly lies to you about user experience.
The mobile score is not just the desktop score with smaller pixels
Lighthouse, the engine behind PageSpeed Insights, simulates a slow 4G network connection and a throttled mobile CPU when it runs the mobile audit. This is not a real device. It is a deliberately punishing test environment designed to expose performance assumptions you can get away with on a fast laptop.
The throttling is aggressive. Network throughput is capped at roughly 1.6 Mbps. CPU is slowed to about a quarter of a typical desktop core. Every kilobyte of JavaScript you ship has to download slower and execute slower than your dev experience suggests it will. The same site that returns 99 on desktop can return 65 on mobile because the mobile test refuses to lie to you about what your code costs.
This is why most “fast” sites land in the 80 to 95 range on mobile. They are fast enough on real phones to feel responsive. They fail the synthetic stress test by a small but consistent margin. The score punishes anything that is fine but not perfect.
Why the conventional stack cannot reach 100
Most small business sites in 2026 are built on one of four stacks, and three of them have a structural ceiling somewhere below 100 on mobile.
WordPress with a page builder like Divi or Elementor is the most common stack and the worst offender. Every page request goes through PHP, which queries a database, assembles the page on the server, then ships the result to the browser. The HTML you receive is bloated with classes the page builder needed during construction but the browser has to parse and ignore. The CSS includes hundreds of utility classes you never use. The JavaScript bundle includes the page builder’s runtime, jQuery, and a small army of plugins each one adding their own scripts. None of this is wrong exactly. It is just expensive on a throttled mobile CPU.
Squarespace and Wix are slightly cleaner versions of the same problem. The host renders the page from a template system, ships a heavy JavaScript bundle for their interactive components, and prevents you from removing anything. You can reach the high 80s on mobile. You cannot reach 100.
Modern JavaScript frameworks like Next.js, Astro, and Remix can reach 100 in theory. In practice, the default configurations ship enough JavaScript to the client that the throttled CPU runs out the clock during hydration. A skilled developer can squeeze a 100 out of these stacks, but it takes the same level of attention as the approach below, just with more moving parts.
The fourth stack is the one that has a clean shot at 100: vanilla HTML, CSS, and JavaScript with no framework. The HTML is a static file the browser fetches directly. There is no PHP runtime, no database query, no server-side assembly. The CSS is exactly what the page needs and nothing else. The JavaScript is event-driven and loaded only when the user actually does something. The browser receives a finished page and renders it.
The reason this approach is rare in 2026 is that frameworks make development faster and the performance cost is invisible during the build phase. You only notice the cost on the first real PageSpeed run, by which point the architecture is locked in.
The actual decisions that produced the score
The site in question is liceclinicsoftexas.com. Five locations in Texas, fully responsive, includes booking integration with a third-party scheduler, an AI chatbot, an interactive game with email capture, schema markup for local business and FAQ, geo-targeted location pages, and a custom 404 page with a canvas animation of lice exploding into amber and teal particles. None of those features are simple. The score is 100 on mobile and 100 on desktop on the homepage, with the four Core Web Vitals reading: First Contentful Paint 0.9 seconds, Largest Contentful Paint 1.1 seconds, Cumulative Layout Shift 0.001, Total Blocking Time 0 milliseconds.
The decisions that produced those numbers, in roughly the order they mattered:
Inline the critical CSS
Anything required to render the above-the-fold viewport is in a style block in the head of the document. The browser parses the HTML, hits the inline styles, and immediately knows how to draw the visible portion of the page. There is no waiting for an external stylesheet to download, parse, and apply. Every external CSS request you eliminate is a round trip you do not have to wait for.
Defer everything that is not critical
Google Analytics fires on the window load event, not on page parse. The Mangomint booking widget is loaded only when a user clicks a booking link. The booking drawer CSS used to be deferred too, but I caught a flash of unstyled drawer on initial load and pulled the defer back, which dropped the score by zero points because the drawer CSS is 1.3 KiB. Tradeoffs are everywhere.
Preload the LCP element with fetch priority
The hero image is the Largest Contentful Paint element on most landing pages. Tell the browser explicitly with a preload hint and fetchpriority=”high” attribute. The browser starts the image download in parallel with the HTML parsing instead of discovering it later. This single change moved my LCP from 2.9 seconds to 1.1 seconds.
Worth noting because I burned myself on this: preloading the wrong element actively hurts the score. I once preloaded the company logo expecting it to help. It dropped the score from 91 to 88 because the logo loaded fast enough on its own that the preload was flagged as unused. The browser does not appreciate hints it cannot use. Preload only the largest above-the-fold image, and confirm with the Lighthouse waterfall that it is genuinely the LCP element.
Self-host nothing, then self-host everything you can
The original WordPress site loaded the hero images directly from its own WordPress upload directory, which was fine while we were building. For the production launch, I downloaded the three hero images, ran them through Squoosh.app at WebP quality 75, dropped them in a local images folder, and updated the source attributes to point to local paths. The savings were 580 KiB of payload over throttled 4G. That alone moved the score from 89 to 93.
Fonts followed a different path. Google Fonts is loaded via the standard async preload pattern, which gets the score but introduces a brief flash of unstyled text on first paint. I have not yet self-hosted the fonts. That is a separate article.
Write less JavaScript
The site has roughly 4 KB of JavaScript across the entire page, all of it event-driven. Click handlers for the booking drawer, the mobile nav toggle, the chatbot trigger, and the canvas animation on the 404 page. That is the entire JavaScript surface area. There is no framework runtime, no state management library, no virtual DOM diffing. Total Blocking Time is 0 ms because there is no JavaScript blocking the main thread during initial render. There is barely any JavaScript at all.
The location pages tell a more honest story
The homepage scores 100. The five location pages score in the high 70s to mid 80s. This is intentional. The location pages prioritize content density, local SEO copy, schema markup, photos of each clinic, hours, phone numbers, and embedded location-specific booking links. Each one carries more weight than the homepage and they pay for it on the score.
The strategic decision was to optimize the homepage as the ad landing page, since paid traffic from Google Ads and Meta routes there. The location pages serve organic search intent. Different jobs, different optimization targets. An honest performance budget allocates differently across pages based on what each page is for. Most agencies optimize the homepage and ship the rest with whatever score the page weight produces. I do something similar but I name it out loud, which counts for something on the discovery call.
What the score actually buys you
A 100 on mobile PageSpeed is not a vanity number. It maps to three real business outcomes.
The first is Google’s organic ranking signal, which uses Core Web Vitals as a tiebreaker among otherwise comparable pages. Passing all three Core Web Vitals (LCP under 2.5 seconds, INP under 200 ms, CLS under 0.1) puts you in Google’s “good” classification, which is the actual signal Google uses. Going from a 75 to a 100 within the “good” classification is incrementally less valuable than getting from “needs improvement” to “good.” But for competitive local search, every advantage compounds.
The second is paid ad efficiency. Google Ads Quality Score factors in landing page experience, and landing page experience leans heavily on speed. A faster landing page costs less per click on the same keyword bid. For a local service business spending one to two thousand dollars a month on paid search, the savings from a 100-scoring landing page versus a 75-scoring competitor’s landing page can run into the hundreds per month. This is the easiest argument to make to a client because it puts a dollar figure on the score.
The third is conversion rate. Faster sites convert better at every stage of the funnel because every additional second of load time is a moment the prospect can decide to leave. The relationship between load time and conversion rate is well documented and consistent across industries. A site that loads in under one second versus a site that loads in three seconds will see meaningful differences in form completion, booking rate, and add-to-cart behavior.
The thing the metric does not measure
Here is the part that took me a while to internalize. Lighthouse measures First Contentful Paint, Largest Contentful Paint, Cumulative Layout Shift, Total Blocking Time, and Speed Index. It does not measure perceived stability after first paint. It does not measure how the page feels in the wrist when you scroll. It does not catch the small visual glitch that happens between the moment text first appears and the moment the custom font loads in. It rewards a strict set of measurements and is silent on the rest.
This means it is possible to ship a 100-scoring site that has noticeable rough edges to a careful viewer. I have done it. The site we are discussing has a brief flash of system-default text before the Google Fonts arrive, which the score rewards as correct behavior because the default fonts render instantly and the swap does not shift layout. A user on a fast connection sees a barely perceptible visual update at maybe 200 milliseconds in. A user on a slow connection sees a longer period of system-default text before the swap. Neither costs you a single point on the score.
This gap between what the metric rewards and what feels polished is the hidden cost of optimizing for the score rather than for the user. Most modern performance guides recommend exactly the pattern that produces this glitch. The score-driven culture of web development has quietly accepted a tradeoff most users notice but no metric measures. I am writing a separate article on this because it deserves its own teardown.
Where the score is worth chasing and where it is not
Not every page needs a 100. Most pages do not need to even try. A 100-scoring homepage that doubles as the ad landing page is high-leverage. A 100-scoring blog article on page 47 of your archive is a waste of your optimization budget.
The framework I use: optimize hard for any page that receives paid traffic. Optimize hard for the homepage. Optimize for the conversion path (services, pricing, contact). For everything else, set a floor of “passes Core Web Vitals” and stop there.
This is not most agencies’ approach. Most agencies either claim every page is optimized (rarely true) or do not optimize anything past the homepage (more common). Naming the budget out loud is a credibility move that sophisticated buyers actually respond to.
The thing you do not want to hear
The reason 100 is rare is that most freelancers and agencies do not actually know how to reach it. The conventional wisdom is correct directionally but misses the specific decisions that produce the number. I have met a lot of developers who can quote the Core Web Vitals thresholds and have never personally shipped a site that hit them across the board on mobile. The gap between knowing the rules and actually executing under throttling is the gap that produces the rarity.
If you want a 100 on mobile, the path is simple but unforgiving. Choose a stack that does not work against you. Inline the critical CSS. Defer the non-critical work until the user asks for it. Preload only the LCP element. Compress your images aggressively. Write less JavaScript. Run the audit, read the waterfall, fix the slowest single thing, and repeat until the number stops moving.
That is the entire method. It is not glamorous. It is not what gets sold in the typical web design package. It is the method anyway.
View the live case study with verifiable PageSpeed receipts, including the Wayback Machine snapshot of the old WordPress version for comparison.