Glossary term

Next.js

Next.js is a React framework with conventions for routing, server-side and client-side UI, data fetching, and production output. It is not limited to SSR, and its runtime requirements depend on the features an application uses.

In brief

A framework built on React for building web applications.

React supplies the component model for the user interface. Next.js adds project structure, file-system routing, server capabilities, a build system, and production conventions. It is therefore neither another name for React nor merely a library for a single component.

The App Router in the app directory is the current model for new features. page files define pages, layout files define shared wrappers, and route files define custom HTTP handlers. The older Pages Router remains supported for existing applications, but any explanation that covers both must distinguish their different rules.

Next.js can produce static output, render parts of an application at request time, and hydrate interactive parts in the browser. It is therefore not simply another term for server-side rendering. Nor is it Node.js: the standard toolchain requires Node.js for builds, but the production output does not always have to run as a persistent Node.js server.

What problem it solves

Turns the pieces of a React application into a consistent application model.

React alone does not define URLs, shared layouts, server-side data fetching, metadata, or production output. Next.js provides conventions and tools for these concerns so that a team does not have to assemble every layer independently.

  • web applications with public pages, authenticated areas, and shared layouts
  • product catalogues and content that can be generated at build time or request time as needed
  • interactive administration interfaces that combine Server Components with small client boundaries
  • fetching data directly in a Server Component close to a database or API
  • Route Handlers for focused HTTP endpoints, webhooks, or backend-for-frontend operations
  • managing metadata, images, and production builds within one framework

Practical example

A product page fetches data on the server while the cart remains interactive.

The page.tsx file is a Server Component. It loads the product on the server, handles an unknown ID, and sends only the values needed by the button to the client. AddToCart marks a use client boundary because it uses state and an event handler, so the fetch call in this component runs in the browser.

The example deliberately keeps the UI separate from the authoritative API. The cart endpoint must authenticate the user, authorise the operation, validate the product and price, and protect the request as required by the authentication method. A successful local render does not replace any of those checks.

TypeScript / Next.js (TSX)

// app/products/[id]/page.tsx — Server Component
import { notFound } from 'next/navigation';
import AddToCart from './add-to-cart';
import { getProduct } from '@/lib/products';

export default async function ProductPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const product = await getProduct(id);
  if (!product) notFound();

  return (
    <main>
      <h1>{product.name}</h1>
      <p>{product.formattedPrice}</p>
      <AddToCart productId={product.id} disabled={!product.inStock} />
    </main>
  );
}

// app/products/[id]/add-to-cart.tsx — Client Component
'use client';

import { useState } from 'react';

export default function AddToCart({
  productId, disabled,
}: {
  productId: string;
  disabled: boolean;
}) {
  const [status, setStatus] = useState<'idle' | 'pending' | 'added' | 'error'>('idle');

  async function handleAdd() {
    setStatus('pending');
    try {
      const response = await fetch('/api/cart', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ productId, quantity: 1 }),
      });
      if (!response.ok) throw new Error('The cart could not be updated.');
      setStatus('added');
    } catch {
      setStatus('error');
    }
  }

  return (
    <div>
      <button type="button" disabled={disabled || status === 'pending'} onClick={handleAdd}>
        {status === 'added' ? 'Added' : 'Add to cart'}
      </button>
      <span aria-live="polite">
        {status === 'error' ? 'Could not add the item.' : ''}
      </span>
    </div>
  );
}

How it works

Request → App Router → server output → HTML and RSC payload → interaction.

A route may be static, rendered at request time, or composed from a static shell and streamed sections. This flow describes a typical initial load of an App Router page.

  1. The App Router matches segments Folders and special files determine the page, nested layouts, loading state, and any dynamic URL parameters.
  2. Server Components fetch data Pages and layouts are Server Components by default. They can read data on the server and render a result without shipping their implementation in the client-side JavaScript bundle.
  3. Next.js produces the output The React Server Component payload describes the server-rendered tree and references to client-side parts. Next.js can also use it to prerender the initial HTML.
  4. Suspense enables streaming A ready shell and fallback can arrive before a slower section. Streaming does not make the data source itself faster, and it still needs meaningful loading and error states.
  5. The browser hydrates client boundaries JavaScript attaches the Client Component handlers. On later navigations, the framework uses the RSC payload and client-side router without fully reloading the document.

Core concepts

Routing, component boundaries, and rendering serve different purposes.

The exact caching and data-fetching model must be checked against the version and configuration in use. What does not change is the need to decide explicitly when data is produced and how it is refreshed.

Pages, layouts, and segments

A page exposes the UI for a route, while a layout wraps its descendants and preserves shared UI during navigation. Square brackets define a dynamic segment; a folder alone does not create a URL without a corresponding page or route.

Server Components

These run in a separate server environment at build time or request time. They can use server-side resources and pass serializable data to a Client Component, but cannot use browser APIs or interactive Hooks such as useState.

Client Components

The use client directive marks an entry point into the client module graph. These components can use state, Effects, event handlers, and browser APIs, yet their initial output may still be included in server-prerendered HTML.

Static and request-time rendering

Static output is generated before a particular request and can be distributed efficiently. Request-time rendering can use cookies, headers, or fresh request-specific data at the cost of server work and more complex caching.

Data, caching, and revalidation

A Server Component can read data through fetch, a database library, or another asynchronous source. The current model offers explicit cache directives through the optional Cache Components feature, which must be enabled in configuration, as well as revalidation. Older versions and other configurations behave differently, so guidance cannot be copied blindly.

Route Handlers and metadata

A route.ts file handles HTTP methods through Request and Response and represents a real endpoint. Metadata can come from a static object, generateMetadata, or file conventions; a Server Component is not a substitute for an API route.

Image, build, and deployment

The Image component can prepare sizes, formats, and lazy loading according to the loader. A build can produce optimised output for a Node.js server, Docker, a limited static export, or a supported adapter.

Benefits, limitations, and common mistakes

A framework standardises decisions; it does not make them correct automatically.

Practical benefits

  • routing and nested layouts based on consistent file conventions
  • keeping data access and non-interactive logic out of the client bundle
  • combining static output, request-time rendering, and streaming in one application
  • integrated metadata, image handling, builds, and multiple deployment options

Limitations and common mistakes

  • choosing Next.js for a small, entirely client-side widget that uses none of its framework features
  • confusing a Server Component with SSR or a backend endpoint
  • assuming use client means the component is rendered only in the browser at every stage
  • using browser APIs or an interactive Hook in a Server Component
  • relying on an unverified caching model copied from another major version
  • expecting good performance or SEO automatically without sound data, metadata, HTML, and measurement

When to use it and how it compares

Next.js is not React, Node.js, or one fixed rendering strategy.

React handles component composition and interface updates. Next.js defines the broader architecture of a web application: URLs, layouts, server and client boundaries, data fetching, and the production build. A simple React widget does not need it, while a catalogue with public content and an authenticated administration area may benefit from its shared conventions.

Server Components and SSR answer different questions. A Server Component means the implementation runs outside the client module graph and the client receives its result in the RSC payload. SSR means generating the initial HTML for a request. A Server Component may run at build time, while initial SSR can include the output of Client Components too.

Client-side rendering means that JavaScript in the browser creates the primary content. A Client Component, by contrast, identifies code that can use client-side React APIs. Next.js may prerender its HTML for the first request and hydrate it later; use client does not mean “never participate in server rendering.”

Static rendering produces output before a user visits, whereas request-time rendering can account for specific cookies, headers, and current data. Caching can reduce repeated work, but correctness depends on the actual inputs, lifetime, and invalidation. Streaming only allows ready sections to be sent sooner.

A Next.js application can run as a Node.js server or in Docker, but it can also be deployed as a limited static export or through an adapter. Static exports do not support every dynamic feature, and adapters differ in their capability matrices. It is therefore inaccurate to say that every production Next.js project always needs a persistent Node.js server.

Implementation checklist

Server, client, and cache boundaries must be visible in the design.

A well-designed Next.js application neither sends everything to the client nor hides every operation behind a magical cache. Each route makes it clear where data originates, who may share it, and how failures appear.

  • keep use client at the smallest practical interactive boundary, and never pass secrets or non-serializable values into it
  • run independent data operations in parallel and use Suspense where an incremental state genuinely helps
  • verify default caching, revalidation, and fetch behaviour for the specific version instead of reusing older guidance
  • test agreement between server HTML and the client render, along with errors, navigation, focus, and behaviour without hydration
  • confirm that the target deployment supports every feature in use, and measure both the client bundle size and server response time

Frequently asked questions

Next.js without confusing its rendering models

Are Next.js and React the same thing?

No. React is a user-interface library. Next.js is a framework built on React that supplies routing, server capabilities, data fetching, builds, and deployment conventions.

Is Next.js only an SSR framework?

No. The App Router combines static and request-time rendering, React Server and Client Components, streaming, and client-side navigation according to the needs of each route.

Is a Server Component an API endpoint?

No. A Server Component produces part of the user interface and the RSC payload. A Route Handler in route.ts provides a custom HTTP endpoint in the App Router.

Does use client mean a component exists only in the browser?

No. The directive marks a client module boundary and enables interactive APIs. On the initial load, Next.js may include its output in prerendered HTML and then hydrate it in the browser.

Does every Next.js application need a Node.js server in production?

No. A Node.js server and Docker support the full feature set, but some applications can be exported statically or deployed through an adapter. Available capabilities always depend on the chosen output.

Hands-on experience

I evaluate a framework against the data, operational, and user boundaries of the application.

When designing web systems, I connect the frontend to APIs, caching, failure scenarios, and deployment while keeping every layer accountable for a clear responsibility.

Request a call

I will call you on the next working day between 9:00 and 17:00.

You can also call me directly.

+420 605 181 728

Leave your phone number and send a callback request.

By sending, you agree to processing your data in order to handle your request.