gavmac00/nextjs-app-docs huggingface dataset:
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 (
    <section>
      <Suspense fallback={<p>Loading feed...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>Loading weather...</p>}>
        <Weather />
<Suspense fallback={<p>Loading weather...</p>}>
        <Weather />
      </Suspense>
    </section>
  )
}
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 <head> 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).
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 <h1>Hello, Next.js!</h1>
}
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 (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}
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.
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 <h1>Hello, Home page!</h1>
}
app/dashboard/page.tsx // `app/dashboard/page.tsx` is the UI for the `/dashboard` URL
export default function Page() {
export default function Page() {
  return <h1>Hello, Dashboard Page!</h1>
}
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 (
    <section>
      {/* Include shared UI here e.g. a header or sidebar */}
      <nav></nav>
 
      {children}
    </section>
  )
}
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.
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'