server-components-design
Server Components Design
Concept of the skill
React Server Components (RSC) are a kind of component that runs only on the server, never ships to the browser as JavaScript, can be async, and can reach directly into server-side resources — databases, the file system, secrets, server-only environment variables. Their rendered output is serialized into a wire format (the RSC payload) and reconstituted into the client tree without any intermediating JSON API. Server and Client Components compose in a single tree with strictly one-way directionality: a Server Component may render (or import) a Client Component, but a Client Component may never import a Server Component — though it can receive one as a children/slot prop that its Server-Component parent already rendered. The two capability surfaces are disjoint: Server Components cannot use hooks, state, effects, event handlers, or browser APIs; Client Components cannot read databases, secrets, or server-only modules directly. The discipline this skill teaches is where to draw the boundary in the tree: push as much as possible to the server side and place 'use client' at the thinnest interactive leaf, so the surrounding layout and data reads stay server-only (zero bundle, no hydration, data baked into the payload). Three concerns run through every RSC review — execution locality (does this need server-only or browser-only resources?), data security (every prop crossing to a Client Component is serialized and shipped to the browser, so private fields must be filtered into minimal DTOs before they cross), and reveal/freshness (which reads block, which stream behind Suspense, and which are cached). Next.js App Router is the canonical implementation, but the primitive is the React RFC, so the discipline is framework-agnostic.
Coverage
The discipline of designing React Server Components (RSC): what an RSC is for, what it can do that Client Components cannot, what it cannot do, how the server/client boundary shapes the component graph and the data-flow graph, how to keep private data from leaking across that boundary (Data Access Layer, Data Transfer Objects, the server-only package, and the taint APIs), how to fetch data without waterfalls (request memoization, parallel reads, the preload pattern), how RSC composes with Suspense to stream content from the server in chunks, how a framework's caching layer (Next.js 'use cache' / Partial Prerendering) reuses a Server Component's output, why Server Components remove the need for a separate API layer for read-path data, and the recurring design questions a reviewer asks of any RSC tree. Next.js App Router is the canonical implementation referenced throughout; the discipline applies to any RSC implementation (Remix RSC, Waku, Parcel RSC, hand-rolled RSC servers) since the underlying primitive is the React RFC, not a single framework.
RSC design also covers the data-freshness axis that modern App Router projects must make explicit: whether a Server Component read is uncached, request-cached, framework-cached, tagged for revalidation, or intentionally streamed behind Suspense. In current Next.js, Cache Components and the 'use cache' directive make caching a component/data design decision, not an incidental fetch option. This skill owns the RSC read-path placement question; server-actions-design owns the write-path mutation and revalidation trigger.
Philosophy of the skill
The original React component model collapsed two roles into one function: produce HTML for the initial render, and produce a virtual DOM update in response to client-side state. Server-Side Rendering pre-React-18 tried to make that single function run twice — once on the server to produce HTML, once on the client to produce the interactive tree — and pay for it with hydration: a full re-execution on the client to bind event handlers and reconstruct state.
Hydration has two costs the industry tolerated for a decade: every component must ship to the client (bundle size grows with the page), and every component re-runs on the client (CPU cost grows with the page). React Server Components separate the two roles into different kinds of component. A Server Component runs once, on the server, and produces a serialized output that the client uses directly — no shipping, no re-execution. A Client Component is what we used to call "a component": ships to the browser, runs on render and on every interaction.
The discipline of RSC design is to push as much of the tree as possible to the server side of the boundary, and to draw the line as close to the actual interactive leaves as possible. A button needs useState; the dashboard surrounding the button does not. A chart that responds to filter clicks is interactive; the page header above it is not. The win is real: bundle size shrinks toward "only the interactive parts," and the server has direct access to databases, file systems, and secrets without an intermediating API layer.