I kept hitting the same three problems deploying Next.js App Router
sites as a static export on Cloudflare Pages across multiple client
projects. None of them throw a loud error — they just quietly cost
PageSpeed points until you know to look for them.
Here's the site scoring 100/100 across the board, verified today:
1. next/image breaks silently in static export
The default Image Optimization API calls a live server endpoint to
resize and re-encode images on demand. output: 'export' produces no
server — Cloudflare Pages serves static files only. The component
doesn't always throw; it can silently serve unoptimized full-size
originals instead.
Fix:
// next.config.js
images: {
unoptimized: true,
},
You lose automatic resizing, so pre-export images as WebP/AVIF before
they enter the project rather than shipping camera-resolution files.
2. A manual Google Fonts link tag blocks first paint
This pattern is everywhere:
<link href="https://fonts.googleapis.com/css2?family=Inter" rel="stylesheet">
It forces a round trip to a third-party domain before any text can
render. On the mobile connections PageSpeed simulates, that's a direct
hit to Largest Contentful Paint.
Fix — use next/font, which downloads the font at build time and
self-hosts it from your own domain:
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"], display: "swap" });
Zero runtime request to Google's servers.
3. Cloudflare Pages doesn't cache aggressively by default
You have to declare it yourself in a public/_headers file:
/_next/static/*
Cache-Control: public, max-age=31536000, immutable
The result
Same site, same content, three small changes — Performance,
Accessibility, Best Practices, and SEO all at 100, desktop and mobile.
I packaged this as a Claude Code/Cursor skill so I don't have to
re-solve it by hand on every new client project — free diagnostic
version is on GitHub, full pack with ready-made
config templates is here.
Happy to answer questions about static export edge cases in the
comments.

Top comments (0)