Skip to content

Rule · Lint

Browser global (window, document, navigator, localStorage) at module scope or during render

lint/browser-global-in-rendererrorvoid lintupdated

Why it matters

Client components are still rendered on the server. Touching browser globals at import time or in the render body crashes SSR (window is not defined) or renders different markup on server and client (hydration mismatch, e.g. ⌘ vs Ctrl labels from navigator.platform).

How to fix it

Read browser APIs inside useEffect, event handlers, or useSyncExternalStore with a server snapshot. For values needed in the first paint, render a neutral default and update after mount.

Example

tsx
const isMac = useSyncExternalStore(
  () => () => {},
  () => /Mac/.test(navigator.platform),
  () => false, // server snapshot
)

References

void lint reports 67 rules in this category. Static source checks with no browser: Tailwind v4 silent failures, Next.js 16 API traps, React render-body bugs, accessibility markup, SEO files and motion hygiene.