Skip to content

Eliminate flash-of-wrong-theme and fix theme hydration mismatches #7

Closed

Description

@chonilius

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.tsx needs 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 (matchMedia change listener) — verify ThemeContext.tsx's current behavior for all three and fix any that are missing or wrong.
  • Next.js robots.ts/sitemap.ts and 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.tsx for 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.

Activity

  1. added
    very hardVery difficult task, expert-level effort required
    bugSomething isn't working
    performancePerformance/optimization issue
    on Jul 15, 2026
  2. darius-daniel commented on Jul 15, 2026

    @darius-daniel
    Contributor

    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 ThemeContext to correctly support explicit, system, and live OS theme changes without hydration mismatches, add the appropriate color-scheme metadata, and verify the behavior across hard reloads and dashboard routes with tests and visual validation.

  3. grantfox-oss commented on Jul 16, 2026

    @grantfox-oss

    🦊 GrantFox — @darius-daniel has been assigned to this issue as part of the Official Campaign | FWC26 campaign!

    Next steps:

    1. Open a Pull Request referencing this issue (e.g., Closes #7)
    2. Your PR will be reviewed by the MergeFi maintainers

    Good luck! Track your progress on GrantFox.

  4. grantfox-oss commented on Jul 20, 2026

    @grantfox-oss

    🎉 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26bugSomething isn't workingperformancePerformance/optimization issuevery hardVery difficult task, expert-level effort required

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions