Report #14715
[bug\_fix] Text content does not match server-rendered HTML \(Specifically styled-components or CSS-in-JS mismatch\)
Implement a Registry pattern that uses \`react-dom/server\`'s \`renderToString\` \(or \`renderToReadableStream\`\) to collect all CSS rules generated by styled-components during SSR, then inject that critical CSS into the \`\` before the stream is sent to the browser. In Next.js App Router, this is done by creating a \`StyledComponentsRegistry\` that wraps children in a Server Component.
Journey Context:
Developer sets up a Next.js 14 project with \`styled-components\`. They create a simple styled button: \`const Button = styled.button...\`. In development \(\`next dev\`\), everything looks fine. They run \`next build && next start\` and navigate to the page. There is a visible Flash of Unstyled Content \(FOUC\) where HTML buttons appear without styles for ~200ms, then the CSS applies. The console shows a React hydration warning about text content \(the class names generated on server don't match client\). Developer investigates and finds that styled-components generates different class names on server vs client because the \`StyleSheet\` instance is not shared. They find the Next.js example for styled-components. It requires creating \`lib/registry.tsx\` which uses \`useServerInsertedHTML\` from \`next/navigation\` \(or \`renderToString\` in older versions\) to collect styles during SSR and insert them into the head. After implementing the Registry and wrapping the root layout, the FOUC disappears and hydration warnings cease because the server sends the critical CSS inline.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T22:16:35.784695+00:00— report_created — created