Skip to content

fix(frontend): document SSR/hydration guard in theme provider (#1083) - #1169

Merged
ogazboiz merged 1 commit into
LabsCrypt:mainfrom
omoh5:fix/1083-theme-ssr-hydration-docs
Aug 6, 2026
Merged

fix(frontend): document SSR/hydration guard in theme provider (#1083)#1169
ogazboiz merged 1 commit into
LabsCrypt:mainfrom
omoh5:fix/1083-theme-ssr-hydration-docs

Conversation

@omoh5

@omoh5 omoh5 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Description

Closes #1083

This PR resolves the open SSR/hydration concern for the theme provider by documenting the existing guard strategy in code comments rather than adding a redundant hand-rolled inline script.

Context: A previous attempt (PR #1158) added a custom blocking inline <script> to layout.tsx. A maintainer closed it with the guidance that main already ships both halves of the protection:

  1. suppressHydrationWarning on <html> in frontend/src/app/layout.tsx — tells React to skip the hydration diff check for the class attribute, since the pre-paint script intentionally mutates it.
  2. next-themes@0.4.6's built-in blocking pre-paint script (the library's core feature) — it reads localStorage["flowfi-theme"], resolves "system" via matchMedia("(prefers-color-scheme: dark)"), and adds/removes the dark class on document.documentElement before the first paint.

A second hand-rolled script would race the built-in one, so this PR deliberately does not add one. Instead it documents the strategy so the intent is preserved for future contributors (acceptance criterion: "Document the approach in a code comment").

Type of Change

  • 📚 Documentation update (comment-only change that resolves a bug-flagged issue)
  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 🔧 Refactoring (no functional changes)
  • ⚡ Performance improvement
  • 🧪 Test addition or update

Related Issues

Closes #1083

Changes Made

  • frontend/src/context/theme-provider.tsx — Added a JSDoc block documenting the full SSR/hydration strategy:
    • How next-themes' built-in pre-paint script prevents flash-of-wrong-theme (FOUC).
    • How suppressHydrationWarning on <html> prevents the hydration mismatch warning.
    • Why we do not hand-roll a second inline script (it would race the library's own script and create two sources of truth).
    • What each ThemeProvider prop does (attribute, defaultTheme, enableSystem, storageKey, disableTransitionOnChange).
  • frontend/src/app/layout.tsx — Replaced the stale TODO comment with an explanation of why suppressHydrationWarning is on <html> and how it pairs with the next-themes pre-paint script rendered by <ThemeProvider>.

No functional change — the current behavior already satisfies acceptance criteria 1–2 (see Testing for evidence).

Testing

  • npm run lint --workspace=frontend0 errors (5 pre-existing warnings in unrelated files)
  • npm run build --workspace=frontend (Next.js 16.2.9, Turbopack) — succeeds
  • npm test --workspace=frontend206 tests passed (24 files)
  • Inspected the prerendered SSR output (.next/server/app/index.html) to confirm current behavior:
    • suppressHydrationWarning:true is serialized on the <html> element in the React tree (honored at hydration).
    • The next-themes pre-paint script is present in the HTML: ...("class","flowfi-theme","dark",null,["light","dark",...]) — the library's inline script reads localStorage["flowfi-theme"] (default "dark") and applies the class before paint.
    • ThemeProvider props are serialized consistently (attribute="class", defaultTheme="dark", enableSystem=true, storageKey="flowfi-theme", disableTransitionOnChange).

Test Coverage

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed (see Test Steps)

Test Steps

Manual repro for reviewers:

  1. cd frontend && npm run dev
  2. In DevTools, run localStorage.setItem('flowfi-theme', 'light') and hard-reload — there is no dark→light flash on load (theme is correct before first paint).
  3. With DevTools console open, reload — no Hydration mismatch warnings.
  4. Toggle the theme via the navbar control — the preference persists across reloads with no flash.

Breaking Changes

None — comment-only change.

Migration Guide: N/A

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • Updated Postman/Hoppscotch API collections if routes changed (N/A)
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works (N/A — comment-only change; behavior verified via build output + existing suite)
  • New and existing unit tests pass locally with my changes
  • I have checked for breaking changes and documented them if applicable

Additional Notes

@omoh5
omoh5 force-pushed the fix/1083-theme-ssr-hydration-docs branch from 1c4e2bf to 1d56622 Compare August 4, 2026 22:06
@ogazboiz
ogazboiz merged commit ae0f3c3 into LabsCrypt:main Aug 6, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Frontend] theme-provider.tsx does not guard against SSR/hydration mismatch when localStorage theme differs from server-rendered class

2 participants