Repository navigation
Eliminate flash-of-wrong-theme and fix theme hydration mismatches #7
Copy link
Copy link
Closed
Labels
GrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Campaign: Official Campaign | FWC26bugSomething isn't workingSomething isn't workingperformancePerformance/optimization issuePerformance/optimization issuevery hardVery difficult task, expert-level effort requiredVery difficult task, expert-level effort required
Description
Problem
src/app/layout.tsx presumably wraps the tree in ThemeContext/ThemeProvider (per src/context/ThemeContext.tsx and src/components/ui/ThemeToggle.tsx) for the "dark-mode-first design system." With Next.js App Router and Server Components, a client-side theme context that reads a persisted preference (localStorage, likely) cannot know the user's preference during server rendering, which is the classic setup for a flash-of-wrong-theme (FOWT/FOUC) on every full page load and on every server-rendered route transition — jarring specifically because this is a "dark-mode-first" product where a flash to light (or an unstyled flash) is visually loud.
Why this is hard
- Fixing this properly in Next.js 16 App Router requires a blocking inline script in
<head>(before hydration) that reads the persisted preference and sets a class/attribute on<html>synchronously — but this must be done without violating the CSP you may be simultaneously hardening (see the localStorage/XSS issue in this batch) and without breaking Turbopack's dev-mode HMR overlay theming. ThemeContext.tsxneeds to be audited for whether it currently causes a hydration mismatch warning (React 19 is strict about server/client HTML mismatches) — if the server renders one theme class and the client immediately overwrites it, you'll see console warnings or, worse, layout thrash as Tailwind v4's dark: variants repaint.- Must handle three preference states correctly: explicit user choice (persisted), system preference (
prefers-color-scheme) with no explicit choice, and the interaction between them when the OS-level preference changes while the tab is open (matchMediachange listener) — verifyThemeContext.tsx's current behavior for all three and fix any that are missing or wrong. - Next.js
robots.ts/sitemap.tsand metadata generation run at build/request time server-side and must not depend on theme state, but any color-scheme meta tags (<meta name="color-scheme">) need to be correctly set for native form control/scrollbar theming, which is easy to overlook.
Scope
- Add a synchronous, CSP-compliant inline theme-init script in
src/app/layout.tsx's<head>. - Audit and fix
ThemeContext.tsxfor hydration-mismatch safety and correct three-state handling (explicit/system/live system-change). - Add
<meta name="color-scheme">reflecting the active theme. - Verify no FOWT across a hard reload on
/,/issues, and a dashboard route, in both explicit dark, explicit light, and system-follows-OS modes.
Acceptance criteria
- Hard-reloading any route with an explicit theme preference set shows zero flash of the wrong theme, verified visually/via a screenshot diff or frame-by-frame check.
- No React hydration mismatch warnings related to theme in the browser console.
- Toggling OS-level color scheme while on a "system" preference updates the app live without a manual refresh.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
GrantFox OSSIssue tracked in GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Campaign: Official Campaign | FWC26bugSomething isn't workingSomething isn't workingperformancePerformance/optimization issuePerformance/optimization issuevery hardVery difficult task, expert-level effort requiredVery difficult task, expert-level effort required
Activity
darius-daniel commentedon Jul 15, 2026
I'd like to work on this issue.
I'll implement a hydration-safe theme initialization flow that eliminates flash of the wrong theme by applying the user's preferred theme before hydration. I'll audit and update the
ThemeContextto correctly support explicit, system, and live OS theme changes without hydration mismatches, add the appropriatecolor-schememetadata, and verify the behavior across hard reloads and dashboard routes with tests and visual validation.grantfox-oss commentedon Jul 16, 2026
🦊 GrantFox — @darius-daniel has been assigned to this issue as part of the Official Campaign | FWC26 campaign!
Next steps:
Closes #7)Good luck! Track your progress on GrantFox.
grantfox-oss commentedon Jul 20, 2026
🎉 This issue has been marked as completed on GrantFox as part of the Official Campaign | FWC26 campaign!
@darius-daniel's PR #64 was approved and merged by @chonilius.
🏆 @darius-daniel: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (379 total points). Track your full progress on GrantFox.
👏 Great work, @darius-daniel! Keep contributing to MergeFi.