Description
Theme pages are currently emitting hydration warnings because the theme state differs between server render and client render. This is caused by an incomplete next-themes configuration in theme-provider.tsx, which allows the client to rehydrate with a different theme value than the server initially rendered.
This issue should stabilize theme initialization so the app renders the same theme on the server and client, and avoid a visible flash of theme change during hydration.
Tasks
- Update theme-provider.tsx
- Configure
next-themes with:
defaultTheme
enableSystem
attribute="class"
disableTransitionOnChange or equivalent transition suppression
- Ensure the provider uses a consistent initial theme value for both server and client
- Apply the theme preference as early as possible on first client render
- Verify the theme provider is wrapped around all theme pages and not rendered conditionally
- If needed, add a safe mount guard or hydration-safe rendering pattern to keep theme DOM stable until the client theme is resolved
Implementation details
The provider should stop relying on implicit defaults and explicitly define the initial theme strategy. For example:
'use client'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import type { ThemeProviderProps } from 'next-themes/dist/types'
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return (
<NextThemesProvider
{...props}
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</NextThemesProvider>
)
}
Key behavior to lock in
attribute="class" ensures theme is controlled via CSS class rather than inline styles
defaultTheme defines a stable initial server-side theme
enableSystem lets the browser preference apply consistently
disableTransitionOnChange prevents a flash when the theme switches after hydration
- If
defaultTheme="system" is used, the provider must still avoid theme mismatch flash by applying the preference in a hydration-safe way
Acceptance criteria
next-themes is explicitly configured with defaultTheme and enableSystem
- Theme rendering is stable across server and client
- No hydration warnings appear in the browser console on theme pages
- The visible theme does not flash or jump during first render
- Theme pages render the same initial theme class before and after hydration
- The provider is implemented in theme-provider.tsx with a consistent theme initialization strategy
Why this matters
- Hydration warnings indicate a mismatch between server-generated HTML and client-side React state
- Theme mismatch can cause a visible flash and degrade perceived quality
- A stable theme provider improves user experience and prevents inconsistent appearance across renders
Description
Theme pages are currently emitting hydration warnings because the theme state differs between server render and client render. This is caused by an incomplete
next-themesconfiguration in theme-provider.tsx, which allows the client to rehydrate with a different theme value than the server initially rendered.This issue should stabilize theme initialization so the app renders the same theme on the server and client, and avoid a visible flash of theme change during hydration.
Tasks
next-themeswith:defaultThemeenableSystemattribute="class"disableTransitionOnChangeor equivalent transition suppressionImplementation details
The provider should stop relying on implicit defaults and explicitly define the initial theme strategy. For example:
Key behavior to lock in
attribute="class"ensures theme is controlled via CSS class rather than inline stylesdefaultThemedefines a stable initial server-side themeenableSystemlets the browser preference apply consistentlydisableTransitionOnChangeprevents a flash when the theme switches after hydrationdefaultTheme="system"is used, the provider must still avoid theme mismatch flash by applying the preference in a hydration-safe wayAcceptance criteria
next-themesis explicitly configured withdefaultThemeandenableSystemWhy this matters