From 1d56622404119e3d1013cd99c8313d4e15f66168 Mon Sep 17 00:00:00 2001 From: omoh5 Date: Tue, 4 Aug 2026 22:00:07 +0000 Subject: [PATCH] fix(frontend): document SSR/hydration guard in theme provider (#1083) --- frontend/src/app/layout.tsx | 13 +++++- frontend/src/context/theme-provider.tsx | 56 +++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index e039ba12..f22db926 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -60,7 +60,18 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - {/* TODO: revisit if i18n is introduced */} + /* + `suppressHydrationWarning` is the companion to next-themes' built-in + blocking pre-paint script (rendered by below). The + server renders without a theme class; that script then reads the + persisted theme from localStorage and adds/removes the theme class + (`light`/`dark`) on before the first paint, so the client DOM + class list can legitimately differ from what the server rendered. This + prop tells React to skip the hydration-difference check for this + element because the divergence is intentional and resolved before paint. + See `theme-provider.tsx` for the full strategy. + */ + ` **without a theme class**; the correct + * class is applied only on the client. Without the guard described below, two + * problems would follow: + * + * 1. **Flash of wrong theme (FOUC)** — the browser would paint with the + * default styles first (no class means Tailwind's `dark:` variants are + * off, i.e. light mode), then swap to the persisted theme once the client + * applies it after hydration. + * 2. **Hydration mismatch warning** — React compares the server-rendered + * `` class list with the client DOM and warns if they differ. + * + * Both are prevented today, without any custom script: + * + * - `next-themes@0.4.x` renders its **own blocking inline `