Server and Client Components
The server-client boundary decides where code executes, what JavaScript ships, and which values are allowed to cross into the browser.
Start on the server
Pages and layouts are Server Components by default. They can read from a database, call private services, use server-only environment variables, and render without shipping their component implementation as normal browser JavaScript.
That makes Server Components a good home for work the browser does not need to own.
'use client' is a boundary, not a decoration
The directive marks an entry point into the client module graph. Imports below that boundary may become part of the client bundle. Putting it on a large page because one button needs onClick can therefore move much more code to the browser than intended.
Extract the interactive part instead. Let the page stay on the server and give the browser the smallest useful client component.
// app/products/page.tsx
import { AddToCart } from './add-to-cart'
export default async function Page() {
const product = await getProduct()
return (
<main>
<ProductDetails product={product} />
<AddToCart productId={product.id} />
</main>
)
}Use the client when the browser owns the behaviour
- Local state with useState or useReducer.
- Event handlers such as onClick and onChange.
- Effects.
- DOM and browser APIs such as localStorage, Canvas, navigator, ResizeObserver, and media APIs.
- Client-side context providers.
- Custom hooks that depend on client-only React APIs.
Crossing the boundary changes what you can pass
Data passed from a Server Component into a Client Component crosses a serialization boundary. Prefer plain data supported by React's server-client protocol.
Do not try to pass database clients, secret-bearing service objects, arbitrary class instances, or browser-incompatible objects across that line.
A client shell can still receive server-rendered content
A Client Component can accept server-rendered content through props such as children. That pattern is useful when the wrapper needs interaction but the content inside it does not.
Think in boundaries rather than whole pages. A small client island can sit inside a much larger server-rendered tree.
Can you explain “Server and Client Components” without reaching for the API reference?
Describe the main trade-off, one failure mode, and the decision you would make in a real project.