- Published on
Next.js: the React framework for production applications
- Blog

- Henrico Piubello
- Henrico Piubello
- IT Specialist - Grupo Voitto
IT Specialist - Grupo Voitto
- What is Next.js and why does it dominate the React ecosystem?
- How does the App Router work and what changes with Server Components?
- What are the rendering strategies and when should you use each?
- Which Next.js features save the most work?
- When is Next.js NOT the right choice?
- How do you start a Next.js project the right way?
Next.js is the framework that turns React into a complete application: routing, server rendering, caching, asset optimization and a backend in the same project. It exists because React solves the interface and leaves everything else to you.
What is Next.js and why does it dominate the React ecosystem?
Next.js is a web application framework maintained by Vercel, launched in 2016. Its proposal is to offer ready-made decisions for the questions every React project must answer and the library does not: how URLs become screens, where HTML is generated, what gets cached, how code is split and where the application talks to the database.
Adoption came from a concrete problem. Single-page applications (SPAs) deliver an almost empty HTML document plus a JavaScript bundle that builds the screen. That means slower first render, dependence on script execution for content to appear and a disadvantage in indexing — three problems that hurt precisely the sites whose traffic comes from organic search.
Next.js inverts the pattern: HTML comes ready from the server or the build, and JavaScript arrives afterward to add interactivity. The current stable version, 16.3, released in August 2026, followed that line with a focus on build performance and instant navigation between routes.
Practical example: a blog built as an SPA delivers a <div id="root"></div> to the crawler and hopes it executes the script. The same blog in Next.js delivers the whole article as HTML in the first response — which is the scenario where semantic HTML structure actually scores points.
How does the App Router work and what changes with Server Components?
The App Router, the default since version 13, organizes the application by folders inside app/. Each folder is a URL segment, and files with reserved names define the behavior of that segment:
page.tsx— the interface reachable at that route.layout.tsx— a shared wrapper that does not remount when navigating between children.loading.tsx— the interface shown while content loads, automatically enabling streaming.error.tsx— the error boundary for that segment.route.ts— an API endpoint in the same tree.
The deepest conceptual change is React Server Components: by default, every component runs on the server and never enters the browser bundle. You query the database directly in the component, use secrets without exposing them and send only the rendered result.
import { db } from '@/lib/db';
import Buy from './Buy'; // this one has 'use client'
export default async function Product({ params }: { params: { slug: string } }) {
// runs on the server: none of this goes to the browser
const product = await db.product.findUnique({ where: { slug: params.slug } });
if (!product) return <p>Product not found.</p>;
return (
<article>
<h1>{product.name}</h1>
<p>{product.description}</p>
<Buy id={product.id} price={product.price} />
</article>
);
}
The practical rule for deciding: everything that only reads and displays stays on the server; only what needs state, events or browser APIs goes to the client. Marking a component with 'use client' does not make it client-only — it is still pre-rendered on the server, but its code is now shipped to the browser.
Practical example: a product page with ten components usually has two interactive ones (buy button, gallery). Keeping the other eight on the server drops the route's JavaScript bundle substantially — and the effect shows up directly in the interaction time measured by Core Web Vitals.
What are the rendering strategies and when should you use each?
Per-route granularity is the framework's main technical gain. You do not pick one mode for the whole site; you pick per page:
| Strategy | When HTML is generated | Best for | Cost |
|---|---|---|---|
| Static (SSG) | At build time | Content that rarely changes: blog, docs, landing pages | Longer builds |
| Incremental (ISR) | At build, revalidated afterward | Large catalogs, editorial content | Slightly stale content |
| Dynamic (SSR) | On every request | Per-user data, real-time pricing | A server hit per visit |
| Client (CSR) | In the browser | Authenticated dashboards, editors | No SEO gain |
| Streaming | In parts, as they become ready | Pages with one slow section | Layout complexity |
The decision starts from two questions: is the content the same for everyone? and how quickly must it reflect changes? Same for everyone and tolerant of minutes of delay: static or incremental. Different per user or sensitive to the second: dynamic.
Streaming deserves attention because it solves a specific problem: when part of the page depends on a slow query, you do not need to hold the whole page. What is ready is sent, and the rest arrives afterward, with <Suspense> marking the boundary.
Practical example: on a product page, the spec sheet and price are static with ten-minute revalidation; the "recommended for you" block is dynamic and arrives via streaming. The user sees the product immediately and the recommendations appear half a second later — instead of waiting for everything.
Which Next.js features save the most work?
Five deliver gains disproportionate to the effort of adopting them:
next/image. Resizes, converts to modern formats, applies lazy loading and reserves space to avoid layout shift. It is the highest-impact Core Web Vitals optimization for the lowest effort.next/font. Downloads and serves fonts from your own domain at build time, removes the third-party request and eliminates the flash of unstyled text.- Route Handlers. API endpoints in the same route tree, with access to standard web
RequestandResponse— no separate backend needed for simple cases. - Server Actions. Async functions that run on the server and can be called directly from a form, without writing an endpoint or a manual
fetch. - The metadata API. Title, description, Open Graph, canonical and language alternates declared per route, with support for dynamic generation — which solves, in a typed way, much of technical SEO work.
Practical example: swapping <img> for next/image in a listing with 30 thumbnails usually cuts page weight by more than 60% and eliminates layout shift — with no architectural change.
When is Next.js NOT the right choice?
Four scenarios where the framework charges more than it delivers:
- Fully authenticated applications. An admin dashboard behind a login has no SEO to gain and rarely needs server rendering. Vite with React Router is simpler, compiles faster and hosts anywhere as static files.
- Pure content sites with no interactivity. For documentation or a company site, generators like Astro or Hugo deliver less JavaScript and faster builds.
- Teams without server-client model experience. The App Router requires understanding where each component executes. Without that clarity, the common outcome is
'use client'at the top of everything — which cancels the benefit and keeps the complexity. - Restricted hosting requirements. Outside Vercel, features like on-demand revalidation, middleware and incremental caching require extra configuration. It is perfectly viable — in containers or any cloud — but the "it just works" convenience is gone.
Practical example: an internal ERP migrated to Next.js "for standardization" gained six-times-longer build times and a caching layer nobody used. Every screen was authenticated: not a single line of server-generated HTML had value there.
How do you start a Next.js project the right way?
A roadmap that avoids rework:
- Create it with
npx create-next-app@latestand accept TypeScript and ESLint. TypeScript matters more here than on average: typing covers the server-client boundary, where the silent errors live. - Design the routes before writing components. The folder tree is the application's architecture; refactoring it later costs more than planning it up front.
- Start everything as a Server Component. Add
'use client'only when the compiler error demands it. The reverse path — assuming client by default — is the most common mistake for people coming from the Pages Router. - Choose the caching strategy per route deliberately. Writing
export const dynamic = 'force-dynamic'to "fix" stale data usually throws away the very gain that motivated choosing the framework. - Measure before optimizing.
next buildshows the size of each route; Lighthouse shows the effect on the user. Optimizing without those two numbers is guesswork.
If the goal is to see the whole thing working end to end, a good exercise is connecting the application to a real database — the walkthrough on integrating MongoDB with Next.js covers exactly that path.
Practical example: a team that started marking every component with 'use client' to "avoid errors" ended up with a bundle larger than their previous SPA. The fix was removing the directive from the outside in, keeping it only on components with state.
Conclusion
Next.js became the de facto standard for React in production because it solves, with mutually coherent decisions, the set of problems any serious application encounters: routing, rendering, caching, asset optimization and the server-client boundary. The App Router and Server Components push work to the server, reduce shipped JavaScript and improve both experience and indexing — provided you understand where each component executes and choose the rendering strategy per route rather than by habit. For sites whose traffic comes from search, or applications mixing public content and a logged-in area, it is a hard choice to beat. For internal dashboards and tools behind a login, admit it without guilt: Vite delivers the same result with fewer moving parts.
## faq
Frequently asked questions
What is Next.js?
It is a web application framework built on top of React and maintained by Vercel. It adds to React what a real application needs and the library does not provide: a routing system, server rendering, static generation, caching layers, image and font optimization, and an integrated backend layer for APIs.
What is the difference between React and Next.js?
React is an interface library: it renders components and manages state. Next.js is a framework that uses React as its interface layer and solves everything else — how pages are routed, where HTML is generated, what gets cached and how code reaches the browser. You do not choose between them: you choose whether to assemble those pieces manually or use the framework's.
What are React Server Components?
They are components executed exclusively on the server, whose output is sent to the browser already rendered, without the component code going into the bundle. That lets you access databases and secrets directly in the component and reduces the JavaScript delivered to the client. Components that need interactivity — state, events, effect hooks — are marked with the use client directive.
Is Next.js good for SEO?
Yes, and it is one of the main reasons for adoption. Because HTML is generated on the server or at build time, the crawler receives the complete page in the first response, without depending on JavaScript execution. Combined with the per-route metadata API, generated sitemaps and image and font optimizations that improve Core Web Vitals, the result is usually superior to an equivalent SPA.
Do I have to host Next.js on Vercel?
No. Vercel maintains the framework and offers the most direct integration, but Next.js applications run in any Node.js environment, in Docker containers, on providers like AWS, Google Cloud and Azure, and — in static export mode — on any file hosting. Some edge and revalidation features require extra configuration outside Vercel.
App Router or Pages Router: which should I use?
For new projects, the App Router — that is where the new features, Server Components, streaming and the modern caching layers live. The Pages Router is still supported and remains a solid base for existing applications; migration can be incremental, since both routers coexist in the same project.
Topics in this article
## continue lendo
Artigos relacionados
Keep browsing
Previous article

Rust: the language that solves memory safety without a garbage collector
Rust delivers C-level performance with memory safety guaranteed at compile time. Understand ownership, the borrow checker and the real learning curve.
Read moreNext article

Terraform and Infrastructure as Code: the guide to stop clicking in the console
Terraform describes infrastructure in versioned files and applies changes predictably. See the workflow, the state, common mistakes and OpenTofu.
Read moreAbout the author



