The Default Is Already Correct
In Next.js 16 every layout and page in the app/ directory is a Server Component by default. That is the right default. Server Components render on the server, send zero JavaScript for their own logic, can talk to databases and secrets directly, and stream HTML to the browser. The moment you add 'use client' higher than necessary, you forfeit those benefits for an entire subtree.
What You Will Learn
- When
'use client'is actually required - The children-slot pattern that keeps Server Components inside Client Components
- How to wrap third-party interactive libraries without poisoning the tree
- Context providers that stay as deep as possible
- A practical decision checklist for every new component
1. The Real Cost of an Unnecessary Client Boundary
Once a file is marked 'use client', every module it imports and every component it renders directly becomes part of the client bundle. That includes heavy libraries you only needed on the server, database helpers that should never ship, and pure presentational components that could have stayed server-only.
The boundary is one-way. Server Components can import Client Components. Client Components cannot import Server Components. The only safe way to interleave them is to pass Server Components as children or as props from a parent Server Component.
2. Decision Tree: Server or Client?
Ask these questions in order:
- Does the component need state, event handlers, or browser APIs (
window,localStorage,useEffect)? → Client Component. - Does it only fetch data, render static markup, or use secrets? → Server Component (leave the default).
- Does a third-party package require client features? → Create a thin Client wrapper; keep the rest of the tree server-side.
Most leaves that need interactivity (buttons, forms, modals, theme toggles) are Client Components. Everything above them should stay Server Components.
3. The Children-Slot Pattern (Production Standard)
This is the pattern official Next.js docs recommend and the one that appears in every well-structured App Router codebase.
Create a Client Component that accepts children:
Then compose from a Server Component page:
Cart never becomes part of the client module graph. Its output is already rendered in the RSC payload and simply slotted into the Client Component.
4. Context Providers Belong Deep in the Tree
React context only works in Client Components. Wrap only the subtree that needs the context, not the entire document.
In the root layout keep the provider around {children} only — never around <html> or <body> if you can avoid it. That leaves static shell pieces free for Next.js to optimise.
5. Third-Party Interactive Libraries
Many packages (carousels, rich text editors, charts) still ship without a 'use client' directive. Importing them directly into a Server Component fails. The fix is a one-line re-export:
You can now safely use <Carousel /> from any Server Component. The rest of the page stays server-rendered.
6. Common Mistakes That Still Appear in Production
- Putting
'use client'on a layout or page just to use one interactive child. - Importing a Prisma client or secret-bearing module into a Client Component.
- Creating a new Client boundary for every small interactive element instead of one shared provider or shell.
- Passing non-serialisable props (functions, class instances, Dates without conversion) from Server to Client.
- Relying on middleware alone for auth while the interactive form itself lives in a Client Component that never re-checks the session.
Summary
Treat 'use client' as a precision tool, not a default. Keep Server Components as high as possible, push Client Components to the leaves, and use the children-slot pattern to compose them. The result is smaller bundles, faster First Contentful Paint, secrets that stay on the server, and an architecture that survives future Next.js releases.
Key Takeaway
Default to Server Components. Add 'use client' only when the component truly needs the browser. Pass Server Components as children into Client shells. That single habit eliminates the majority of App Router performance and security regressions.
Need a production review of your App Router architecture?
I audit Next.js 16 codebases for unnecessary client boundaries, data-access patterns, and security posture. Get in touch if you want a focused pass on your Server/Client split.
