When you need the browser
State, events, refs, browser APIs, third-party UI libraries (Framer Motion, headless UI, React Hook Form). For these, declare the file a Client Component with 'use client' at the very top.
The directive is contagious
'use client' applies to the file and everything it imports. Anything in the import graph below the directive is part of the client bundle. Place it as low in the tree as possible.
The decision table
| Need | Where |
|---|---|
useState / useEffect / useRef | Client |
Event handlers (onClick, onChange, onSubmit) | Client |
window, document, localStorage | Client |
| Third-party hook-based libraries | Client |
| Plain rendering of data | Server |
| Data fetching / DB queries | Server |
| Reading secrets | Server |
| Heavy data shaping | Server |
Review the import graph under every 'use client' file. A tiny interactive toggle should not pull a charting library, server-independent content, and layout code into the browser. Let a server parent provide initial values and rendered children to a narrow interactive leaf. When moving a client boundary, compare the imports newly pulled into the bundle as well as behavior. If one small interaction carries an entire heavy library, the boundary is too high. Client Component is not synonymous with client-only HTML. Next.js can prerender it for the initial response; the distinction is that its code also ships for hydration. Keep initial rendering location separate from ongoing execution responsibility. Place the directive first at page level and then at the smallest event-owning leaf. Compare the analyzer reports and disable JavaScript to see what remains. The interaction should survive when enabled without making unrelated content part of the client graph.