Server & Client Boundaries

This example demonstrates how server and client components nest together in React Server Components. Each colored box shows its environment and whether it can use hooks or access server-only APIs.

SERVERPage (Server Component)

Rendered on the server at 2026-03-01T21:46:59.404Z. This component can access Node.js APIs, read from databases, and use async/await directly.

CLIENTInteractive Panel

This is a client component. It uses useState to manage expand/collapse and highlight state. Its children are server-rendered and passed in as props.

Children (server-rendered, passed via props)
SERVERServerInfo (Server Component)

This server component is passed as children into the client panel above. It renders on the server even though its parent is a client component — this is the “donut pattern”.

nodeVersion:v22.22.0
platform:linux
pid:4
uptime:216s
renderedAt:2026-03-01T21:46:59.405Z
This data comes from process.* — proof this component ran on the server, not in the browser.
CLIENTToggleDetails (Client Component)
SERVERStatic Server Content

This server component sits alongside the client panel. It has no interactivity — just static content rendered once on the server.

Key Takeaways

  • Server components are the default — no special suffix needed
  • Client components use the .client.tsx naming convention
  • The “donut pattern”: pass server content as children into a client component
  • Client boundaries don't “infect” their children — server components can appear inside client components via props
  • You cannot import a server component directly from a client component — only pass it as a prop