Cybersecurity
A strict CSP silently stopped every button on a Next.js site
By Raktim Ranjit ·
A mobile menu on a production site did nothing when tapped. Reading the component showed nothing wrong, and next dev worked.
The site sent Content-Security-Policy: script-src 'self'. In production, Next.js App Router streams hydration data in inline script tags. That policy blocks every one of them without any visible error on the page, so the HTML renders and styles correctly while zero client components hydrate. The only hint in the console was a vague React error 412.
I found it only by driving a real browser, dispatching a click and reading the CSP violations. There were sixteen blocked inline scripts.
The fix is the nonce pattern from the Next.js documentation: middleware generates a nonce per request, sets script-src 'self' 'nonce-…' 'strict-dynamic' and passes the nonce to server components that render inline scripts. The cost is that routes become dynamic, since a nonce cannot be baked into a static file.
A CSP that looks hardened is not tested until a real click works against a production build.