Next.js

Next.js is a powerful React framework that enables you to build high-performance web applications with features like Server-Side Rendering (SSR) and Static Site Generation (SSG) out of the box. While React is a library for building UIs, Next.js provides the "scaffolding"—handling routing, optimization, and data fetching—making it a full-stack framework.

  1. App Router: A modern routing system built on React Server Components, supporting layouts, nesting, and streaming.
  2. Hybrid Rendering: Choose between SSR, SSG, and ISR (Incremental Static Regeneration) on a per-page basis.
  3. Automatic Image Optimization: Automatically resizes and serves images in modern formats like WebP or AVIF using the component.
  4. Built-in CSS/Sass Support: Support for CSS Modules, Tailwind CSS, and CSS-in-JS.
  5. Turbopack: A high-performance Rust-based bundler that makes development builds significantly faster than Webpack.

  1. SEO Friendly: By pre-rendering content on the server, search engines can easily crawl your site, which is a major advantage over standard Client-Side React.
  2. Fast Initial Load: Only the necessary JavaScript and CSS are sent to the client, reducing "Time to Interactive."
  3. Zero Config: Features like TypeScript support, linting, and bundling are configured automatically.
  4. API Routes: You can write backend code (like handling form submissions or database queries) directly within your Next.js project.

To start a new project, you need Node.js (v20.9 or later as of 2026). The recommended way is using the automated CLI tool:

  1. Run the installer: npx create-next-app@latest
  2. Follow the prompts: You’ll be asked to name your project and choose options like TypeScript, ESLint, and Tailwind CSS.
  3. Start development: cd your-app-name and then npm run dev.
  4. View it: Open http://localhost:3000.

Note: As of early 2026, Next.js 15/16 is the stable standard. These versions focus on deep integration with React 19, stable Server Actions, and the use of Turbopack as the default bundler for lightning-fast development cycles.

In the modern App Router, components are Server Components by default. They stay on the server and do not send JavaScript to the client, which keeps your bundle size small.

  1. Client Components: If you need interactivity (like useState or ,onClick), you must add the 'use client' directive at the top of the file.

Next.js uses a file-system based router. In the App Router, folders define routes.

  1. app/page.tsx ? maps to /
  2. app/about/page.tsx ? maps to /about
  3. app/blog/[slug]/page.tsx ? maps to a dynamic route like /blog/hello-world

A layout is UI that is shared between multiple pages. On navigation, layouts preserve state, remain interactive, and do not re-render. This is where you typically put your Navigation bar and Footer.

In the App Router, you can fetch data directly inside Server Components using standard async/await and the native fetch API.

Next.js extends fetch to allow for automatic caching and revalidation (replacing the old getStaticProps).

Server Actions are asynchronous functions that run on the server. They are often used to handle form submissions without needing to manually create an API endpoint.

Comparison of App Router vs. Pages Router

The App Router is the modern standard for Next.js, introduced to leverage React Server Components, while the Pages Router is the legacy system still maintained for backwards compatibility.

Feature App Router (Modern) Pages Router (Legacy)
Directory Uses the app/ directory. Uses the pages/ directory.
Routing Logic Folder-based: Folders define routes; page.js makes them public. File-based: Every file in the folder is a route.
Component Type Server Components by default; Client Components via 'use client'. Client Components only (with SSR/SSG hydration).
Data Fetching Uses async/await in Server Components + fetch(). Uses getStaticProps, getServerSideProps, and getInitialProps.
Layouts Supports Nested Layouts (native layout.js). Requires custom _app.js or _document.js wrappers.
Rendering Granular (Server, Client, Streaming, and Static). Page-level (SSR, SSG, or CSR).

Key Technical Differences

  1. Server Components (RSC): The App Router allows components to stay on the server, significantly reducing the JavaScript bundle sent to the browser. In the Pages Router, all components are sent to the client for hydration.
  2. Data Fetching Evolution: In the App Router, data fetching is simplified. You no longer need specific Next.js functions like getServerSideProps; you simply use fetch with caching options (>{ cache: 'no-store' } for dynamic data or >{ next: { revalidate: 3600 } } for ISR).
  3. Streaming & Suspense: The App Router is built on React Suspense. This allows for Streaming, where parts of the page can load and display UI immediately while slower data-fetching segments are still loading.
  4. SEO & Metadata: The App Router uses a built-in Metadata API (exporting a metadata object), whereas the Pages Router relies on the >< Head> component.

Server Components vs. Client Components

In the Next.js App Router, components are Server Components by default. The distinction lies in where the component renders and how much JavaScript is sent to the browser.

Feature App Router (Modern) Pages Router (Legacy)
Directory Uses the app/ directory. Uses the pages/ directory.
Routing Logic Folder-based: Folders define routes; page.js makes them public. File-based: Every file in the folder is a route.
Component Type Server Components by default; Client Components via 'use client'. Client Components only (with SSR/SSG hydration).
Data Fetching Uses async/await in Server Components + fetch(). Uses getStaticProps, getServerSideProps, and getInitialProps.
Layouts Supports Nested Layouts (native layout.js). Requires custom _app.js or _document.js wrappers.
Rendering Granular (Server, Client, Streaming, and Static). Page-level (SSR, SSG, or CSR).

When to Use Each

. Use Server Components for:

  1. Fetching data from a database or API.
  2. Storing sensitive information (API keys, tokens).
  3. Keeping large dependencies on the server to reduce client-side bundle size.
  4. Static content that doesn't change based on user input.

. Use Client Components for:

  1. Interactivity (buttons, forms, carousels).
  2. Using State and Lifecycle hooks (useState, useReducer, useEffect).
  3. Browser-only APIs (Geolocation, localStorage, document).
  4. Custom hooks that depend on state or effects.

The "Component Tree" Rule

You can import a Client Component into a Server Component. However, you cannot import a Server Component into a Client Component directly. To use a Server Component inside a Client Component, you must pass it as children or a prop to maintain the server-side rendering boundary.

The 'use client' Directive

The 'use client' directive is a convention used to declare a boundary between server-side and client-side code. It signals to the bundler that the module and its dependencies are intended for the browser.

  1. Placement: It must be the very first line of the file, appearing before any import statements.
  2. Scope: Once a file is marked with 'use client', all other modules imported into it are also considered part of the client bundle.

Usage Rules and Best Practices

  1. Leaf Component Pattern: To keep the application fast, you should move 'use client' as far down the component tree as possible. For example, instead of making a whole layout a Client Component just for a search bar, make only the SearchBar component a Client Component.
  2. Default Behavior: You do not need 'use client' in every file. In the App Router, files are Server Components by default.
  3. Interoperability: You can pass Server Components as children or props to a Client Component, but you cannot import and render a Server Component directly inside a Client Component file.

Implementation Comparison

Aspect Correct Implementation Incorrect Implementation
Position Top of the file (Line 1). Inside a function or after imports.
Syntax 'use client'; (quotes required). use client; (no quotes).
Imports Imports follow the directive. Imports precede the directive.

Example Code

Static Site Generation (SSG) in the App Router

In the Next.js App Router, Static Site Generation (SSG) is the process of fetching data and rendering pages at build time rather than at request time. The result is a set of static HTML, JavaScript, and CSS files that can be served instantly from a CDN.

In the App Router, SSG is the default behavior for any component that does not use dynamic functions (like cookies() or headers()) or uncached data fetches.

How SSG is Triggered

Next.js automatically statically generates routes unless you explicitly opt out. It relies on the caching behavior of the fetch API.

  1. Static Fetch (Default): fetch('https://api.example.com/data') is cached indefinitely by default.
  2. Force Cache: fetch('url', { cache: 'force-cache' }) explicitly ensures the data is fetched once at build time.

Dynamic Routes and SSG

For routes with dynamic parameters (e.g., /blog/[slug]), Next.js needs to know which paths to pre-render at build time. This is handled by the generateStaticParams function.

Function/Feature Purpose in SSG
generateStaticParams Replaces the old getStaticPaths. It returns an array of objects representing the route segments to be statically generated.
fetch Caching Replaces getStaticProps. Data is fetched during the build and stored in the Data Cache.
export const dynamic Setting force-static ensures a layout or page is always treated as static, even if it uses dynamic logic.

Key Advantages of SSG

  1. Maximum Performance: Since the HTML is already generated, the server just sends a file, leading to a near-instant "Time to First Byte" (TTFB).
  2. Reduced Server Load: The server (or Edge Network) doesn't need to execute database queries or complex logic for every user request.
  3. SEO Optimization: Fully rendered HTML is available immediately for search engine crawlers.

Example: SSG for Dynamic Routes

Dynamic Rendering in Next.js

Dynamic Rendering is a strategy where routes are rendered for each user at request time. This is essential for pages that display personalized data (like user profiles), real-time information (like stock prices), or information that depends on information only known at the time of the request (like cookies).

How Next.js Decides: Static vs. Dynamic

Next.js automatically switches from Static Rendering (default) to Dynamic Rendering if it detects the use of Dynamic Functions or Uncached Data Requests.

Category Triggers Dynamic Rendering Description
Dynamic Functions cookies(), headers() Accessing request-specific info like auth tokens or browser headers.
Search Params searchParams prop Accessing URL query strings (e.g., ?query=nextjs) in a page component.
Uncached Fetch cache: 'no-store' Explicitly telling a fetch request to bypass the cache and get fresh data.
Segment Config export const dynamic = 'force-dynamic' Manually forcing the route to render dynamically.

Key Characteristics

  1. Request-Time Execution: The server processes the code and generates HTML only when a user visits the URL.
  2. Data Freshness: Since rendering happens on-demand, the content is always up-to-date with the latest database or API changes.
  3. Performance Trade-off: It is generally slower than Static Rendering because the server must do work for every request rather than serving a pre-built file from a CDN.

The "Caching" Nuance

In the App Router, even if a route is dynamically rendered, Next.js may still cache specific data fetches within that route unless specified otherwise. This is known as the Data Cache, which operates independently of whether the page itself is static or dynamic.

Incremental Static Regeneration (ISR)

Incremental Static Regeneration (ISR) allows you to update static content without needing to rebuild the entire site. It provides the performance benefits of Static Site Generation (SSG) with the flexibility of Dynamic Rendering by revalidating specific pages in the background.

How it Works

  1. Build Time: The page is generated statically.
  2. Initial Requests: All users see the cached static version.
  3. Revalidation Window: After a specified time interval, the next request triggers a background regeneration
  4. Background Update: Next.js fetches new data and regenerates the page. Once successful, the cache is updated for future visitors.

Implementation Methods

In the App Router, ISR is implemented through the fetch API or segment configuration rather than the legacy revalidate prop from getStaticProps.

Method Implementation Code Use Case
Time-based (Fetch) fetch(url, { next: { revalidate: 3600 } }) Automatically updates the data cache every hour.
Segment Config export const revalidate = 3600; Applies a revalidation frequency to the entire page or layout.
On-Demand (Tag) revalidateTag('collection') Manually clears cache when a specific event occurs (e.g., CMS update).
On-Demand (Path) revalidatePath('/blog/post-1') Manually updates a specific URL immediately.

Example: Implementation with Fetch

Benefits of ISR

  1. Scalability: Handles millions of pages without massive build times.
  2. Freshness: Keeps content updated without manual redeploys.
  3. Reliability: If a background regeneration fails, the old page remains available, ensuring zero downtime.

Streaming and React Suspense

Streaming allows you to break down a page's HTML into smaller chunks and progressively send them from the server to the client. This prevents "slow" data requests from blocking the entire page, allowing the user to see and interact with parts of the page (like navigation or sidebars) while the main content is still loading.

How it Works

  1. Traditional SSR: The server must fetch all data for a page before it can send any HTML to the client. The user sees a blank screen or a loading spinner for the whole page.
  2. Streaming with Suspense: Next.js sends the static parts of the page immediately. Parts of the UI wrapped in are replaced by a loading fallback. Once the server finishes fetching the data for that specific component, it "streams" the final HTML and swaps it into place.

Implementation Methods

Method Level Description
loading.js Route Level A special file placed in a folder. Next.js automatically wraps the page.js and any nested children in a <Suspense> boundary with this file as the fallback.
<Suspense> Component Level Manual wrapping around specific components. This allows for more granular control, letting multiple parts of a page load independently.

Example: Component-Level Streaming

Key Benefits

  1. Reduced Time to First Byte (TTFB): The server starts sending HTML almost immediately.
  2. Improved First Contentful Paint (FCP): Critical UI elements appear sooner.
  3. Prioritized Interaction: Users can click links or use the sidebar without waiting for the entire data-heavy center of the page to load.

The Purpose of loading.tsx

The loading.tsx file is a special Next.js file used to create instant loading states for a specific route segment. It leverages React Suspense under the hood to improve the user experience during data fetching.

Core Functions

  1. Automatic Suspense: Next.js automatically wraps your page.tsx file (and any nested children) in a boundary. The content of loading.tsx serves as the fallback UI.
  2. Instant Feedback: Because it is pre-rendered on the server, the loading UI appears immediately upon navigation, even before the server has finished fetching the data for the page.
  3. Shared Layouts: Navigation remains interactive. Users can still interact with shared elements like sidebars or navbars defined in layout.tsx while the specific page content loads.

Hierarchy and Nesting

The loading.tsx file follows the file-system hierarchy. A file in a parent folder will apply to all nested child routes unless the child route has its own loading.tsx file to override it.

Feature Description
Behavior loading.tsx behavior
Placement Place in any folder within the /app directory.
Trigger Triggered automatically during server-side data fetching or client-side navigation.
User Experience Prevents "stuck" navigations where the screen doesn't change until data is ready.
Implementation Usually contains Skeletons, Spinners, or "Ghost" UI elements.

Example Implementation

Nested Layouts in Next.js

A Nested Layout is a UI structure created by placing a layout.tsx file inside a sub-folder of the /app directory. This layout wraps only the segments within that specific folder, while being "nested" inside the parent layout (usually the root layout).

How Nesting Works

Next.js uses a containment model. A child layout or page is passed as the children prop to the layout immediately above it in the file hierarchy.

  1. Root Layout (app/layout.tsx): Applies to the entire application (contains < html> and < body>).
  2. Segment Layout (app/dashboard/layout.tsx): Applies only to routes starting with /dashboard.

State Persistence

One of the primary advantages of layouts is that they persist state and maintain interactivity during navigation between their child routes.

Feature Behavior in Layouts
Partial Rendering On navigation, only the changing page segment re-renders; the layout remains static.
Component State Client-side state (e.g., a search input value or a toggle) inside a layout is preserved.
Scroll Position The scroll position within a layout (like a sidebar) is maintained.
Lifecycle Hooks useEffect or useState inside a layout do not re-trigger when switching between sibling pages.

Route Groups in Next.js

A Route Group is a folder naming convention using parentheses—for example, (auth) or (marketing)—that allows you to organize your route segments and layouts without affecting the URL path.

Primary Purposes

  1. Organized Hierarchy: Group related routes (e.g., all authentication pages) into a single folder to keep the app directory clean.
  2. Opt-in Layouts: Apply a specific layout.tsx to a group of routes while excluding others at the same level.
  3. Multiple Root Layouts: Create entirely different UI shells for different sections of the app (e.g., a (shop) layout vs. a (dashboard) layout) by creating multiple route groups at the top level, each with its own layout.tsx.

How the URL is Affected

The folder name in parentheses is completely omitted from the URL.

Folder Structure Resulting URL
app/(auth)/login/page.tsx /login
app/(auth)/register/page.tsx /register
app/(marketing)/about/page.tsx /about

Use Case: Scoped Layouts

Without Route Groups, any layout.tsx file automatically applies to all nested child routes. With Route Groups, you can isolate layouts:

  1. Shared Logic: If you have app/(admin)/layout.tsx, only the pages inside the (admin) folder will inherit that layout.
  2. Exclusion: Pages in app/(user)/ will not see the admin layout, even though both groups live at the same "level" in the file system.

Dynamic Routes in Next.js

Dynamic Routes allow you to create pages where the URL segment is not known ahead of time (e.g., blog posts, user profiles, or product pages). By wrapping a folder name in square brackets, such as [id] or [slug], you create a placeholder that Next.js will fill with the actual value from the URL.

Accessing Route Parameters

How you access these parameters depends on whether the component is a Server Component or a Client Component.

Component Type Method to Access Example
Server Component params: Prop: Passed directly to the page function as a Promise. const { id } = await params;
Client Component useParams() Hook: A hook imported from next/navigation. const params = useParams();

Types of Dynamic Segments

Next.js supports different levels of dynamic matching:

  1. Single Segment ([id]): Matches one segment.
  2. Example: app/blog/[id]/page.js matches /blog/123.
  3. Catch-all ([...slug]): Matches one or more segments.
  4. Example: app/shop/[...slug]/page.js matches /shop/clothes, /shop/clothes/tops, etc.
  5. Optional Catch-all ([[...slug]]): Matches zero or more segments (also matches the base route).
  6. Example: app/docs/[[...slug]]/page.js matches /docs, /docs/intro, /docs/intro/setup.

Code Example: Server Component

In the App Router (v15+), params is an asynchronous object:

Code Example: Client Component

Catch-all vs. Optional Catch-all Segments

These special dynamic route patterns allow a single route file to handle multiple URL path depths, making them ideal for documentation, file browsers, or complex CMS-driven sites.

  1. .Catch-all Segments ([...slug])

By adding an ellipsis inside the brackets, you tell Next.js to match all subsequent segments of the URL. This segment is returned as an array of strings.

  1. Requirement: It must match at least one segment after the parent path.
  2. Behavior:
File Path URL params Value
app/shop/[...slug]/page.js /shop/shoes { slug: ['shoes'] }
app/shop/[...slug]/page.js /shop/shoes/nike { slug: ['shoes', 'nike'] }
app/shop/[...slug]/page.js /shop 404 Not Found**

2. Optional Catch-all Segments ([[...slug]])

By wrapping the catch-all in double brackets, you make the parameter optional. This allows the route to match even if there are zero segments after the parent path.

  1. Requirement: Matches any number of segments, including none.
  2. Behavior:
File Path URL params Value
app/docs/[[...slug]]/page.js /docs { slug: undefined }
app/docs/[[...slug]]/page.js /docs/setup { slug: ['setup'] }
app/docs/[[...slug]]/page.js /docs/setup/git { slug: ['setup', 'git'] }

Key Differences at a Glance

Feature Catch-all ([...slug]) Optional Catch-all ([[...slug]])
Matches Base Route? No Yes
Minimum Segments 1 0
Primary Use Case Deeply nested product categories. Documentation sites with a main index.

Example Code (Server Component)

Link Component vs. useRouter Hook

In Next.js, both the component and the useRouter hook are used for navigation, but they serve different purposes and are optimized for different scenarios.

Feature <Link> Component useRouter Hook
Primary Use Declarative navigation (standard UI links). Programmatic navigation (logic-based).
SEO Excellent: Renders as an <a> tag for crawlers. Poor: Not discoverable by crawlers.
Prefetching Automatic: Prefetches data when in viewport. Manual: Requires calling router.prefetch().
Requirement Works in both Server & Client Components. Client Components only ('use client').
Environment Standard JSX. Inside event handlers or useEffect.

When to Use the , Component

The component is the primary way to navigate between routes. It is a wrapper around the HTML < a> tag and is optimized for performance.

. Standard Navigation: Menus, sidebars, and footer links.

. Performance: Next.js automatically prefetches the code for the linked page in the background, making the transition feel near-instant.

. Accessibility: It handles keyboard navigation and right-clicks ("Open in new tab") natively.

When to Use the useRouter Hook

Parallel Routes and Named Slots

Parallel Routes allow you to render one or more pages simultaneously in the same layout. This is particularly useful for complex, highly dynamic dashboards or social feeds where different sections of the page load independently.

The @folder Slot Convention

Parallel routes are defined using Named Slots. You create a slot by prefixing a folder name with the @ symbol (e.g., @analytics or @team).
  1. Folder Structure: These slots are not part of the URL path. A folder at app/dashboard/@analytics is accessed at the URL /dashboard.
  2. Layout Integration: The layout at the same level as the slots receives these slots as props.

Implementation Example

1. File Structure:

2. Layout Code (app/dashboard/layout.tsx): Next.js automatically passes @analytics and @team to the layout component.

Key Features & Use Cases

Feature Description
Independent Streaming Each slot can have its own loading.js and fetch data independently without blocking the others.
Independent Error Handling You can wrap individual slots in their own Error Boundaries.
Conditional Rendering You can render slots based on user roles or state (e.g., show @admin slot only for authenticated admins).
Simultaneous States One slot can be in a "details" view while the other remains in a "list" view.

The default.js File

When using Parallel Routes, Next.js needs a fallback if it cannot recover a slot's state during a full-page reload. You should provide a default.js file within each slot folder to serve as the UI when a slot doesn't have a matching route for the current URL.

Intercepting Routes

Intercepting Routes allow you to load a route from another part of your application within the current layout. This is commonly used to show content in a modal or overlay without losing the context of the background page.

The Syntax

The syntax is inspired by relative file paths (../):

. (.) matches segments at the same level.

. (..) matches segments one level above.

.(..)(..) matches segments two levels above.

. (...) matches segments from the root app directory.

How it Works: The "Soft" vs "Hard" Navigation

Navigation Type Result
Soft Navigation (e.g., clicking a <Link>) The route is intercepted. The content defined in the (..) folder appears (usually as a modal) while the background page remains visible.
Hard Navigation (e.g., Refresh or URL paste) The route is not intercepted. Next.js renders the full page for that route as if the interceptor didn't exist.

Primary Use Cases

. Photo Feeds (The "Instagram" UI): When a user clicks a photo in a grid, a modal opens with the photo. If they refresh the page or share the link, the recipient sees the photo on a full page.

. Login Modals: Clicking "Login" opens an overlay on the current page, but navigating directly to /login shows a dedicated login page.

. Shopping Carts: Opening a quick-view of a product without leaving the product listing.

Example Implementation

If you want to intercept the /photo/[id] route from your home page:

  1. Original Route: app/photo/[id]/page.tsx (The full page view).
  2. Intercepted Route: app/(.)photo/[id]/page.tsx (The modal view).

When a user clicks a on the home page, the content from app/(.)photo/[id]/page.tsx will render inside the current layout (often paired with a Parallel Route slot like @modal).

Combining with Parallel Routes

Intercepting routes are most powerful when used alongside Parallel Routes. This allows you to render the intercepted content into a specific slot (like @modal) in your layout while keeping the main children content visible underneath.

From The Same Category

Ruby On Rails

Browse FAQ's

Express.js

Browse FAQ's

Spring Boot

Browse FAQ's

Laravel

Browse FAQ's

Flask

Browse FAQ's

ASP.NET

Browse FAQ's

Django

Browse FAQ's

DocsAllOver

Where knowledge is just a click away ! DocsAllOver is a one-stop-shop for all your software programming needs, from beginner tutorials to advanced documentation

Get In Touch

We'd love to hear from you! Get in touch and let's collaborate on something great

Copyright copyright © Docsallover - Your One Shop Stop For Documentation