Defining Routes
We recommend reading the Routing Fundamentals page before continuing.
This page will guide you through how to define and organize routes in your Next.js application.
Creating Routes
Next.js uses a file-system based router where folders are used to define routes.
Each folder represents a route segment that maps to a URL segment. To create a nested route, you can nest folders inside each other.
A special page.js file is used to make route segments publicly accessible.
In this example, the /dashboard/analytics URL path is not publicly accessible because it does not have a corresponding page.js file. This folder could be used to store components, stylesheets, images, or other colocated files.
Good to know: .js, .jsx, or .tsx file extensions can be used for special files.
Creating UI


Creating UI
Special file conventions are used to create UI for each route segment. The most common are pages to show UI unique to a route, and layouts to show UI that is shared across multiple routes.
For example, to create your first page, add a page.js file inside the app directory and export a React component:
app/page.tsx export default function Page() {
  return
Hello, Next.js!

}


Pages and Layouts
We recommend reading the Routing Fundamentals and Defining Routes pages before continuing.
The App Router inside Next.js 13 introduced new file conventions to easily create pages, shared layouts, and templates. This page will guide you through how to use these special files in your Next.js application.
Pages
A page is UI that is unique to a route. You can define pages by exporting a component from a page.js file. Use nested folders to define a route and a page.js file to make the route publicly accessible.
Create your first page by adding a page.js file inside the app directory:
app/page.tsx // `app/page.tsx` is the UI for the `/` URL
export default function Page() {
  return
Hello, Home page!

}
app/dashboard/page.tsx // `app/dashboard/page.tsx` is the UI for the `/dashboard` URL
export default function Page() {


export default function Page() {
  return
Hello, Dashboard Page!

}
Good to know:
A page is always the leaf of the route subtree.
.js, .jsx, or .tsx file extensions can be used for Pages.
A page.js file is required to make a route segment publicly accessible.
Pages are Server Components by default but can be set to a Client Component.
Pages can fetch data. View the Data Fetching section for more information.
Layouts
A layout is UI that is shared between multiple pages. On navigation, layouts preserve state, remain interactive, and do not re-render. Layouts can also be nested.
You can define a layout by default exporting a React component from a layout.js file. The component should accept a children prop that will be populated with a child layout (if it exists) or a child page during rendering.
app/dashboard/layout.tsx export default function DashboardLayout({


app/dashboard/layout.tsx export default function DashboardLayout({
  children, // will be a page or nested layout
}: {
  children: React.ReactNode
}) {
  return (

      {/* Include shared UI here e.g. a header or sidebar */}

      {children}

  )
}
Good to know:
The top-most layout is called the Root Layout. This required layout is shared across all pages in an application. Root layouts must contain html and body tags.
Any route segment can optionally define its own Layout. These layouts will be shared across all pages in that segment.
Layouts in a route are nested by default. Each parent layout wraps child layouts below it using the React children prop.
You can use Route Groups to opt specific route segments in and out of shared layouts.


You can use Route Groups to opt specific route segments in and out of shared layouts.
Layouts are Server Components by default but can be set to a Client Component.
Layouts can fetch data. View the Data Fetching section for more information.
Passing data between a parent layout and its children is not possible. However, you can fetch the same data in a route more than once, and React will automatically dedupe the requests without affecting performance.
Layouts do not have access to the current route segment(s). To access route segments, you can use useSelectedLayoutSegment or useSelectedLayoutSegments in a Client Component.
.js, .jsx, or .tsx file extensions can be used for Layouts.
A layout.js and page.js file can be defined in the same folder. The layout will wrap the page.
Root Layout (Required)


Root Layout (Required)
The root layout is defined at the top level of the app directory and applies to all routes. This layout enables you to modify the initial HTML returned from the server.
app/layout.tsx export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
Good to know:
The app directory must include a root layout.
The root layout must define <html> and <body> tags since Next.js does not automatically create them.
You can use the built-in SEO support to manage <head> HTML elements, for example, the <title> element.
You can use route groups to create multiple root layouts. See an example here.
The root layout is a Server Component by default and can not be set to a Client Component.


The root layout is a Server Component by default and can not be set to a Client Component.
Migrating from the pages directory: The root layout replaces the _app.js and _document.js files. View the migration guide.
Nesting Layouts
Layouts defined inside a folder (e.g. app/dashboard/layout.js) apply to specific route segments (e.g. acme.com/dashboard) and render when those segments are active. By default, layouts in the file hierarchy are nested, which means they wrap child layouts via their children prop.
app/dashboard/layout.tsx export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}
Good to know:
Only the root layout can contain <html> and <body> tags.


Only the root layout can contain <html> and <body> tags.
If you were to combine the two layouts above, the root layout (app/layout.js) would wrap the dashboard layout (app/dashboard/layout.js), which would wrap route segments inside app/dashboard/*.
The two layouts would be nested as such:
You can use Route Groups to opt specific route segments in and out of shared layouts.
Templates
Templates are similar to layouts in that they wrap each child layout or page. Unlike layouts that persist across routes and maintain state, templates create a new instance for each of their children on navigation. This means that when a user navigates between routes that share a template, a new instance of the component is mounted, DOM elements are recreated, state is not preserved, and effects are re-synchronized.
There may be cases where you need those specific behaviors, and templates would be a more suitable option than layouts. For example:


Enter/exit animations using CSS or animation libraries.
Features that rely on useEffect (e.g logging page views) and useState (e.g a per-page feedback form).
To change the default framework behavior. For example, Suspense Boundaries inside layouts only show the fallback the first time the Layout is loaded and not when switching pages. For templates, the fallback is shown on each navigation.
Recommendation: We recommend using Layouts unless you have a specific reason to use Template.
A template can be defined by exporting a default React component from a template.js file. The component should accept a children prop which will be nested segments.
app/template.tsx export default function Template({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}
The rendered output of a route segment with a layout and a template will be as such:
Output <Layout>
  {/* Note that the template is given a unique key. */}


Output <Layout>
  {/* Note that the template is given a unique key. */}
  <Template key={routeParam}>{children}</Template>
</Layout>
Modifying <head>
In the app directory, you can modify the <head> HTML elements such as title and meta using the built-in SEO support.
Metadata can be defined by exporting a metadata object or generateMetadata function in a layout.js or page.js file.
app/page.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Next.js',
}

export default function Page() {
  return '...'
}
Good to know: You should not manually add <head> tags such as <title> and <meta> to root layouts. Instead, you should use the Metadata API which automatically handles advanced requirements such as streaming and de-duplicating <head> elements.


Learn more about available metadata options in the API reference.


Linking and NavigatingThe Next.js router uses server-centric routing with client-side navigation. It supports instant loading states and concurrent rendering. This means navigation maintains client-side state, avoids expensive re-renders, is interruptible, and doesn't cause race conditions.
There are two ways to navigate between routes:
<Link> Component
useRouter Hook
This page will go through how to use <Link>, useRouter(), and dive deeper into how navigation works.
<Link> Component
<Link> is a React component that extends the HTML <a> element to provide prefetching and client-side navigation between routes. It is the primary way to navigate between routes in Next.js.
To use <Link>, import it from next/link, and pass a href prop to the component:
app/page.tsx import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}


return <Link href="/dashboard">Dashboard</Link>
}
There are optional props you can pass to <Link>. See the API reference for more information.
Examples
Linking to Dynamic Segments
When linking to dynamic segments, you can use template literals and interpolation to generate a list of links. For example, to generate a list of blog posts:
app/blog/PostList.js import Link from 'next/link'

export default function PostList({ posts }) {
  return (

      {posts.map((post) => (

          <Link href={`/blog/${post.slug}`}>{post.title}</Link>

      ))}

  )
}
Checking Active Links


))}
    </ul>
  )
}
Checking Active Links
You can use usePathname() to determine if a link is active. For example, to add a class to the active link, you can check if the current pathname matches the href of the link:
app/ui/Navigation.js 'use client'

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function Navigation({ navLinks }) {
  const pathname = usePathname()

  return (
    <>
      {navLinks.map((link) => {
        const isActive = pathname.startsWith(link.href)

        return (
          <Link
            className={isActive ? 'text-blue' : 'text-black'}
            href={link.href}
            key={link.name}
          >
            {link.name}
          </Link>
        )


>
            {link.name}
          </Link>
        )
      })}
    </>
  )
}
Scrolling to an id
The default behavior of <Link> is to scroll to the top of the route segment that has changed. When there is an id defined in href, it will scroll to the specific id, similarly to a normal <a> tag.
useRouter() Hook
The useRouter hook allows you to programmatically change routes inside Client Components.
To use useRouter, import it from next/navigation, and call the hook inside your Client Component:
app/page.js 'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}


Dashboard
    </button>
  )
}
The useRouter provides methods such as push(), refresh(), and more. See the API reference for more information.
Recommendation: Use the <Link> component to navigate between routes unless you have a specific requirement for using useRouter.
How Navigation Works
A route transition is initiated using <Link> or calling router.push().
The router updates the URL in the browser's address bar.
The router avoids unnecessary work by re-using segments that haven't changed (e.g. shared layouts) from the client-side cache. This is also referred to as partial rendering.
If the conditions of soft navigation are met, the router fetches the new segment from the cache rather than the server. If not, the router performs a hard navigation and fetches the Server Component payload from the server.
If created, loading UI is shown from the server while the payload is being fetched.


If created, loading UI is shown from the server while the payload is being fetched.
The router uses the cached or fresh payload to render the new segments on the client.
Client-side Caching of Rendered Server Components
Good to know: This client-side cache is different from the server-side Next.js HTTP cache.
The new router has an in-memory client-side cache that stores the rendered result of Server Components (payload). The cache is split by route segments which allows invalidation at any level and ensures consistency across concurrent renders.
As users navigate around the app, the router will store the payload of previously fetched segments and prefetched segments in the cache.
This means, for certain cases, the router can re-use the cache instead of making a new request to the server. This improves performance by avoiding re-fetching data and re-rendering components unnecessarily.
Invalidating the Cache


Invalidating the Cache
Server Actions can be used to revalidate data on-demand by path (revalidatePath) or by cache tag (revalidateTag).
Prefetching
Prefetching is a way to preload a route in the background before it's visited. The rendered result of prefetched routes is added to the router's client-side cache. This makes navigating to a prefetched route near-instant.
By default, routes are prefetched as they become visible in the viewport when using the <Link> component. This can happen when the page first loads or through scrolling. Routes can also be programmatically prefetched using the prefetch method of the useRouter() hook.
Static and Dynamic Routes:
If the route is static, all the Server Component payloads for the route segments will be prefetched.


If the route is dynamic, the payload from the first shared layout down until the first loading.js file is prefetched. This reduces the cost of prefetching the whole route dynamically and allows instant loading states for dynamic routes.
Good to know:
Prefetching is only enabled in production.
Prefetching can be disabled by passing prefetch={false} to <Link>.
Soft Navigation
On navigation, the cache for changed segments is reused (if it exists), and no new requests are made to the server for data.
Conditions for Soft Navigation
On navigation, Next.js will use soft navigation if the route you are navigating to has been prefetched, and either doesn't include dynamic segments or has the same dynamic parameters as the current route.
For example, consider the following route that includes a dynamic [team] segment: /dashboard/[team]/*. The cached segments below /dashboard/[team]/* will only be invalidated when the [team] parameter changes.


Navigating from /dashboard/team-red/* to /dashboard/team-red/* will be a soft navigation.
Navigating from /dashboard/team-red/* to /dashboard/team-blue/* will be a hard navigation.
Hard Navigation
On navigation, the cache is invalidated and the server refetches data and re-renders the changed segments.
Back/Forward Navigation
Back and forward navigation (popstate event) has a soft navigation behavior. This means, the client-side cache is re-used and navigation is near-instant.
Focus and Scroll Management
By default, Next.js will set focus and scroll into view the segment that's changed on navigation.


Route GroupsIn the app directory, nested folders are normally mapped to URL paths. However, you can mark a folder as a Route Group to prevent the folder from being included in the route's URL path.
This allows you to organize your route segments and project files into logical groups without affecting the URL path structure.
Route groups are useful for:
Organizing routes into groups e.g. by site section, intent, or team.
Enabling nested layouts in the same route segment level:
Creating multiple nested layouts in the same segment, including multiple root layouts
Adding a layout to a subset of routes in a common segment
Convention
A route group can be created by wrapping a folder's name in parenthesis: (folderName)
Examples
Organize routes without affecting the URL path
To organize routes without affecting the URL, create a group to keep related routes together. The folders in parenthesis will be omitted from the URL (e.g. (marketing) or (shop)).


Even though routes inside (marketing) and (shop) share the same URL hierarchy, you can create a different layout for each group by adding a layout.js file inside their folders.
Opting specific segments into a layout
To opt specific routes into a layout, create a new route group (e.g. (shop)) and move the routes that share the same layout into the group (e.g. account and cart). The routes outside of the group will not share the layout (e.g. checkout).
Creating multiple root layouts
To create multiple root layouts, remove the top-level layout.js file, and add a layout.js file inside each route groups. This is useful for partitioning an application into sections that have a completely different UI or experience. The <html> and <body> tags need to be added to each root layout.
In the example above, both (marketing) and (shop) have their own root layout.
Good to know:


Good to know:
The naming of route groups has no special significance other than for organization. They do not affect the URL path.
Routes that include a route group should not resolve to the same URL path as other routes. For example, since route groups don't affect URL structure, (marketing)/about/page.js and (shop)/about/page.js would both resolve to /about and cause an error.
If you use multiple root layouts without a top-level layout.js file, your home page.js file should be defined in one of the route groups, For example: app/(marketing)/page.js.
Navigating across multiple root layouts will cause a full page load (as opposed to a client-side navigation). For example, navigating from /cart that uses app/(shop)/layout.js to /blog that uses app/(marketing)/layout.js will cause a full page load. This only applies to multiple root layouts.


Dynamic RoutesWhen you don't know the exact segment names ahead of time and want to create routes from dynamic data, you can use Dynamic Segments that are filled in at request time or prerendered at build time.
Convention
A Dynamic Segment can be created by wrapping a folder's name in square brackets: [folderName]. For example, [id] or [slug].
Dynamic Segments are passed as the params prop to layout, page, route, and generateMetadata functions.
Example
For example, a blog could include the following route app/blog/[slug]/page.js where [slug] is the Dynamic Segment for blog posts.
app/blog/[slug]/page.tsx export default function Page({ params }: { params: { slug: string } }) {
  return
My Post: {params.slug}

}


return
My Post: {params.slug}

}
RouteExample URLparamsapp/blog/[slug]/page.js/blog/a{ slug: 'a' }app/blog/[slug]/page.js/blog/b{ slug: 'b' }app/blog/[slug]/page.js/blog/c{ slug: 'c' }
See the generateStaticParams() page to learn how to generate the params for the segment.
Good to know: Dynamic Segments are equivalent to Dynamic Routes in the pages directory.
Generating Static Params
The generateStaticParams function can be used in combination with dynamic route segments to statically generate routes at build time instead of on-demand at request time.
app/blog/[slug]/page.tsx export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())

  return posts.map((post) => ({
    slug: post.slug,


return posts.map((post) => ({
    slug: post.slug,
  }))
}
The primary benefit of the generateStaticParams function is its smart retrieval of data. If content is fetched within the generateStaticParams function using a fetch request, the requests are automatically deduplicated. This means a fetch request with the same arguments across multiple generateStaticParams, Layouts, and Pages will only be made once, which decreases build times.
Use the migration guide if you are migrating from the pages directory.
See generateStaticParams server function documentation for more information and advanced use cases.
Catch-all Segments
Dynamic Segments can be extended to catch-all subsequent segments by adding an ellipsis inside the brackets [...folderName].
For example, app/shop/[...slug]/page.js will match /shop/clothes, but also /shop/clothes/tops, /shop/clothes/tops/t-shirts, and so on.


RouteExample URLparamsapp/shop/[...slug]/page.js/shop/a{ slug: ['a'] }app/shop/[...slug]/page.js/shop/a/b{ slug: ['a', 'b'] }app/shop/[...slug]/page.js/shop/a/b/c{ slug: ['a', 'b', 'c'] }
Optional Catch-all Segments
Catch-all Segments can be made optional by including the parameter in double square brackets: [[...folderName]].
For example, app/shop/[[...slug]]/page.js will also match /shop, in addition to /shop/clothes, /shop/clothes/tops, /shop/clothes/tops/t-shirts.
The difference between catch-all and optional catch-all segments is that with optional, the route without the parameter is also matched (/shop in the example above).


RouteExample URLparamsapp/shop/[[...slug]]/page.js/shop{}app/shop/[[...slug]]/page.js/shop/a{ slug: ['a'] }app/shop/[[...slug]]/page.js/shop/a/b{ slug: ['a', 'b'] }app/shop/[[...slug]]/page.js/shop/a/b/c{ slug: ['a', 'b', 'c'] }
TypeScript
When using TypeScript, you can add types for params depending on your configured route segment.
app/blog/[slug]/page.tsx export default function Page({ params }: { params: { slug: string } }) {
  return
My Page

}
Routeparams Type Definitionapp/blog/[slug]/page.js{ slug: string }app/shop/[...slug]/page.js{ slug: string[] }app/[categoryId]/[itemId]/page.js{ categoryId: string, itemId: string }


Good to know: This may be done automatically by the TypeScript plugin in the future.


Loading UI and StreamingThe special file loading.js helps you create meaningful Loading UI with React Suspense. With this convention, you can show an instant loading state from the server while the content of a route segment loads. The new content is automatically swapped in once rendering is complete.
Instant Loading States
An instant loading state is fallback UI that is shown immediately upon navigation. You can pre-render loading indicators such as skeletons and spinners, or a small but meaningful part of future screens such as a cover photo, title, etc. This helps users understand the app is responding and provides a better user experience.
Create a loading state by adding a loading.js file inside a folder.
app/dashboard/loading.tsx export default function Loading() {
  // You can add any UI inside Loading, including a Skeleton.
  return <LoadingSkeleton />
}


return <LoadingSkeleton />
}
In the same folder, loading.js will be nested inside layout.js. It will automatically wrap the page.js file and any children below in a <Suspense> boundary.
Good to know:
Navigation is immediate, even with server-centric routing.
Navigation is interruptible, meaning changing routes does not need to wait for the content of the route to fully load before navigating to another route.
Shared layouts remain interactive while new route segments load.
Recommendation: Use the loading.js convention for route segments (layouts and pages) as Next.js optimizes this functionality.
Streaming with Suspense
In addition to loading.js, you can also manually create Suspense Boundaries for your own UI components. The App Router supports streaming with Suspense for both Node.js and Edge runtimes.
What is Streaming?


What is Streaming?
To learn how Streaming works in React and Next.js, it's helpful to understand Server-Side Rendering (SSR) and its limitations.
With SSR, there's a series of steps that need to be completed before a user can see and interact with a page:
First, all data for a given page is fetched on the server.
The server then renders the HTML for the page.
The HTML, CSS, and JavaScript for the page are sent to the client.
A non-interactive user interface is shown using the generated HTML, and CSS.
Finally, React hydrates the user interface to make it interactive.
These steps are sequential and blocking, meaning the server can only render the HTML for a page once all the data has been fetched. And, on the client, React can only hydrate the UI once the code for all components in the page has been downloaded.


SSR with React and Next.js helps improve the perceived loading performance by showing a non-interactive page to the user as soon as possible.
However, it can still be slow as all data fetching on server needs to be completed before the page can be shown to the user.
Streaming allows you to break down the page's HTML into smaller chunks and progressively send those chunks from the server to the client.
This enables parts of the page to be displayed sooner, without waiting for all the data to load before any UI can be rendered.
Streaming works well with React's component model because each component can be considered a chunk. Components that have higher priority (e.g. product information) or that don't rely on data can be sent first (e.g. layout), and React can start hydration earlier. Components that have lower priority (e.g. reviews, related products) can be sent in the same server request after their data has been fetched.


Streaming is particularly beneficial when you want to prevent long data requests from blocking the page from rendering as it can reduce the Time To First Byte (TTFB) and First Contentful Paint (FCP). It also helps improve Time to Interactive (TTI), especially on slower devices.
Example
<Suspense> works by wrapping a component that performs an asynchronous action (e.g. fetch data), showing fallback UI (e.g. skeleton, spinner) while it's happening, and then swapping in your component once the action completes.
app/dashboard/page.tsx import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (

      <Suspense fallback={
Loading feed...
}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={
Loading weather...
}>
        <Weather />


<Suspense fallback={
Loading weather...
}>
        <Weather />
      </Suspense>

  )
}
By using Suspense, you get the benefits of:
Streaming Server Rendering - Progressively rendering HTML from the server to the client.
Selective Hydration - React prioritizes what components to make interactive first based on user interaction.
For more Suspense examples and use cases, please see the React Documentation.
SEO
Next.js will wait for data fetching inside generateMetadata to complete before streaming UI to the client. This guarantees the first part of a streamed response includes  tags.
Since streaming is server-rendered, it does not impact SEO. You can use the Mobile Friendly Test tool from Google to see how your page appears to Google's web crawlers and view the serialized HTML (source).


Error HandlingThe error.js file convention allows you to gracefully handle unexpected runtime errors in nested routes.
Automatically wrap a route segment and its nested children in a React Error Boundary.
Create error UI tailored to specific segments using the file-system hierarchy to adjust granularity.
Isolate errors to affected segments while keeping the rest of the application functional.
Add functionality to attempt to recover from an error without a full page reload.
Create error UI by adding an error.js file inside a route segment and exporting a React component:
app/dashboard/error.tsx 'use client' // Error components must be Client Components

import { useEffect } from 'react'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  useEffect(() => {
    // Log the error to an error reporting service
    console.error(error)
  }, [error])


console.error(error)
  }, [error])

  return (

Something went wrong!

      <button
        onClick={
          // Attempt to recover by trying to re-render the segment
          () => reset()
        }
      >
        Try again
      </button>

  )
}
How error.js Works
error.js automatically creates an React Error Boundary that wraps a nested child segment or page.js component.
The React component exported from the error.js file is used as the fallback component.
If an error is thrown within the error boundary, the error is contained, and the fallback component is rendered.
When the fallback error component is active, layouts above the error boundary maintain their state and remain interactive, and the error component can display functionality to recover from the error.
Recovering From Errors


Recovering From Errors
The cause of an error can sometimes be temporary. In these cases, simply trying again might resolve the issue.
An error component can use the reset() function to prompt the user to attempt to recover from the error. When executed, the function will try to re-render the Error boundary's contents. If successful, the fallback error component is replaced with the result of the re-render.
app/dashboard/error.tsx 'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (

Something went wrong!

      <button onClick={() => reset()}>Try again</button>

  )
}
Nested Routes
React components created through special files are rendered in a specific nested hierarchy.


}
Nested Routes
React components created through special files are rendered in a specific nested hierarchy.
For example, a nested route with two segments that both include layout.js and error.js files are rendered in the following simplified component hierarchy:
The nested component hierarchy has implications for the behavior of error.js files across a nested route:
Errors bubble up to the nearest parent error boundary. This means an error.js file will handle errors for all its nested child segments. More or less granular error UI can be achieved by placing error.js files at different levels in the nested folders of a route.
An error.js boundary will not handle errors thrown in a layout.js component in the same segment because the error boundary is nested inside that layouts component.
Handling Errors in Layouts


Handling Errors in Layouts
error.js boundaries do not catch errors thrown in layout.js or template.js components of the same segment. This intentional hierarchy keeps important UI that is shared between sibling routes (such as navigation) visible and functional when an error occurs.
To handle errors within a specific layout or template, place an error.js file in the layouts parent segment.
To handle errors within the root layout or template, use a variation of error.js called global-error.js.
Handling Errors in Root Layouts
The root app/error.js boundary does not catch errors thrown in the root app/layout.js or app/template.js component.
To specifically handle errors in these root components, use a variation of error.js called app/global-error.js located in the root app directory.


Unlike the root error.js, the global-error.js error boundary wraps the entire application, and its fallback component replaces the root layout when active. Because of this, it is important to note that global-error.js must define its own <html> and <body> tags.
global-error.js is the least granular error UI and can be considered "catch-all" error handling for the whole application. It is unlikely to be triggered often as root components are typically less dynamic, and other error.js boundaries will catch most errors.
Even if a global-error.js is defined, it is still recommended to define a root error.js whose fallback component will be rendered within the root layout, which includes globally shared UI and branding.
app/global-error.tsx 'use client'

export default function GlobalError({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <html>


reset: () => void
}) {
  return (

Something went wrong!

        <button onClick={() => reset()}>Try again</button>

  )
}
Handling Server Errors
If an error is thrown inside a Server Component, Next.js will forward an Error object (stripped of sensitive error information in production) to the nearest error.js file as the error prop.
Securing Sensitive Error Information
During production, the Error object forwarded to the client only includes a generic message and digest property.
This is a security precaution to avoid leaking potentially sensitive details included in the error to the client.
The message property contains a generic message about the error and the digest property contains an automatically generated hash of the error that can be used to match the corresponding error in server-side logs.


During development, the Error object forwarded to the client will be serialized and include the message of the original error for easier debugging.


Parallel RoutesParallel Routing allows you to simultaneously or conditionally render one or more pages in the same layout. For highly dynamic sections of an app, such as dashboards and feeds on social sites, Parallel Routing can be used to implement complex routing patterns.
For example, you can simultaneously render the team and analytics pages.
Parallel Routing allows you to define independent error and loading states for each route as they're being streamed in independently.
Parallel Routing also allows you to conditionally render a slot based on certain conditions, such as authentication state. This enables fully separated code on the same URL.
Convention
Parallel routes are created using named slots. Slots are defined with the @folder convention, and are passed to the same-level layout as props.
Slots are not route segments and do not affect the URL structure. The file path /@team/members would be accessible at /members.
For example, the following file structure defines two explicit slots: @analytics and @team.


For example, the following file structure defines two explicit slots: @analytics and @team.
The folder structure above means that the component in app/layout.js now accepts the @analytics and @team slots props, and can render them in parallel alongside the children prop:
app/layout.tsx export default function Layout(props: {
  children: React.ReactNode
  analytics: React.ReactNode
  team: React.ReactNode
}) {
  return (
    <>
      {props.children}
      {props.team}
      {props.analytics}
    </>
  )
}
Good to know: The children prop is an implicit slot that does not need to be mapped to a folder. This means app/page.js is equivalent to app/@children/page.js.
Unmatched Routes
By default, the content rendered within a slot will match the current URL.


Unmatched Routes
By default, the content rendered within a slot will match the current URL.
In the case of an unmatched slot, the content that Next.js renders differs based on the routing technique and folder structure.
default.js
You can define a default.js file to render as a fallback when Next.js cannot recover a slot's active state based on the current URL.
Consider the following folder structure. The @team slot has a settings directory, but @analytics does not.
If you were to navigate from the root / to /settings, the content that gets rendered is different based on the type of navigation and the availability of the default.js file.
With @analytics/default.jsWithout @analytics/default.jsSoft Navigation@team/settings/page.js and @analytics/page.js@team/settings/page.js and @analytics/page.jsHard Navigation@team/settings/page.js and @analytics/default.js404
Soft Navigation


Soft Navigation
On a soft navigation - Next.js will render the slot's previously active state, even if it doesn't match the current URL.
Hard Navigation
On a hard navigation - a navigation that requires a full page reload - Next.js will first try to render the unmatched slot's default.js file. If that's not available, a 404 gets rendered.
The 404 for unmatched routes helps ensure that you don't accidentally render a route that shouldn't be parallel rendered.
useSelectedLayoutSegment(s)
Both useSelectedLayoutSegment and useSelectedLayoutSegments accept a parallelRoutesKey, which allows you read the active route segment within that slot.
app/layout.tsx 'use client'

import { useSelectedLayoutSegment } from 'next/navigation'

export default async function Layout(props: {
  //...
  authModal: React.ReactNode
}) {
  const loginSegments = useSelectedLayoutSegment('authModal')


}) {
  const loginSegments = useSelectedLayoutSegment('authModal')
  // ...
}
When a user navigates to @authModal/login, or /login in the URL bar, loginSegments will be equal to the string "login".
Examples
Modals
Parallel Routing can be used to render modals.
The @authModal slot renders a <Modal> component that can be shown by navigating to a matching route, for example /login.
app/layout.tsx export default async function Layout(props: {
  // ...
  authModal: React.ReactNode
}) {
  return (
    <>
      {/* ... */}
      {props.authModal}
    </>
  )
}
app/@authModal/login/page.tsx import { Modal } from 'components/modal'

export default function Login() {
  return (
    <Modal>

Login


return (
    <Modal>

Login

      {/* ... */}
    </Modal>
  )
}
To ensure that the contents of the modal don't get rendered when it's not active, you can create a default.js file that returns null.
app/@authModal/default.tsx export default function Default() {
  return null
}
Dismissing a modal
If a modal was initiated through client navigation, e.g. by using <Link href="/login">, you can dismiss the modal by calling router.back() or by using a Link component.
app/@authModal/login/page.tsx 'use client'
import { useRouter } from 'next/navigation'
import { Modal } from 'components/modal'

export default async function Login() {
  const router = useRouter()
  return (
    <Modal>


const router = useRouter()
  return (
    <Modal>
       router.back()}>Close modal

Login

      ...
    </Modal>
  )
}
More information on modals is covered in the Intercepting Routes section.
If you want to navigate elsewhere and dismiss a modal, you can also use a catch-all route.
app/@authModal/[...catchAll]/page.tsx export default function CatchAll() {
  return null
}
Catch-all routes take precedence over default.js.
Conditional Routes
Parallel Routes can be used to implement conditional routing. For example, you can render a @dashboard or @login route depending on the authentication state.
app/layout.tsx import { getUser } from '@/lib/auth'

export default function Layout({
  dashboard,
  login,
}: {
  dashboard: React.ReactNode


dashboard,
  login,
}: {
  dashboard: React.ReactNode
  login: React.ReactNode
}) {
  const isLoggedIn = getUser()
  return isLoggedIn ? dashboard : login
}


Intercepting RoutesIntercepting routes allows you to load a route within the current layout while keeping the context for the current page. This routing paradigm can be useful when you want to "intercept" a certain route to show a different route.
For example, when clicking on a photo from within a feed, a modal overlaying the feed should show up with the photo. In this case, Next.js intercepts the /feed route and "masks" this URL to show /photo/123 instead.
However, when navigating to the photo directly by for example when clicking a shareable URL or by refreshing the page, the entire photo page should render instead of the modal. No route interception should occur.
Convention
Intercepting routes can be defined with the (..) convention, which is similar to relative path convention ../ but for segments.
You can use:
(.) to match segments on the same level
(..) to match segments one level above


(.) to match segments on the same level
(..) to match segments one level above
(..)(..) to match segments two levels above
(...) to match segments from the root app directory
For example, you can intercept the photo segment from within the feed segment by creating a (..)photo directory.
Note that the (..) convention is based on route segments, not the file-system.
Examples
Modals
Intercepting Routes can be used together with Parallel Routes to create modals.
Using this pattern to create modals overcomes some common challenges when working with modals, by allowing you to:
Make the modal content shareable through a URL
Preserve context when the page is refreshed, instead of closing the modal
Close the modal on backwards navigation rather than going to the previous route
Reopen the modal on forwards navigation


Reopen the modal on forwards navigation
In the above example, the path to the photo segment can use the (..) matcher since @modal is a slot and not a segment. This means that the photo route is only one segment level higher, despite being two file-system levels higher.
Other examples could include opening a login modal in a top navbar while also having a dedicated /login page, or opening a shopping cart in a side modal.
View an example of modals with Intercepted and Parallel Routes.


Route HandlersRoute Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.
Good to know: Route Handlers are only available inside the app directory. They are the equivalent of API Routes inside the pages directory meaning you do not need to use API Routes and Route Handlers together.
Convention
Route Handlers are defined in a route.js|ts file inside the app directory:
app/api/route.ts export async function GET(request: Request) {}
Route Handlers can be nested inside the app directory, similar to page.js and layout.js. But there cannot be a route.js file at the same route segment level as page.js.
Supported HTTP Methods
The following HTTP methods are supported: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. If an unsupported method is called, Next.js will return a 405 Method Not Allowed response.
Extended NextRequest and NextResponse APIs


Extended NextRequest and NextResponse APIs
In addition to supporting native Request and Response. Next.js extends them with
NextRequest and NextResponse to provide convenient helpers for advanced use cases.
Behavior
Static Route Handlers
Route Handlers are statically evaluated by default when using the GET method with the Response object.
app/items/route.ts import { NextResponse } from 'next/server'

export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const data = await res.json()

  return NextResponse.json({ data })
}
TypeScript Warning: Although Response.json() is valid, native TypeScript types currently shows an error, you can use NextResponse.json() for typed responses instead.
Dynamic Route Handlers


Dynamic Route Handlers
Route handlers are evaluated dynamically when:
Using the Request object with the GET method.
Using any of the other HTTP methods.
Using Dynamic Functions like cookies and headers.
The Segment Config Options manually specifies dynamic mode.
For example:
app/products/api/route.ts import { NextResponse } from 'next/server'

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const id = searchParams.get('id')
  const res = await fetch(`https://data.mongodb-api.com/product/${id}`, {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const product = await res.json()

  return NextResponse.json({ product })
}
Similarly, the POST method will cause the Route Handler to be evaluated dynamically.


}
Similarly, the POST method will cause the Route Handler to be evaluated dynamically.
app/items/route.ts import { NextResponse } from 'next/server'

export async function POST() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
    body: JSON.stringify({ time: new Date().toISOString() }),
  })

  const data = await res.json()

  return NextResponse.json(data)
}
Good to know: Like API Routes, Route Handlers can be used for cases like handling form submissions. A new abstraction for handling forms and mutations that integrates deeply with React is being worked on.
Route Resolution
You can consider a route the lowest level routing primitive.


Route Resolution
You can consider a route the lowest level routing primitive.
They do not participate in layouts or client-side navigations like page.
There cannot be a route.js file at the same route as page.js.
PageRouteResultapp/page.jsapp/route.js Conflictapp/page.jsapp/api/route.js Validapp/[user]/page.jsapp/api/route.js Valid
Each route.js or page.js file takes over all HTTP verbs for that route.
app/page.js export default function Page() {
  return
Hello, Next.js!

}

// ❌ Conflict
// `app/route.js`
export async function POST(request) {}
Examples
The following examples show how to combine Route Handlers with other Next.js APIs and features.
Revalidating Static Data
You can revalidate static data fetches using the next.revalidate option:


You can revalidate static data fetches using the next.revalidate option:
app/items/route.ts import { NextResponse } from 'next/server'

export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    next: { revalidate: 60 }, // Revalidate every 60 seconds
  })
  const data = await res.json()

  return NextResponse.json(data)
}
Alternatively, you can use the revalidate segment config option:
 export const revalidate = 60
Dynamic Functions
Route Handlers can be used with dynamic functions from Next.js, like cookies and headers.
Cookies
You can read cookies with cookies from next/headers. This server function can be called directly in a Route Handler, or nested inside of another function.


This cookies instance is read-only. To set cookies, you need to return a new Response using the Set-Cookie header.
app/api/route.ts import { cookies } from 'next/headers'

export async function GET(request: Request) {
  const cookieStore = cookies()
  const token = cookieStore.get('token')

  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { 'Set-Cookie': `token=${token.value}` },
  })
}
Alternatively, you can use abstractions on top of the underlying Web APIs to read cookies (NextRequest):
app/api/route.ts import { type NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const token = request.cookies.get('token')
}
Headers


const token = request.cookies.get('token')
}
Headers
You can read headers with headers from next/headers. This server function can be called directly in a Route Handler, or nested inside of another function.
This headers instance is read-only. To set headers, you need to return a new Response with new headers.
app/api/route.ts import { headers } from 'next/headers'

export async function GET(request: Request) {
  const headersList = headers()
  const referer = headersList.get('referer')

  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { referer: referer },
  })
}
Alternatively, you can use abstractions on top of the underlying Web APIs to read headers (NextRequest):
app/api/route.ts import { type NextRequest } from 'next/server'


app/api/route.ts import { type NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const requestHeaders = new Headers(request.headers)
}
Redirects
app/api/route.ts import { redirect } from 'next/navigation'

export async function GET(request: Request) {
  redirect('https://nextjs.org/')
}
Dynamic Route Segments
We recommend reading the Defining Routes page before continuing.
Route Handlers can use Dynamic Segments to create request handlers from dynamic data.
app/items/[slug]/route.ts export async function GET(
  request: Request,
  { params }: { params: { slug: string } }
) {
  const slug = params.slug // 'a', 'b', or 'c'
}


const slug = params.slug // 'a', 'b', or 'c'
}
RouteExample URLparamsapp/items/[slug]/route.js/items/a{ slug: 'a' }app/items/[slug]/route.js/items/b{ slug: 'b' }app/items/[slug]/route.js/items/c{ slug: 'c' }
Streaming
Streaming is commonly used in combination with Large Language Models (LLMs), such an OpenAI, for AI-generated content. Learn more about the AI SDK.
app/api/completion/route.ts import { Configuration, OpenAIApi } from 'openai-edge'
import { OpenAIStream, StreamingTextResponse } from 'ai'

const config = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
})
const openai = new OpenAIApi(config)

export const runtime = 'edge'


export const runtime = 'edge'

export async function POST(req: Request) {
  const { prompt } = await req.json()
  const response = await openai.createCompletion({
    model: 'text-davinci-003',
    stream: true,
    temperature: 0.6,
    prompt: 'What is Next.js?',
  })

  const stream = OpenAIStream(response)
  return new StreamingTextResponse(stream)
}
These abstractions use the Web APIs to create a stream. You can also use the underlying Web APIs directly.
app/api/route.ts // https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream#convert_async_iterator_to_stream
function iteratorToStream(iterator: any) {
  return new ReadableStream({
    async pull(controller) {
      const { value, done } = await iterator.next()


const { value, done } = await iterator.next()

      if (done) {
        controller.close()
      } else {
        controller.enqueue(value)
      }
    },
  })
}

function sleep(time: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, time)
  })
}

const encoder = new TextEncoder()

async function* makeIterator() {
  yield encoder.encode('
One
')
  await sleep(200)
  yield encoder.encode('
Two
')
  await sleep(200)
  yield encoder.encode('
Three
')
}

export async function GET() {
  const iterator = makeIterator()
  const stream = iteratorToStream(iterator)

  return new Response(stream)
}
Request Body


return new Response(stream)
}
Request Body
You can read the Request body using the standard Web API methods:
app/items/route.ts import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const res = await request.json()
  return NextResponse.json({ res })
}
Request Body FormData
You can read the FormData using the the request.formData() function:
app/items/route.ts import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const formData = await request.formData()
  const name = formData.get('name')
  const email = formData.get('email')
  return NextResponse.json({ name, email })
}
Since formData data are all strings, you may want to use zod-form-data to validate the request and retrieve data in the format you prefer (e.g. number).


CORS
You can set CORS headers on a Response using the standard Web API methods:
app/api/route.ts export async function GET(request: Request) {
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  })
}
Edge and Node.js Runtimes
Route Handlers have an isomorphic Web API to support both Edge and Node.js runtimes seamlessly, including support for streaming. Since Route Handlers use the same route segment configuration as Pages and Layouts, they support long-awaited features like general-purpose statically regenerated Route Handlers.
You can use the runtime segment config option to specify the runtime:
 export const runtime = 'edge' // 'nodejs' is the default


export const runtime = 'edge' // 'nodejs' is the default
Non-UI Responses
You can use Route Handlers to return non-UI content. Note that sitemap.xml, robots.txt, app icons, and open graph images all have built-in support.
app/rss.xml/route.ts export async function GET() {
  return new Response(`<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">

<channel>
  <title>Next.js Documentation</title>
  <link>https://nextjs.org/docs</link>
  <description>The React Framework for the Web</description>
</channel>

</rss>`)
}
Segment Config Options
Route Handlers use the same route segment configuration as pages and layouts.
app/items/route.ts export const dynamic = 'auto'
export const dynamicParams = true


app/items/route.ts export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
See the API reference for more details.


Middleware
Middleware allows you to run code before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly.
Middleware runs before cached content and routes are matched. See Matching Paths for more details.
Convention
Use the file middleware.ts (or .js) in the root of your project to define Middleware. For example, at the same level as pages or app, or inside src if applicable.
Example
middleware.ts import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}

// See "Matching Paths" below to learn more
export const config = {


// See "Matching Paths" below to learn more
export const config = {
  matcher: '/about/:path*',
}
Matching Paths
Middleware will be invoked for every route in your project. The following is the execution order:
headers from next.config.js
redirects from next.config.js
Middleware (rewrites, redirects, etc.)
beforeFiles (rewrites) from next.config.js
Filesystem routes (public/, _next/static/, pages/, app/, etc.)
afterFiles (rewrites) from next.config.js
Dynamic Routes (/blog/[slug])
fallback (rewrites) from next.config.js
There are two ways to define which paths Middleware will run on:
Custom matcher config
Conditional statements
Matcher
matcher allows you to filter Middleware to run on specific paths.
middleware.js export const config = {
  matcher: '/about/:path*',
}


middleware.js export const config = {
  matcher: '/about/:path*',
}
You can match a single path or multiple paths with an array syntax:
middleware.js export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
}
The matcher config allows full regex so matching like negative lookaheads or character matching is supported. An example of a negative lookahead to match all except specific paths can be seen here:
middleware.js export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
}


],
}
Good to know: The matcher values need to be constants so they can be statically analyzed at build-time. Dynamic values such as variables will be ignored.
Configured matchers:
MUST start with /
Can include named parameters: /about/:path matches /about/a and /about/b but not /about/a/c
Can have modifiers on named parameters (starting with :): /about/:path* matches /about/a/b/c because * is zero or more. ? is zero or one and + one or more
Can use regular expression enclosed in parenthesis: /about/(.*) is the same as /about/:path*
Read more details on path-to-regexp documentation.
Good to know: For backward compatibility, Next.js always considers /public as /public/index. Therefore, a matcher of /public/:path will match.
Conditional Statements
middleware.ts import { NextResponse } from 'next/server'


Conditional Statements
middleware.ts import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/about')) {
    return NextResponse.rewrite(new URL('/about-2', request.url))
  }

  if (request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.rewrite(new URL('/dashboard/user', request.url))
  }
}
NextResponse
The NextResponse API allows you to:
redirect the incoming request to a different URL
rewrite the response by displaying a given URL
Set request headers for API Routes, getServerSideProps, and rewrite destinations
Set response cookies
Set response headers
To produce a response from Middleware, you can:
rewrite to a route (Page or Route Handler) that produces a response


rewrite to a route (Page or Route Handler) that produces a response
return a NextResponse directly. See Producing a Response
Using Cookies
Cookies are regular headers. On a Request, they are stored in the Cookie header. On a Response they are in the Set-Cookie header. Next.js provides a convenient way to access and manipulate these cookies through the cookies extension on NextRequest and NextResponse.
For incoming requests, cookies comes with the following methods: get, getAll, set, and delete cookies. You can check for the existence of a cookie with has or remove all cookies with clear.
For outgoing responses, cookies have the following methods get, getAll, set, and delete.
middleware.ts import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  // Assume a "Cookie:nextjs=fast" header to be present on the incoming request


// Getting cookies from the request using the `RequestCookies` API
  let cookie = request.cookies.get('nextjs')
  console.log(cookie) // => { name: 'nextjs', value: 'fast', Path: '/' }
  const allCookies = request.cookies.getAll()
  console.log(allCookies) // => [{ name: 'nextjs', value: 'fast' }]

  request.cookies.has('nextjs') // => true
  request.cookies.delete('nextjs')
  request.cookies.has('nextjs') // => false

  // Setting cookies on the response using the `ResponseCookies` API
  const response = NextResponse.next()
  response.cookies.set('vercel', 'fast')
  response.cookies.set({
    name: 'vercel',
    value: 'fast',
    path: '/',
  })
  cookie = response.cookies.get('vercel')


path: '/',
  })
  cookie = response.cookies.get('vercel')
  console.log(cookie) // => { name: 'vercel', value: 'fast', Path: '/' }
  // The outgoing response will have a `Set-Cookie:vercel=fast;path=/test` header.

  return response
}
Setting Headers
You can set request and response headers using the NextResponse API (setting request headers is available since Next.js v13.0.0).
middleware.ts import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-hello-from-middleware1`
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-hello-from-middleware1', 'hello')


requestHeaders.set('x-hello-from-middleware1', 'hello')

  // You can also set request headers in NextResponse.rewrite
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  })

  // Set a new response header `x-hello-from-middleware2`
  response.headers.set('x-hello-from-middleware2', 'hello')
  return response
}
Good to know: Avoid setting large headers as it might cause 431 Request Header Fields Too Large error depending on your backend web server configuration.
Producing a Response
You can respond from Middleware directly by returning a Response or NextResponse instance. (This is available since Next.js v13.1.0)
middleware.ts import { NextRequest, NextResponse } from 'next/server'
import { isAuthenticated } from '@lib/auth'


import { isAuthenticated } from '@lib/auth'

// Limit the middleware to paths starting with `/api/`
export const config = {
  matcher: '/api/:function*',
}

export function middleware(request: NextRequest) {
  // Call our authentication function to check the request
  if (!isAuthenticated(request)) {
    // Respond with JSON indicating an error message
    return new NextResponse(
      JSON.stringify({ success: false, message: 'authentication failed' }),
      { status: 401, headers: { 'content-type': 'application/json' } }
    )
  }
}
Advanced Middleware Flags
In v13.1 of Next.js two additional flags were introduced for middleware, skipMiddlewareUrlNormalize and skipTrailingSlashRedirect to handle advanced use cases.


skipTrailingSlashRedirect allows disabling Next.js default redirects for adding or removing trailing slashes allowing custom handling inside middleware which can allow maintaining the trailing slash for some paths but not others allowing easier incremental migrations.
next.config.js module.exports = {
  skipTrailingSlashRedirect: true,
}
middleware.js const legacyPrefixes = ['/docs', '/blog']

export default async function middleware(req) {
  const { pathname } = req.nextUrl

  if (legacyPrefixes.some((prefix) => pathname.startsWith(prefix))) {
    return NextResponse.next()
  }

  // apply trailing slash handling
  if (
    !pathname.endsWith('/') &&
    !pathname.match(/((?!\.well-known(?:\/.*)?)(?:[^/]+\/)*[^/]+\.\w+)/)
  ) {
    req.nextUrl.pathname += '/'
    return NextResponse.redirect(req.nextUrl)
  }


return NextResponse.redirect(req.nextUrl)
  }
}
skipMiddlewareUrlNormalize allows disabling the URL normalizing Next.js does to make handling direct visits and client-transitions the same. There are some advanced cases where you need full control using the original URL which this unlocks.
next.config.js module.exports = {
  skipMiddlewareUrlNormalize: true,
}
middleware.js export default async function middleware(req) {
  const { pathname } = req.nextUrl

  // GET /_next/data/build-id/hello.json

  console.log(pathname)
  // with the flag this now /_next/data/build-id/hello.json
  // without the flag this would be normalized to /hello
}
Version History


// without the flag this would be normalized to /hello
}
Version History
VersionChangesv13.1.0Advanced Middleware flags addedv13.0.0Middleware can modify request headers, response headers, and send responsesv12.2.0Middleware is stable, please see the upgrade guidev12.0.9Enforce absolute URLs in Edge Runtime (PR)v12.0.0Middleware (Beta) added


Project Organization and File ColocationApart from routing folder and file conventions, Next.js is unopinionated about how you organize and colocate your project files.
This page shares default behavior and features you can use to organize your project.
Safe colocation by default
Project organization features
Project organization strategies
Safe colocation by default
In the app directory, nested folder hierarchy defines route structure.
Each folder represents a route segment that is mapped to a corresponding segment in a URL path.
However, even though route structure is defined through folders, a route is not publicly accessible until a page.js or route.js file is added to a route segment.
And, even when a route is made publicly accessible, only the content returned by page.js or route.js is sent to the client.
This means that project files can be safely colocated inside route segments in the app directory without accidentally being routable.
Good to know:


Good to know:
This is different from the pages directory, where any file in pages is considered a route.
While you can colocate your project files in app you don't have to. If you prefer, you can keep them outside the app directory.
Project organization features
Next.js provides several features to help you organize your project.
Private Folders
Private folders can be created by prefixing a folder with an underscore: _folderName
This indicates the folder is a private implementation detail and should not be considered by the routing system, thereby opting the folder and all its subfolders out of routing.
Since files in the app directory can be safely colocated by default, private folders are not required for colocation. However, they can be useful for:
Separating UI logic from routing logic.
Consistently organizing internal files across a project and the Next.js ecosystem.
Sorting and grouping files in code editors.


Sorting and grouping files in code editors.
Avoiding potential naming conflicts with future Next.js file conventions.
Good to know
While not a framework convention, you might also consider marking files outside private folders as "private" using the same underscore pattern.
You can create URL segments that start with an underscore by prefixing the folder name with %5F (the URL-encoded form of an underscore): %5FfolderName.
If you don't use private folders, it would be helpful to know Next.js special file conventions to prevent unexpected naming conflicts.
Route Groups
Route groups can be created by wrapping a folder in parenthesis: (folderName)
This indicates the folder is for organizational purposes and should not be included in the route's URL path.
Route groups are useful for:
Organizing routes into groups e.g. by site section, intent, or team.
Enabling nested layouts in the same route segment level:


Enabling nested layouts in the same route segment level:
Creating multiple nested layouts in the same segment, including multiple root layouts
Adding a layout to a subset of routes in a common segment
src Directory
Next.js supports storing application code (including app) inside an optional src directory. This separates application code from project configuration files which mostly live in the root of a project.
Module Path Aliases
Next.js supports Module Path Aliases which make it easier to read and maintain imports across deeply nested project files.
app/dashboard/settings/analytics/page.js // before
import { Button } from '../../../components/button'

// after
import { Button } from '@/components/button'
Project organization strategies
There is no "right" or "wrong" way when it comes to organizing your own files and folders in a Next.js project.


The following section lists a very high-level overview of common strategies. The simplest takeaway is to choose a strategy that works for you and your team and be consistent across the project.
Good to know: In our examples below, we're using components and lib folders as generalized placeholders, their naming has no special framework significance and your projects might use other folders like ui, utils, hooks, styles, etc.
Store project files outside of app
This strategy stores all application code in shared folders in the root of your project and keeps the app directory purely for routing purposes.
Store project files in top-level folders inside of app
This strategy stores all application code in shared folders in the root of the app directory.
Split project files by feature or route
This strategy stores globally shared application code in the root app directory and splits more specific application code into the route segments that use them.


InternationalizationNext.js enables you to configure the routing and rendering of content to support multiple languages. Making your site adaptive to different locales includes translated content (localization) and internationalized routes.
Terminology
Locale: An identifier for a set of language and formatting preferences. This usually includes the preferred language of the user and possibly their geographic region.
en-US: English as spoken in the United States
nl-NL: Dutch as spoken in the Netherlands
nl: Dutch, no specific region
Routing Overview
It’s recommended to use the user’s language preferences in the browser to select which locale to use. Changing your preferred language will modify the incoming Accept-Language header to your application.
For example, using the following libraries, you can look at an incoming Request to determine which locale to select, based on the Headers, locales you plan to support, and the default locale.
middleware.js import { match } from '@formatjs/intl-localematcher'


middleware.js import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'

let headers = { 'accept-language': 'en-US,en;q=0.5' }
let languages = new Negotiator({ headers }).languages()
let locales = ['en-US', 'nl-NL', 'nl']
let defaultLocale = 'en-US'

match(languages, locales, defaultLocale) // -> 'en-US'
Routing can be internationalized by either the sub-path (/fr/products) or domain (my-site.fr/products). With this information, you can now redirect the user based on the locale inside Middleware.
middleware.js import { NextResponse } from 'next/server'

let locales = ['en-US', 'nl-NL', 'nl']

// Get the preferred locale, similar to above or using a library
function getLocale(request) { ... }


function getLocale(request) { ... }

export function middleware(request) {
  // Check if there is any supported locale in the pathname
  const pathname = request.nextUrl.pathname
  const pathnameIsMissingLocale = locales.every(
    (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
  )

  // Redirect if there is no locale
  if (pathnameIsMissingLocale) {
    const locale = getLocale(request)

    // e.g. incoming request is /products
    // The new URL is now /en-US/products
    return NextResponse.redirect(
      new URL(`/${locale}/${pathname}`, request.url)
    )
  }
}

export const config = {
  matcher: [
    // Skip all internal paths (_next)
    '/((?!_next).*)',


// Skip all internal paths (_next)
    '/((?!_next).*)',
    // Optional: only run on root (/) URL
    // '/'
  ],
}
Finally, ensure all special files inside app/ are nested under app/[lang]. This enables the Next.js router to dynamically handle different locales in the route, and forward the lang parameter to every layout and page. For example:
app/[lang]/page.js // You now have access to the current locale
// e.g. /en-US/products -> `lang` is "en-US"
export default async function Page({ params: { lang } }) {
  return ...
}
The root layout can also be nested in the new folder (e.g. app/[lang]/layout.js).
Localization


Localization
Changing displayed content based on the user’s preferred locale, or localization, is not something specific to Next.js. The patterns described below would work the same with any web application.
Let’s assume we want to support both English and Dutch content inside our application. We might maintain two different “dictionaries”, which are objects that give us a mapping from some key to a localized string. For example:
dictionaries/en.json {
  "products": {
    "cart": "Add to Cart"
  }
}
dictionaries/nl.json {
  "products": {
    "cart": "Toevoegen aan Winkelwagen"
  }
}
We can then create a getDictionary function to load the translations for the requested locale:
app/[lang]/dictionaries.js import 'server-only'

const dictionaries = {


app/[lang]/dictionaries.js import 'server-only'

const dictionaries = {
  en: () => import('./dictionaries/en.json').then((module) => module.default),
  nl: () => import('./dictionaries/nl.json').then((module) => module.default),
}

export const getDictionary = async (locale) => dictionaries[locale]()
Given the currently selected language, we can fetch the dictionary inside of a layout or page.
app/[lang]/page.js import { getDictionary } from './dictionaries'

export default async function Page({ params: { lang } }) {
  const dict = await getDictionary(lang) // en
  return <button>{dict.products.cart}</button> // Add to Cart
}


return <button>{dict.products.cart}</button> // Add to Cart
}
Because all layouts and pages in the app/ directory default to Server Components, we do not need to worry about the size of the translation files affecting our client-side JavaScript bundle size. This code will only run on the server, and only the resulting HTML will be sent to the browser.
Static Generation
To generate static routes for a given set of locales, we can use generateStaticParams with any page or layout. This can be global, for example, in the root layout:
app/[lang]/layout.js export async function generateStaticParams() {
  return [{ lang: 'en-US' }, { lang: 'de' }]
}

export default function Root({ children, params }) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  )
}
Examples


</html>
  )
}
Examples
Minimal i18n routing and translations
next-intl


Static and Dynamic RenderingIn Next.js, a route can be statically or dynamically rendered.
In a static route, components are rendered on the server at build time. The result of the work is cached and reused on subsequent requests.
In a dynamic route, components are rendered on the server at request time.
Static Rendering (Default)
By default, Next.js statically renders routes to improve performance. This means all the rendering work is done ahead of time and can be served from a Content Delivery Network (CDN) geographically closer to the user.
Static Data Fetching (Default)
By default, Next.js will cache the result of fetch() requests that do not specifically opt out of caching behavior. This means that fetch requests that do not set a cache option will use the force-cache option.
If any fetch requests in the route use the revalidate option, the route will be re-rendered statically during revalidation.


To learn more about caching data fetching requests, see the Caching and Revalidating page.
Dynamic Rendering
During static rendering, if a dynamic function or a dynamic fetch() request (no caching) is discovered, Next.js will switch to dynamically rendering the whole route at request time. Any cached data requests can still be re-used during dynamic rendering.
This table summarizes how dynamic functions and caching affect the rendering behavior of a route:
Data FetchingDynamic FunctionsRenderingStatic (Cached)NoStaticStatic (Cached)YesDynamicNot CachedNoDynamicNot CachedYesDynamic
Note how dynamic functions always opt the route into dynamic rendering, regardless of whether the data fetching is cached or not. In other words, static rendering is dependent not only on the data fetching behavior, but also on the dynamic functions used in the route.


Good to know: In the future, Next.js will introduce hybrid server-side rendering where layouts and pages in a route can be independently statically or dynamically rendered, instead of the whole route.
Dynamic Functions
Dynamic functions rely on information that can only be known at request time such as a user's cookies, current requests headers, or the URL's search params. In Next.js, these dynamic functions are:
Using cookies() or headers() in a Server Component will opt the whole route into dynamic rendering at request time.
Using useSearchParams() in Client Components will skip static rendering and instead render all Client Components up to the nearest parent Suspense boundary on the client.
We recommend wrapping the Client Component that uses useSearchParams() in a <Suspense/> boundary. This will allow any Client Components above it to be statically rendered. Example.
Using the searchParams Pages prop will opt the page into dynamic rendering at request time.
Dynamic Data Fetching


Dynamic Data Fetching
Dynamic data fetches are fetch() requests that specifically opt out of caching behavior by setting the cache option to 'no-store' or revalidate to 0.
The caching options for all fetch requests in a layout or page can also be set using the segment config object.
To learn more about Dynamic Data Fetching, see the Data Fetching page.


Edge and Node.js Runtimes
In the context of Next.js, "runtime" refers to the set of libraries, APIs, and general functionality available to your code during execution.
Next.js has two server runtimes where you can render parts of your application code:
Node.js Runtime
Edge Runtime
Each runtime has its own set of APIs. Please refer to the Node.js Docs and Edge Docs for the full list of available APIs. Both runtimes can also support streaming depending on your deployment infrastructure.
By default, the app directory uses the Node.js runtime. However, you can opt into different runtimes (e.g. Edge) on a per-route basis.
Runtime Differences
There are many considerations to make when choosing a runtime. This table shows the major differences at a glance. If you want a more in-depth analysis of the differences, check out the sections below.


NodeServerlessEdgeCold Boot/~250msInstantHTTP StreamingYesYesYesIOAllAllfetchScalability/HighHighestSecurityNormalHighHighLatencyNormalLowLowestnpm PackagesAllAllA smaller subset
Edge Runtime
In Next.js, the lightweight Edge Runtime is a subset of available Node.js APIs.
The Edge Runtime is ideal if you need to deliver dynamic, personalized content at low latency with small, simple functions. The Edge Runtime's speed comes from its minimal use of resources, but that can be limiting in many scenarios.
For example, code executed in the Edge Runtime on Vercel cannot exceed between 1 MB and 4 MB, this limit includes imported packages, fonts and files, and will vary depending on your deployment infrastructure.
Node.js Runtime
Using the Node.js runtime gives you access to all Node.js APIs, and all npm packages that rely on them. However, it's not as fast to start up as routes using the Edge runtime.


Deploying your Next.js application to a Node.js server will require managing, scaling, and configuring your infrastructure. Alternatively, you can consider deploying your Next.js application to a serverless platform like Vercel, which will handle this for you.
Serverless Node.js
Serverless is ideal if you need a scalable solution that can handle more complex computational loads than the Edge Runtime. With Serverless Functions on Vercel, for example, your overall code size is 50MB including imported packages, fonts, and files.
The downside compared to routes using the Edge is that it can take hundreds of milliseconds for Serverless Functions to boot up before they begin processing requests. Depending on the amount of traffic your site receives, this could be a frequent occurrence as the functions are not frequently "warm".
Examples
Segment Runtime Option


Examples
Segment Runtime Option
You can specify a runtime for individual route segments in your Next.js application. To do so, declare a variable called runtime and export it. The variable must be a string, and must have a value of either 'nodejs' or 'edge' runtime.The following example demonstrates a page route segment that exports a runtime with a value of 'edge':app/page.tsx export const runtime = 'edge' // 'nodejs' (default) | 'edge'You can also define runtime on a layout level, which will make all routes under the layout run on the edge runtime:app/layout.tsx export const runtime = 'edge' // 'nodejs' (default) | 'edge'If the segment runtime is not set, the default nodejs runtime will be used. You do not need to use the runtime option if you do not plan to change from the Node.js runtime.


Data FetchingThe Next.js App Router allows you to fetch data directly in your React components by marking the function as async and using await for the Promise.
Data fetching is built on top of the fetch() Web API and React Server Components. When using fetch(), requests are automatically deduped by default.
Next.js extends the fetch options object to allow each request to set its own caching and revalidating.
async and await in Server Components
You can use async and await to fetch data in Server Components.
app/page.tsx async function getData() {
  const res = await fetch('https://api.example.com/...')
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.

  // Recommendation: handle errors
  if (!res.ok) {
    // This will activate the closest `error.js` Error Boundary
    throw new Error('Failed to fetch data')


throw new Error('Failed to fetch data')
  }

  return res.json()
}

export default async function Page() {
  const data = await getData()

  return <main></main>
}
Good to know:
To use an async Server Component with TypeScript, ensure you are using TypeScript 5.1.3 or higher and @types/react 18.2.8 or higher.
Server Component Functions
Next.js provides helpful server functions you may need when fetching data in Server Components:
cookies()
headers()
use in Client Components
use is a new React function that accepts a promise conceptually similar to await. use handles the promise returned by a function in a way that is compatible with components, hooks, and Suspense. Learn more about use in the React RFC.


Wrapping fetch in use is currently not recommended in Client Components and may trigger multiple re-renders. For now, if you need to fetch data in a Client Component, we recommend using a third-party library such as SWR or React Query.
Good to know: We'll be adding more examples once fetch and use work in Client Components.
Static Data Fetching
By default, fetch will automatically fetch and cache data indefinitely.
 fetch('https://...') // cache: 'force-cache' is the default
Revalidating Data
To revalidate cached data at a timed interval, you can use the next.revalidate option in fetch() to set the cache lifetime of a resource (in seconds).
 fetch('https://...', { next: { revalidate: 10 } })
See Revalidating Data for more information.
Good to know:


See Revalidating Data for more information.
Good to know:
Caching at the fetch level with revalidate or cache: 'force-cache' stores the data across requests in a shared cache. You should avoid using it for user-specific data (i.e. requests that derive data from cookies() or headers())
Dynamic Data Fetching
To fetch fresh data on every fetch request, use the cache: 'no-store' option.
 fetch('https://...', { cache: 'no-store' })
Data Fetching Patterns
Parallel Data Fetching
To minimize client-server waterfalls, we recommend this pattern to fetch data in parallel:
app/artist/[username]/page.tsx import Albums from './albums'

async function getArtist(username: string) {
  const res = await fetch(`https://api.example.com/artist/${username}`)
  return res.json()
}


return res.json()
}

async function getArtistAlbums(username: string) {
  const res = await fetch(`https://api.example.com/artist/${username}/albums`)
  return res.json()
}

export default async function Page({
  params: { username },
}: {
  params: { username: string }
}) {
  // Initiate both requests in parallel
  const artistData = getArtist(username)
  const albumsData = getArtistAlbums(username)

  // Wait for the promises to resolve
  const [artist, albums] = await Promise.all([artistData, albumsData])

  return (
    <>
      <h1>{artist.name}</h1>
      <Albums list={albums}></Albums>
    </>
  )
}


</>
  )
}
By starting the fetch prior to calling await in the Server Component, each request can eagerly start to fetch requests at the same time. This sets the components up so you can avoid waterfalls.
We can save time by initiating both requests in parallel, however, the user won't see the rendered result until both promises are resolved.
To improve the user experience, you can add a suspense boundary to break up the rendering work and show part of the result as soon as possible:
artist/[username]/page.tsx import { getArtist, getArtistAlbums, type Album } from './api'

export default async function Page({
  params: { username },
}: {
  params: { username: string }
}) {
  // Initiate both requests in parallel
  const artistData = getArtist(username)
  const albumData = getArtistAlbums(username)


const albumData = getArtistAlbums(username)

  // Wait for the artist's promise to resolve first
  const artist = await artistData

  return (
    <>

{artist.name}

      {/* Send the artist information first,
          and wrap albums in a suspense boundary */}
      <Suspense fallback={
Loading...
}>
        <Albums promise={albumData} />
      </Suspense>
    </>
  )
}

// Albums Component
async function Albums({ promise }: { promise: Promise<Album[]> }) {
  // Wait for the albums promise to resolve
  const albums = await promise

  return (

      {albums.map((album) => (

{album.name}

      ))}

  )


))}

  )
}
Take a look at the preloading pattern for more information on improving components structure.
Sequential Data Fetching
To fetch data sequentially, you can fetch directly inside the component that needs it, or you can await the result of fetch inside the component that needs it:
app/artist/page.tsx // ...

async function Playlists({ artistID }: { artistID: string }) {
  // Wait for the playlists
  const playlists = await getArtistPlaylists(artistID)

  return (

      {playlists.map((playlist) => (

{playlist.name}

      ))}

  )
}

export default async function Page({
  params: { username },
}: {
  params: { username: string }
}) {


}: {
  params: { username: string }
}) {
  // Wait for the artist
  const artist = await getArtist(username)

  return (
    <>

{artist.name}

      <Suspense fallback={
Loading...
}>
        <Playlists artistID={artist.id} />
      </Suspense>
    </>
  )
}
By fetching data inside the component, each fetch request and nested segment in the route cannot start fetching data and rendering until the previous request or segment has completed.
Blocking Rendering in a Route
By fetching data in a layout, rendering for all route segments beneath it can only start once the data has finished loading.


In the pages directory, pages using server-rendering would show the browser loading spinner until getServerSideProps had finished, then render the React component for that page. This can be described as "all or nothing" data fetching. Either you had the entire data for your page, or none.
In the app directory, you have additional options to explore:
First, you can use loading.js to show an instant loading state from the server while streaming in the result from your data fetching function.
Second, you can move data fetching lower in the component tree to only block rendering for the parts of the page that need it. For example, moving data fetching to a specific component rather than fetching it at the root layout.
Whenever possible, it's best to fetch data in the segment that uses it. This also allows you to show a loading state for only the part of the page that is loading, and not the entire page.
Data Fetching without fetch()


Data Fetching without fetch()
You might not always have the ability to use and configure fetch requests directly if you're using a third-party library such as an ORM or database client.
In cases where you cannot use fetch but still want to control the caching or revalidating behavior of a layout or page, you can rely on the default caching behavior of the segment or use the segment cache configuration.
Default Caching Behavior
Any data fetching libraries that do not use fetch directly will not affect caching of a route, and will be static or dynamic depending on the route segment.
If the segment is static (default), the output of the request will be cached and revalidated (if configured) alongside the rest of the segment. If the segment is dynamic, the output of the request will not be cached and will be re-fetched on every request when the segment is rendered.
Good to know: Dynamic functions like cookies() and headers() will make the route segment dynamic.


Good to know: Dynamic functions like cookies() and headers() will make the route segment dynamic.
Segment Cache Configuration
As a temporary solution, until the caching behavior of third-party queries can be configured, you can use segment configuration to customize the cache behavior of the entire segment.
app/page.tsx import prisma from './lib/prisma'

export const revalidate = 3600 // revalidate every hour

async function getPosts() {
  const posts = await prisma.post.findMany()
  return posts
}

export default async function Page() {
  const posts = await getPosts()
  // ...
}


Caching DataNext.js has built-in support for caching data, both on a per-request basis (recommended) or for an entire route segment.
Per-request Caching
fetch()
By default, all fetch() requests are cached and deduplicated automatically. This means that if you make the same request twice, the second request will reuse the result from the first request.
app/page.tsx async function getComments() {
  const res = await fetch('https://...') // The result is cached
  return res.json()
}

// This function is called twice, but the result is only fetched once
const comments = await getComments() // cache MISS

// The second call could be anywhere in your application
const comments = await getComments() // cache HIT
Requests are not cached if:


const comments = await getComments() // cache HIT
Requests are not cached if:
Dynamic methods (next/headers, export const POST, or similar) are used and the fetch is a POST request (or uses Authorization or cookie headers)
fetchCache is configured to skip cache by default
revalidate: 0 or cache: 'no-store' is configured on individual fetch
Requests made using fetch can specify a revalidate option to control the revalidation frequency of the request.
app/page.tsx export default async function Page() {
  // revalidate this data every 10 seconds at most
  const res = await fetch('https://...', { next: { revalidate: 10 } })
  const data = res.json()
  // ...
}
React cache()


const data = res.json()
  // ...
}
React cache()
React allows you to cache() and deduplicate requests, memoizing the result of the wrapped function call. The same function called with the same arguments will reuse a cached value instead of re-running the function.
utils/getUser.ts import { cache } from 'react'

export const getUser = cache(async (id: string) => {
  const user = await db.user.findUnique({ id })
  return user
})
app/user/[id]/layout.tsx import { getUser } from '@utils/getUser'

export default async function UserLayout({
  params: { id },
}: {
  params: { id: string }
}) {
  const user = await getUser(id)
  // ...
}
app/user/[id]/page.tsx import { getUser } from '@utils/getUser'


export default async function Page({
  params: { id },
}: {
  params: { id: string }
}) {
  const user = await getUser(id)
  // ...
}
Although the getUser() function is called twice in the example above, only one query will be made to the database. This is because getUser() is wrapped in cache(), so the second request can reuse the result from the first request.
Good to know:
fetch() caches requests automatically, so you don't need to wrap functions that use fetch() with cache(). See automatic request deduping for more information.
In this new model, we recommend fetching data directly in the component that needs it, even if you're requesting the same data in multiple components, rather than passing the data between components as props.
We recommend using the server-only package to make sure server data fetching functions are never used on the client.
POST requests and cache()


POST requests and cache()
POST requests are automatically deduplicated when using fetch – unless they are inside of POST Route Handler or come after reading headers()/cookies(). For example, if you are using GraphQL and POST requests in the above cases, you can use cache to deduplicate requests. The cache arguments must be flat and only include primitives. Deep objects won't match for deduplication.
utils/getUser.ts import { cache } from 'react'

export const getUser = cache(async (id: string) => {
  const res = await fetch('...', { method: 'POST', body: '...' })
  // ...
})
Preload pattern with cache()
As a pattern, we suggest optionally exposing a preload() export in utilities or components that do data fetching.
components/User.tsx import { getUser } from '@utils/getUser'

export const preload = (id: string) => {


export const preload = (id: string) => {
  // void evaluates the given expression and returns undefined
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
  void getUser(id)
}
export default async function User({ id }: { id: string }) {
  const result = await getUser(id)
  // ...
}
By calling preload, you can eagerly start fetching data you're likely going to need.
app/user/[id]/page.tsx import User, { preload } from '@components/User'

export default async function Page({
  params: { id },
}: {
  params: { id: string }
}) {
  preload(id) // starting loading the user data now
  const condition = await fetchCondition()
  return condition ? <User id={id} /> : null
}
Good to know:


}
Good to know:
The preload() function can have any name. It's a pattern, not an API.
This pattern is completely optional and something you can use to optimize on a case-by-case basis.
This pattern is a further optimization on top of parallel data fetching. Now you don't have to pass promises down as props and can instead rely on the preload pattern.
Combining cache, preload, and server-only
You can combine the cache function, the preload pattern, and the server-only package to create a data fetching utility that can be used throughout your app.
utils/getUser.ts import { cache } from 'react'
import 'server-only'

export const preload = (id: string) => {
  void getUser(id)
}

export const getUser = cache(async (id: string) => {
  // ...
})


export const getUser = cache(async (id: string) => {
  // ...
})
With this approach, you can eagerly fetch data, cache responses, and guarantee that this data fetching only happens on the server.
The getUser.ts exports can be used by layouts, pages, or components to give them control over when a user's data is fetched.
Segment-level Caching
Good to know: We recommend using per-request caching for improved granularity and control over caching.
Segment-level caching allows you to cache and revalidate data used in route segments.
This mechanism allows different segments of a path to control the cache lifetime of the entire route. Each page.tsx and layout.tsx in the route hierarchy can export a revalidate value that sets the revalidation time for the route.
app/page.tsx export const revalidate = 60 // revalidate this segment every 60 seconds
Good to know:


Good to know:
If a page, layout, and fetch request inside components all specify a revalidate frequency, the lowest value of the three will be used.
Advanced: You can set fetchCache to 'only-cache' or 'force-cache' to ensure that all fetch requests opt into caching but the revalidation frequency might still be lowered by individual fetch requests. See fetchCache for more information.


Revalidating DataNext.js allows you to update specific static routes without needing to rebuild your entire site. Revalidation (also known as Incremental Static Regeneration) allows you to retain the benefits of static while scaling to millions of pages.
There are two types of revalidation in Next.js:
Background: Revalidates the data at a specific time interval.
On-demand: Revalidates the data based on an event such as an update.
Background Revalidation
To revalidate cached data at a specific interval, you can use the next.revalidate option in fetch() to set the cache lifetime of a resource (in seconds).
 fetch('https://...', { next: { revalidate: 60 } })
If you want to revalidate data that does not use fetch (i.e. using an external package or query builder), you can use the route segment config.


app/page.tsx export const revalidate = 60 // revalidate this page every 60 seconds
In addition to fetch, you can also revalidate data using cache.
How it works
When a request is made to the route that was statically rendered at build time, it will initially show the cached data.
Any requests to the route after the initial request and before 60 seconds are also cached and instantaneous.
After the 60-second window, the next request will still show the cached (stale) data.
Next.js will trigger a regeneration of the data in the background.
Once the route generates successfully, Next.js will invalidate the cache and show the updated route. If the background regeneration fails, the old data would still be unaltered.
When a request is made to a route segment that hasn’t been generated, Next.js will dynamically render the route on the first request. Future requests will serve the static route segments from the cache.


Good to know: Check if your upstream data provider has caching enabled by default. You might need to disable (e.g. useCdn: false), otherwise a revalidation won't be able to pull fresh data to update the ISR cache. Caching can occur at a CDN (for an endpoint being requested) when it returns the Cache-Control header. ISR on Vercel persists the cache globally and handles rollbacks.
On-demand Revalidation
If you set a revalidate time of 60, all visitors will see the same generated version of your site for one minute. The only way to invalidate the cache is if someone visits the page after the minute has passed.
The Next.js App Router supports revalidating content on-demand based on a route or cache tag. This allows you to manually purge the Next.js cache for specific fetches, making it easier to update your site when:
Content from your headless CMS is created or updated.


Content from your headless CMS is created or updated.
Ecommerce metadata changes (price, description, category, reviews, etc).
Using On-Demand Revalidation
Data can be revalidated on-demand by path (revalidatePath) or by cache tag (revalidateTag).
For example, the following fetch adds the cache tag collection:
app/page.tsx export default async function Page() {
  const res = await fetch('https://...', { next: { tags: ['collection'] } })
  const data = await res.json()
  // ...
}
This cached data can then be revalidated on-demand by calling revalidateTag in a Route Handler.
app/api/revalidate/route.ts import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'

export async function GET(request: NextRequest) {


export async function GET(request: NextRequest) {
  const tag = request.nextUrl.searchParams.get('tag')
  revalidateTag(tag)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}
Error Handling and Revalidation
If an error is thrown while attempting to revalidate data, the last successfully generated data will continue to be served from the cache. On the next subsequent request, Next.js will retry revalidating the data.


Server ActionsServer Actions are an alpha feature in Next.js, built on top of React Actions. They enable server-side data mutations, reduced client-side JavaScript, and progressively enhanced forms. They can be defined inside Server Components and/or called from Client Components:
With Server Components:
app/add-to-cart.js import { cookies } from 'next/headers'

// Server action defined inside a Server Component
export default function AddToCart({ productId }) {
  async function addItem(data) {
    'use server'

    const cartId = cookies().get('cartId')?.value
    await saveToDb({ cartId, data })
  }

  return (
    <form action={addItem}>
      <button type="submit">Add to Cart</button>
    </form>
  )
}
With Client Components:
app/actions.js 'use server'

export async function addItem(data) {