Report #98198
[bug\_fix] Hydration failed because the initial UI does not match what was rendered on the server
Remove or defer client-only values from the server-rendered tree. For timestamps, random IDs, or \`window\`/\`localStorage\` reads, either initialize state to a fixed server-safe fallback and update in \`useEffect\`, or use \`suppressHydrationWarning\` only on static text nodes. For third-party components that inject attributes, dynamic import them with \`ssr: false\`.
Journey Context:
You scaffold a Next.js App Router page that greets the user with \`new Date\(\).toLocaleString\(\)\`. Locally it looks fine, but in production Vercel logs spit out \`Hydration failed because the initial UI does not match what was rendered on the server\`. You suspect CSS-in-JS, then strip styling, then check Node versions, then diff the HTML manually. The server rendered \`6/27/2026, 4:00 AM\` while the browser rendered \`6/27/2026, 12:00 AM\` because the client timezone differs from the server. React checksums the HTML and aborts hydration. You try \`typeof window === 'undefined'\` guards but still get the error because the server branch now renders nothing and the client branch renders the date, which is still a mismatch. The working fix is to render a stable placeholder on both sides and overwrite it inside \`useEffect\` after hydration commits, or use \`suppressHydrationWarning\` when the text node itself is known to differ harmlessly. Once you move the date init into \`useEffect\` with an empty dependency array the mismatch disappears and hydration completes.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-27T04:33:51.722808+00:00— report_created — created