Two different jobs on the same page
Picture an article page. Its title, date and paragraphs are readable before the visitor does anything. The theme button beside it needs to respond to a click, remember a preference and update the screen. They share a page but need different tools. Server and Client Components in the Next.js App Router let us design these jobs together.
Pages and layouts are Server Components by default. The code in these components prepares the content without being shipped to the browser. Building a list of articles may not need a separate data-processing layer on the visitor’s device. The point is to put work in a suitable place, rather than turn every page into a complicated server application.
Draw a small boundary around interaction
A component that needs React state, click handlers or browser APIs uses the use client directive at the top of its file. A theme button is a good example. Keep it separate rather than moving the whole article inside that boundary. The boundary also brings directly imported modules into the client side, so the file’s imports matter.
This does not mean that everything displayed beneath a Client Component automatically becomes client code. Content prepared on the server can be passed into an interactive wrapper through a prop such as children. Distinguishing the code a file imports from the content it contains on screen helps avoid making the boundary unnecessarily large.
A Client Component does not run only in the browser
On a direct visit, Next.js can produce HTML for Client Components ahead of time too. React in the browser then attaches interaction to that HTML, a step called hydration. Adding use client therefore does not automatically make window or localStorage safe to use during the component’s initial render. Account for the code being evaluated on the server as well.
Our theme button could read the browser preference in an effect. You also need to consider the difference between the initial paint and the later view: does the page briefly show the wrong theme? Does the initial HTML match the browser’s first output? Trying these questions with a small button teaches more than memorising the terminology.
Does Server mean a server on every request?
No. With a static export, Server Components run during the build. The generated HTML and other files can be served by static hosting without a running Next.js server. That is how the articles on this site are prepared. Seeing a Server Component does not mean the page is regenerated on every visit.
Reading visitor-specific cookies or processing work on the server during a request needs a different deployment model. A static export does not add an API server to your application. Ask a similar question when designing a contact form: will it open an email draft, or actually send data to a service? The interface might look similar, while the infrastructure requirements differ.
Check what you send to the browser
Prefixing an environment variable with NEXT_PUBLIC_ allows its value to be included in JavaScript sent to the browser. Do not use that prefix for secret credentials. Keeping a variable in an .env file alone does not make it private; its use matters too.
Passing information read on the server into a Client Component as a prop can send it to the browser. Printing a secret into page content also makes it visible, even if the code runs on the server. Our article page only needs the title, date and body. Selecting the fields the interface needs keeps both this boundary and the code understandable.
- Think about readable content and interactive behaviour separately.
- Start the use client boundary at the component that needs it.
- Try both direct page visits and navigation between pages.
- Choose a deployment model alongside the server work you need.
Sources and further reading
Want to dig a little deeper? Here are the official docs behind this article.
