Next.js
React
Server Components
Arquitetura
Desenvolvimento Web

Next.js App Router: The Guide to Thinking Server by Default

App Router reverses the rule: server by default, client by exception. See what this changes for your team.

Next.js App Router: The Guide to Thinking Server by Default

When Next.js launched the App Router, it did something that seems technical but is, in essence, a mentality decision: it reversed the pattern. Before, every component was client-owned until you said otherwise. Now, every component is server-side until you check that it needs to be client-side.

This inversion is small in syntax and huge in practice. It changes the question the team asks each component. Instead of assuming that everything runs in the browser, you justify why something would need to run there.

For those coming from traditional React, the App Router is not just a new folder with a different router. It's an invitation to rethink where each piece of the application should live. And this invitation tends to disorient before it makes sense.

The pattern has reversed

In App Router, layouts and pages are server components by default. This means that, when you create a new page, it starts running on the server, without you doing anything. Its code does not go to the browser, and the data search can happen right there, before the response comes out.

The immediate consequence is that a lot of things that you would push to the client now naturally stay on the server. The product list, the article content, the header with user data, all of this is rendered before arriving, with no JavaScript cost on the device.

When you need interactivity, you mark the component with the "use client" directive. From that point on, that component and what it renders start to run in the browser, with state and events. It is an explicit boundary, not an accident.

The healthy side effect is that the customer becomes a conscious exception. You don't fall into it by inertia, you choose when to enter. If this still sounds abstract, it's worth reviewing what React Server Components](/post/o-que-sao-react-server-components) are before moving on.

When the component must be server

The right question is about the nature of the work. If the component only searches and displays information, it has everything to be a server. Listing pages, blog content, order details, dashboards that only show numbers: none of this needs the browser to exist.

Server components shine at fetching data. You consult the bank directly, call internal services with the low latency of those within the infrastructure and create the ready result. You don't need an intermediate API route just for the browser to be able to request the data, because the component is already on the right side.

There is also the gain of keeping weight off the client. Heavy formatting libraries, markdown processing, date manipulation: if this runs on the server, it never enters the package that the user downloads. The bundle shrinks, and the user's device thanks you.

The mental rule that works is this: start by taking over the server. Only move to the customer when there is a concrete need for interaction. Resisting the urge to brand everything as a customer is half the battle.

When the component needs to be client-side

Not everything fits on the server, and trying to force this leads to frustration. There is a clear set of situations that require customers, and recognizing them quickly avoids wasting time.

The first is the state that changes on the screen. A counter, a selected tab, a menu that opens and closes: anything that needs to remember something between interactions lives in the client. The second is user event. Clicking, typing, dragging, any direct manipulation happens in the browser, because that's where the user is.

The third is the use of browser resources. Access to local storage, geolocation, reading window size, anything that only exists in the browser environment requires the component to be client-side. There is no way to run this on the server, simply because the server has no window or mouse.

The detail that unlocks the team's mind is understanding that this is not all or nothing. You can have a server page that renders a small client component just for the interactive button. The rest of the page remains lightweight and rendered on the server. Interactivity is isolated where it really matters, instead of contaminating the entire page.

Data search changes location

In the old model, fetching data was a well-known ritual: the component assembled, triggered an effect, called an API, dealt with loading and error states, and updated the state when the response came back. It worked, but it was verbose and full of pitfalls.

With server components, data fetching becomes straightforward again. You fetch the data during rendering on the server, wait for the result right there and return the ready-made interface. Add a lot of the dance of loading states to the client, because the data already arrives with the page.

This simplifies the code and improves the experience at the same time, which is rare. The user receives content already filled in, without that sequence of empty screens flashing while each part loads. And when you need progressive loading, the framework offers streaming to deliver chunks as they are ready, a subject worth delving into caching and streaming in Next.js.

Data mutation follows similar logic. Instead of putting together a complete API for each form, you can use Server Actions, functions that run on the server and are called directly from the interface. This closes the cycle: reading and writing close to the source, without layers that existed just to serve the browser.

The change in mentality that the team faces

The hard part about App Router isn't the syntax. It's unlearning the reflex that everything runs in the browser. Teams experienced in React tend to mark components as client out of habit, because that's how they learned, and then they lose a lot of the gain.

The classic symptom is the "use client" at the top of almost every file. When this happens, the application returns to being a SPA in disguise, with the weight of before and the new complexity on top. The team needs to internalize that each customer appointment is a decision to justify, not a pattern to copy.

There is also a mental adjustment about where the code executes. Thinking that part of the tree runs on the server and part on the browser requires care about what each side can do. Trying to use a browser feature in a server component generates errors, and these initial stumbles are a normal part of learning.

Once the penny drops, the model becomes intuitive. The question does this need interaction become automatic, and the team starts designing lightweight interfaces by default. But getting there requires technical leadership willing to patiently review code and correct old reflexes.

If you are considering adopting the App Router in your team, treat the learning curve as part of the project, not as a detail. Allow time for the team to make mistakes, review and adjust intuition. To place this choice within a larger architectural decision, move on to the server-first movement as an architectural decision.

Also read