instant validation in development vs production
Next.js does not perform prefetches in development, so navigations may not feel as instant as they will in production. Validation reflects what will happen during `next start`, where prefetching is enabled.
instant cannot be used in Client Components
The `instant` export cannot be used in Client Components. Using it in a Client Component will throw an error.
instant config default validation level
By default with `validationLevel: 'warning'`, Cache Components apps validate every Page and Default segment in development. The `experimental.instantInsights.validationLevel` config in next.config.js tunes this behavior.
maxDuration introduced in version 13.4.10
The maxDuration route segment config option was introduced in Next.js version 13.4.10.
maxDuration export syntax
Export maxDuration as a named export with a numeric value in seconds. Example: export const maxDuration = 5
maxDuration route segment config option
The maxDuration option allows you to set the maximum execution time in seconds for server-side logic in a route segment. Deployment platforms can use maxDuration from the Next.js build output to add specific execution limits.
maxDuration with Server Actions
When using Server Actions, set maxDuration at the page level to change the default timeout of all Server Actions used on that page.
maxDuration applies to layout.tsx, page.tsx, and route.ts files
The maxDuration export can be used in layout.tsx, page.tsx, layout.js, page.js, route.ts, or route.js files.
preferredRegion syntax and types
preferredRegion is exported as a route segment config option that accepts either a string or string array. Syntax: export const preferredRegion = 'string' or export const preferredRegion = ['string', 'string']. A string value deploys the route to a specific region with platform-specific codes like 'iad1'. A string array deploys the route to all listed regions, not just one chosen from the list, for example ['iad1', 'sfo1'].
preferredRegion deprecated
The preferredRegion route segment config is deprecated. Remove the preferredRegion export from your route files.
preferredRegion Vercel runtime note
On Vercel, regions were previously only supported with export const runtime = 'edge', which is now deprecated.
preferredRegion on Vercel options
When deploying Next.js on Vercel, preferredRegion supports the following values: 'auto' (default, uses the default region), 'global' (prefers deploying to all available regions), and 'home' (prefers deploying to the home region). Unsupported values will throw an error.
preferredRegion passed to deployment platform
Next.js passes the preferredRegion values through to the deployment platform. The exact behavior and available region codes are platform-specific and must be determined from the deployment platform's documentation.
preferredRegion inheritance and overrides
If preferredRegion is not specified on a route segment, it inherits the option from the nearest parent layout. The root layout defaults to 'auto'. A child segment's preferredRegion value overrides the parent value; values are not merged.
Edge Runtime is deprecated
The Edge Runtime is deprecated. You should remove the runtime export from your route files if it is set to 'edge'.
runtime cannot be used in Proxy
The runtime export option cannot be used in Proxy file conventions.
runtime export values
The runtime option accepts two values: 'nodejs' (default) and 'edge' (deprecated). Only 'nodejs' should be used; 'edge' is deprecated and should be removed from route files.
runtime route segment config option
The runtime option allows you to select the JavaScript runtime used for rendering your route. It is exported as a constant from layout.tsx, page.tsx, route.ts, or their .js equivalents.
default.js example code for 404 behavior
import { notFound } from 'next/navigation'
export default function Default() {
notFound()
}
default.js params prop example with type
Example showing params as async: export default async function Default({ params }: { params: Promise<{ artist: string }> }) { const { artist } = await params }
default.js params examples table
Dynamic route parameters examples: app/[artist]/@sidebar/default.js with URL /zack resolves to Promise<{ artist: 'zack' }>. app/[artist]/[album]/@sidebar/default.js with URL /zack/next resolves to Promise<{ artist: 'zack', album: 'next' }>.
default.js params prop reference
The params prop is an optional property that is a promise resolving to an object containing the dynamic route parameters from the root segment down to the slot's subpages. The params prop must be awaited or used with React's use function to access the values. In version 14 and earlier, params was synchronous. In Next.js 15, it can still be accessed synchronously for backwards compatibility, but this behavior will be deprecated in the future.
default.js required for named slots to avoid error
If default.js does not exist, an error is returned for named slots (@team, @analytics, etc) and requires you to define a default.js in order to continue.
default.js implementing notFound to return 404
To preserve the old behavior of returning a 404 when Next.js cannot recover a slot's active state, you can create a default.js file that imports notFound from 'next/navigation' and calls it within the component.
default.js file convention purpose
The default.js file is used to render a fallback within Parallel Routes when Next.js cannot recover a slot's active state after a full-page load.
default.js used for hard navigations not soft navigation
During soft navigation, Next.js keeps track of the active state (subpage) for each slot. However, for hard navigations (full-page load), Next.js cannot recover the active state. In this case, a default.js file can be rendered for subpages that don't match the current URL.
default.js required for children slot
Since children is an implicit slot, you also need to create a default.js file to render a fallback for children when Next.js cannot recover the active state of the parent page. If you don't create a default.js for the children slot, it will return a 404 page for the route.
forbidden.js example component
Example of a forbidden component that renders a Forbidden heading, authorization error message, and a link back home:
```tsx
import Link from 'next/link'
export default function Forbidden() {
return (
<div>
<h2>Forbidden</h2>
<p>You are not authorized to access this resource.</p>
<Link href="/">Return Home</Link>
</div>
)
}
```
forbidden.js introduced in v15.1.0
The forbidden.js file convention was introduced in Next.js version 15.1.0.
forbidden component props
The forbidden.js component does not accept any props.
forbidden.js file convention
The forbidden.js file is a special file used to render custom UI when the forbidden function is invoked during authentication. When used, Next.js returns a 403 status code.
Example: Dynamic page without generateStaticParams
```tsx filename="app/blog/[slug]/page.tsx"
import { Suspense } from 'react'
export default function Page({ params }: PageProps<'/blog/[slug]'>) {
return (
<div>
<h1>Blog Post</h1>
<Suspense fallback={<div>Loading...</div>}>
{params.then(({ slug }) => (
<Content slug={slug} />
))}
</Suspense>
</div>
)
}
async function Content({ slug }: { slug: string }) {
const res = await fetch(`https://api.vercel.app/blog/${slug}`)
const post = await res.json()
return (
<article>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
)
}
```
This example shows a dynamic page that wraps param access in Suspense without using generateStaticParams, making all params runtime data.
Handling runtime params not in generateStaticParams samples
For runtime params not returned by `generateStaticParams`, validation occurs during the first request. If a route has conditional logic that accesses runtime APIs for param values not in samples, those branches won't be validated at build time and will error if hit. Wrap such branches with Suspense to handle runtime param access.
Build-time validation with generateStaticParams
During the build process with `generateStaticParams`, the route is executed with each sample param to collect the HTML result. If dynamic content or runtime data are accessed incorrectly, the build will fail. Build-time validation only covers code paths that execute with the sample params provided.
generateStaticParams for prerendering dynamic routes
`generateStaticParams` is an async function that returns an array of param objects to prerender pages at build time. For example: `export async function generateStaticParams() { return [{ slug: '1' }, { slug: '2' }, { slug: '3' }] }`. When used, you can access params synchronously (await params) in the page component because the params are known at build time.
Dynamic Segments params type definitions by route pattern
TypeScript params type definitions vary by route pattern: `app/blog/[slug]/page.js` → `{ slug: string }`, `app/shop/[...slug]/page.js` → `{ slug: string[] }`, `app/shop/[[...slug]]/page.js` → `{ slug?: string[] }`, `app/[categoryId]/[itemId]/page.js` → `{ categoryId: string, itemId: string }`.
Optional Catch-all Segments syntax with double square brackets
Catch-all Segments can be made optional by including the parameter in double square brackets: `[[...folderName]]`. For example, `app/shop/[[...slug]]/page.js` matches both `/shop` (where params.slug is undefined) and `/shop/clothes`, `/shop/clothes/tops`, etc. (where params.slug is an array).
Root parameters and next/root-params
Dynamic segments that appear before the root layout are root parameters. These can be read from any Server Component using `next/root-params`.
Wrapping param access with Suspense when using Cache Components without generateStaticParams
When using Cache Components with dynamic route segments and no `generateStaticParams`, all params are runtime data. Param access must be wrapped by Suspense boundaries to provide fallback UI. Next.js generates a static shell at build time, and content loads on each request.
Params prop type in TypeScript
In TypeScript, params is typed as `Promise<{...}>`. Use the helper types `PageProps<'/route'>`, `LayoutProps<'/route'>`, or `RouteContext<'/route'>` to type params in page, layout, and route functions respectively. Route params values are typed as `string`, `string[]`, or `undefined` because their values aren't known until runtime.
Params prop structure and access in Server Components
In Server Components, the `params` prop is a Promise. You must use `async`/`await` to access its values. For example: `export default async function Page({ params }) { const { slug } = await params; return <div>{slug}</div>; }`. The params object contains all dynamic segments from the matched route as key-value pairs.
Dynamic Segment syntax with square brackets
A Dynamic Segment is created by wrapping a folder name in square brackets. For example, `[slug]` in the path `app/blog/[slug]/page.js` creates a dynamic route segment that captures values from the URL.
Catch-all Segments syntax with ellipsis
A Dynamic Segment can be extended to catch-all subsequent segments by adding an ellipsis inside square brackets: `[...folderName]`. For example, `app/shop/[...slug]/page.js` matches `/shop/clothes`, `/shop/clothes/tops`, `/shop/clothes/tops/t-shirts`, and so on. The captured segments are provided as an array in params.
Accessing params in Client Components with use hook
In Client Component pages, dynamic segments from props can be accessed using React's `use` API: `'use client'; import { use } from 'react'; export default function Page({ params }) { const { slug } = use(params); }`. Alternatively, use the `useParams` hook to access params anywhere in the Client Component tree.
Layout param access should be wrapped before awaiting at top level
In layouts, avoid awaiting `params` at the top level, as doing so prevents the layout from being prerendered. Instead, pass the params promise down to the component that needs it and await there to maximize the static shell.
Fetch request deduplication in generateStaticParams
When using `fetch` inside the `generateStaticParams` function, the requests are automatically deduplicated. This avoids multiple network calls for the same data across Layouts, Pages, and other `generateStaticParams` functions, speeding up build time.
Backwards compatibility for synchronous params access
In Next.js 15, `params` is a Promise, but you can still access it synchronously for backwards compatibility with version 14 and earlier. However, this synchronous behavior will be deprecated in the future, so you should migrate to using `async`/`await` or React's `use` function.
Example: Dynamic Route Handler with generateStaticParams
```ts filename="app/api/posts/[id]/route.ts"
export async function generateStaticParams() {
const posts: { id: number }[] = await fetch(
'https://api.vercel.app/blog'
).then((res) => res.json())
return posts.map((post) => ({
id: `${post.id}`,
}))
}
export async function GET(
request: Request,
{ params }: RouteContext<'/api/posts/[id]'>
) {
const { id } = await params
const res = await fetch(`https://api.vercel.app/blog/${id}`)
if (!res.ok) {
return Response.json({ error: 'Post not found' }, { status: 404 })
}
const post = await res.json()
return Response.json(post)
}
```
This example shows a dynamic Route Handler with generateStaticParams to statically generate API responses at build time. Route handlers for all blog post IDs returned by generateStaticParams are statically generated; requests to other IDs are handled dynamically at request time.
Example: Handling conditional runtime params with Suspense
```tsx filename="app/blog/[slug]/page.tsx"
import { Suspense } from 'react'
import { cookies } from 'next/headers'
export async function generateStaticParams() {
return [{ slug: 'public-post' }, { slug: 'hello-world' }]
}
export default async function Page({ params }: PageProps<'/blog/[slug]'>) {
const { slug } = await params
if (slug.startsWith('private-')) {
return (
<Suspense fallback={<div>Loading...</div>}>
<PrivatePost slug={slug} />
</Suspense>
)
}
return <PublicPost slug={slug} />
}
async function PrivatePost({ slug }: { slug: string }) {
const token = (await cookies()).get('token')
// ... fetch and render private post using token for auth
}
```
This example shows wrapping conditional branches that access runtime APIs for param values not in generateStaticParams samples with Suspense to handle them correctly.
Dynamic Segments pass to multiple file convention functions
Dynamic Segments are passed as the `params` prop to `layout`, `page`, `route`, and `generateMetadata` functions.
Example: Dynamic page with generateStaticParams
```tsx filename="app/blog/[slug]/page.tsx"
import { Suspense } from 'react'
export async function generateStaticParams() {
return [{ slug: '1' }, { slug: '2' }, { slug: '3' }]
}
export default async function Page({ params }: PageProps<'/blog/[slug]'>) {
const { slug } = await params
return (
<div>
<h1>Blog Post</h1>
<Content slug={slug} />
</div>
)
}
async function Content({ slug }: { slug: string }) {
const post = await getPost(slug)
return (
<article>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
)
}
async function getPost(slug: string) {
'use cache'
const res = await fetch(`https://api.vercel.app/blog/${slug}`)
return res.json()
}
```
This example shows a dynamic page prerendering specific param values at build time using generateStaticParams.
Example: generateStaticParams with fetch
```tsx filename="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,
}))
}
```
This example shows using fetch inside generateStaticParams to retrieve data that will be deduplicated across the application during the build process.
File-system conventions overview
Next.js file-system conventions are the API reference for how to structure files in a Next.js application. This document provides guidance on file naming and organization patterns that Next.js recognizes and processes automatically.
error.js scope and hierarchy
In the component hierarchy, error.js wraps loading.js, not-found.js, page.js, and nested layout.js files in a React error boundary. It does not wrap the layout.js or template.js above it in the same segment. To handle errors in the root layout, use global-error.js instead.
error.js version history
Version history: v13.0.0 introduced error, v13.1.0 introduced global-error, v15.2.0 also displays global-error in development, v16.2.0 added unstable_retry prop, v16.3.0 made retry prop stable.
catchError function for component-level error recovery
For component-level error recovery that aren't tied to route segments like error.js, use the catchError function instead.
error.js file convention
error.js is a special file that handles unexpected runtime errors and displays fallback UI. It must be a Client Component (marked with 'use client'). It wraps a route segment and its nested children in a React Error Boundary.
error.js component props
The error component receives two props: error and retry. The error prop is an instance of an Error object with an optional digest property. The retry prop is a function that attempts to recover by re-fetching and re-rendering the error boundary's children.
error prop structure
The error prop is of type Error & { digest?: string }. In development, errors forwarded from Client Components show the original Error message. Errors forwarded from Server Components show a generic message with an identifier to prevent leaking sensitive details.
error.digest property
error.digest is an automatically generated hash of the error thrown. It can be used to match the corresponding error in server-side logs. For Server Component errors, the digest identifier can be used to match corresponding server-side logs.