proxy with headers example
Example of setting request and response headers in proxy: const requestHeaders = new Headers(request.headers); requestHeaders.set('x-hello-from-proxy1', 'hello'); const response = NextResponse.next({ request: { headers: requestHeaders } }); response.headers.set('x-hello-from-proxy2', 'hello'); return response
proxy negative matcher example
Example of negative matching to exclude certain paths: export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)']}
proxy matcher with has and missing conditions
Example of matcher with has and missing conditions: export const config = { matcher: [{ source: '/api/:path*', locale: false, has: [{ type: 'header', key: 'Authorization', value: 'Bearer Token' }, { type: 'query', key: 'userId', value: '123' }], missing: [{ type: 'cookie', key: 'session', value: 'active' }] }]}
proxy isolation from application code
Proxy is meant to be invoked separately from render code and in optimized cases deployed to a CDN for fast redirect/rewrite handling. You should not attempt relying on shared modules or globals. To pass information from Proxy to your application, use headers, cookies, rewrites, redirects, or the URL.
proxy produces response capability
To produce a response from Proxy, you can: 1) rewrite to a route (Page or Route Handler) that produces a response; 2) return a NextResponse directly. For redirects, you can also use Response.redirect instead of NextResponse.redirect.
proxy.js file location
The proxy.js or proxy.ts file must be created in the project root or inside src at the same level as pages or app. If pageExtensions has been customized (for example to .page.ts or .page.js), the file should be named proxy.page.ts or proxy.page.js accordingly.
proxy function export requirement
The proxy.js file must export a single function, either as a default export or named export called 'proxy'. Multiple proxies from the same file are not supported.
proxy execution timing
Proxy executes before routes are rendered. It runs on the server before a request is completed. Without a matcher, Proxy runs on every request, including static files (_next/static), image optimizations (_next/image), and assets in the public/ folder.
proxy parameters: request and event
Next.js calls the Proxy function with two arguments: request (an instance of NextRequest representing the incoming HTTP request) and event (an instance of NextFetchEvent). You can declare only the ones you use.
NextProxy type
The NextProxy type is a shorthand that infers parameter types automatically. It can be used as: export const proxy: NextProxy = (request, event) => { ... }
Route Handlers segment config options
Route Handlers use the same route segment configuration as pages and layouts. Available options are: dynamic, dynamicParams, revalidate, fetchCache, runtime, and preferredRegion (deprecated).
Route Handlers definition and purpose
Route Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.
Supported HTTP methods in Route Handlers
Route Handlers support the following HTTP methods: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS.
OPTIONS method auto-implementation in Route Handlers
If OPTIONS is not explicitly defined in a Route Handler, Next.js will automatically implement OPTIONS and set the appropriate Response Allow header depending on the other methods defined in the Route Handler.
Route Handler request parameter
The request parameter in a Route Handler is a NextRequest object, which is an extension of the Web Request API. NextRequest gives further control over the incoming request, including easily accessing cookies and an extended, parsed URL object nextUrl.
Route Handler context params parameter
The context parameter in a Route Handler contains params, which is a promise that resolves to an object containing the dynamic route parameters for the current route. As of v15.0.0-RC, context.params is a promise and must be awaited.
Dynamic route parameters examples in Route Handlers
Dynamic route parameters in Route Handlers resolve as follows: app/dashboard/[team]/route.js with URL /dashboard/1 resolves to Promise<{ team: '1' }>; app/shop/[tag]/[item]/route.js with URL /shop/1/2 resolves to Promise<{ tag: '1', item: '2' }>; app/blog/[...slug]/route.js with URL /blog/1/2 resolves to Promise<{ slug: ['1', '2'] }>.
RouteContext helper for type-safe Route Handlers
RouteContext is a globally available helper that can type the Route Handler context to get strongly typed params from a route literal. It is used as: ctx: RouteContext<'/users/[id]'>. Types are generated during next dev, next build, or next typegen. After type generation, RouteContext is globally available and does not need to be imported.
Reading cookies in Route Handlers
Cookies can be read or set in Route Handlers using the cookies function imported from next/headers. The cookies function is async and must be awaited. You can also read cookies directly from the NextRequest object using request.cookies.get(). Alternatively, you can return a new Response using the Set-Cookie header.
Reading headers in Route Handlers
Headers can be read in Route Handlers using the headers function imported from next/headers. The headers function is async and must be awaited. The headers instance is read-only. To set headers, you must return a new Response with new headers. You can also use the underlying Web API to read headers from the request by creating a new Headers object from request.headers.
Revalidating cached data in Route Handlers
Cached data in Route Handlers can be revalidated using the revalidate route segment config option. Set export const revalidate = 60 to revalidate cached data every 60 seconds.
Redirects in Route Handlers
Route Handlers can perform redirects by importing the redirect function from next/navigation and calling it with a URL.
Dynamic Route Segments in Route Handlers
Route Handlers can use Dynamic Segments to create request handlers from dynamic data. For example, app/items/[slug]/route.js with URL /items/a resolves to Promise<{ slug: 'a' }>.
generateStaticParams with Route Handlers
You can use generateStaticParams with dynamic Route Handlers to statically generate responses at build time for specified params, while handling other params dynamically at request time. When using Cache Components, you can combine generateStaticParams with use cache to enable data caching for both prerendered and runtime params.
URL Query Parameters in Route Handlers
The request object passed to a Route Handler is a NextRequest instance that includes convenience methods for handling query parameters. Access query parameters using request.nextUrl.searchParams.get('paramName'). For example, request.nextUrl.searchParams.get('query') returns 'hello' for /api/search?query=hello.
Streaming in Route Handlers
Streaming is commonly used in Route Handlers in combination with Large Language Models (LLMs) for AI-generated content. You can use abstractions like StreamingTextResponse from the ai SDK, or use underlying Web APIs directly with ReadableStream.
Reading Request Body in Route Handlers
The Request body in a Route Handler can be read using standard Web API methods. Use await request.json() to parse JSON body content.
Reading FormData in Route Handlers
FormData in a Route Handler can be read using the request.formData() function. Access individual form fields using formData.get('fieldName'). Since FormData values are all strings, you may want to use zod-form-data to validate the request and retrieve data in the preferred format.
CORS headers in Route Handlers
CORS headers can be set in Route Handlers using the standard Web API Response methods by returning a Response with appropriate headers: Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers. To add CORS headers to multiple Route Handlers, you can use Proxy or configure it in next.config.js file.
Webhooks with Route Handlers
Route Handlers can receive webhooks from third-party services. Unlike API Routes with the Pages Router, you do not need to use bodyParser for any additional configuration.
Non-UI responses in Route Handlers
Route Handlers can return non-UI content. sitemap.xml, robots.txt, app icons, and open graph images have built-in support. You can use Route Handlers to return custom XML, RSS feeds, or other content types by setting the appropriate Content-Type header.
Default segment config for Route Handlers
The default route segment configuration values for Route Handlers are: dynamic = 'auto', dynamicParams = true, revalidate = false, fetchCache = 'auto', runtime = 'nodejs', and preferredRegion = 'auto' (deprecated).
Route Handlers default caching change in v15.0.0-RC
As of v15.0.0-RC, the default caching for GET handlers was changed from static to dynamic.
context.params is a promise in Route Handlers v15.0.0-RC
As of v15.0.0-RC, context.params in Route Handlers is now a promise and must be awaited. A codemod is available for upgrading.
Route Handlers introduction version
Route Handlers were introduced in v13.2.0.
unauthorized.js basic example
Create an unauthorized.tsx or unauthorized.js file at app/unauthorized.tsx. Export a default component that renders the custom unauthorized UI, such as a login prompt. Example:
export default function Unauthorized() {
return (
<main>
<h1>401 - Unauthorized</h1>
<p>Please log in to access this page.</p>
<Login />
</main>
)
}
unauthorized.js file convention
The unauthorized.js file is a special file used to render custom UI when the unauthorized() function is invoked during authentication. Next.js will return a 401 status code when this file is rendered. The unauthorized.js component does not accept any props.
unauthorized.js introduced in Next.js v15.1.0
The unauthorized.js special file was introduced in Next.js version 15.1.0.
unauthorized() function usage in pages
Import the unauthorized function from 'next/navigation'. Call unauthorized() in a page or component when a session check fails to render the unauthorized.js file with a 401 status code. Example:
import { unauthorized } from 'next/navigation'
export default async function DashboardPage() {
const session = await verifySession()
if (!session) {
unauthorized()
}
return <div>Dashboard</div>
}
forbidden.js file customizes 403 UI
The forbidden.js (or forbidden.tsx) file can be placed in a directory to define custom UI that renders when forbidden() is called in that route segment or its children.
sitemap file convention location and formats
The sitemap file is a special file that can be created at `sitemap.(xml|js|ts)` in the root of the `app` directory. It matches the Sitemaps XML format to help search engine crawlers index the site more efficiently.
sitemap.xml static file format
A static `sitemap.xml` file placed in the `app` directory contains a root `<urlset>` element with xmlns attribute 'http://www.sitemaps.org/schemas/sitemap/0.9'. Each `<url>` child element contains `<loc>`, `<lastmod>`, `<changefreq>`, and `<priority>` child elements.
sitemap.js/ts default export returns array of URL objects
The `sitemap.(js|ts)` file must export a default function that returns an array of URL objects. This function can be async. The return type in TypeScript is `MetadataRoute.Sitemap`.
sitemap URL object properties
Each URL object in the sitemap array can have the following properties: url (string, required), lastModified (string or Date, optional), changeFrequency (optional, one of 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'), priority (number, optional), alternates (object with languages property, optional), images (array of strings, optional), and videos (array of objects, optional).
sitemap.js caching behavior
The `sitemap.js` file is a special Route Handler that is cached by default unless it uses a Request-time API or dynamic config option.
sitemap images property for image sitemaps
To create an image sitemap, include an `images` property in a URL object containing an array of image URL strings. The output XML will include an `xmlns:image` namespace and `<image:image>` elements with `<image:loc>` children for each image URL.
sitemap videos property for video sitemaps
To create a video sitemap, include a `videos` property in a URL object containing an array of video objects. Each video object must have: title (string), thumbnail_loc (string), and description (string). The output XML will include an `xmlns:video` namespace and `<video:video>` elements with `<video:title>`, `<video:thumbnail_loc>`, and `<video:description>` children.
generateSitemaps function for multiple sitemaps
You can use the `generateSitemaps` function to create multiple sitemaps by exporting it alongside a default sitemap function. The `generateSitemaps` function returns an array of objects with an `id` property. The default function receives props with an `id` property that is a Promise resolving to a string. Google's limit is 50,000 URLs per sitemap. Generated sitemaps are available at `/.../sitemap/[id]` (e.g., `/product/sitemap/1.xml`).
generating multiple sitemaps with nesting
For large applications needing multiple sitemaps, you can nest `sitemap.(xml|js|ts)` files inside multiple route segments. For example, create both `app/sitemap.xml` and `app/products/sitemap.xml`.
sitemap localization with alternates.languages
To create a localized sitemap, include an `alternates` property with a `languages` object mapping language codes to URLs. The output XML will include an `xmlns:xhtml` namespace and `<xhtml:link>` elements with `rel='alternate'`, `hreflang`, and `href` attributes.
sitemap generation example with generateSitemaps
export async function generateSitemaps() {
return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }]
}
export default async function sitemap(props: {
id: Promise<string>
}): Promise<MetadataRoute.Sitemap> {
const id = await props.id
const start = id * 50000
const end = start + 50000
const products = await getProducts(
`SELECT id, date FROM products WHERE id BETWEEN ${start} AND ${end}`
)
return products.map((product) => ({
url: `${BASE_URL}/product/${product.id}`,
lastModified: product.date,
}))
}
This example shows how to generate multiple sitemaps by returning objects with id properties from generateSitemaps and using those ids in the default function to paginate through data.
MetadataRoute.Sitemap return type definition
The MetadataRoute.Sitemap type is an array of objects with properties: url (string, required), lastModified (optional string or Date), changeFrequency (optional, one of 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'), priority (optional number), and alternates (optional object with languages property).
sitemap file convention version history
Version v13.3.0 introduced sitemap. Version v13.4.14 added changeFrequency and priority attributes to sitemaps. Version v14.2.0 added localizations support. Version v16.0.0 changed id to be a promise that resolves to a string.
App Router enables layouts, streaming, and colocated data fetching
The App Router, accessed through the app directory, enables support for layouts, Server Components, streaming, and colocated data fetching.
create-next-app CLI tool
The create-next-app CLI tool is used to quickly create a new Next.js application using the default template or an example from a public GitHub repository.
next CLI tool
The next CLI tool is used to run the Next.js development server, build your application, and perform other development and production tasks.
Next.js CLI tools overview
Next.js comes with two Command Line Interface tools: create-next-app for quickly creating a new Next.js application using the default template or an example from a public GitHub repository, and next for running the Next.js development server, building your application, and more.
Link prefetch prop relationship with segment config
A prefetch starts with a <Link> that expresses intent (should this destination be prefetched, and how eagerly), and ends at a segment that sets a cost ceiling (how much work is it OK to do ahead of time, for any link that points here). A destination can't know which links target it, so the segment config caps what any <Link prefetch={true}> pulls. With 'partial': App Shell for default links; a <Link prefetch={true}> additionally resolves URL data (params, searchParams, and the full URL) and the cached content behind it. With 'force-disabled': skip segment data entirely. <Link prefetch={false}> skips prefetching at the link level regardless of how the destination is configured.
prefetch 'force-disabled' option
The 'force-disabled' value means never prefetch this segment. The client will not request segment data ahead of navigation. Use this for segments where prefetching would be wasteful, for example pages behind authentication that are rarely visited. The 'force-disabled' setting does not prevent Next.js from prefetching metadata about the route. However, the actual segment data for this segment and all deeper segments will be omitted from prefetching.
prefetch 'partial' with downstream segments
When Next.js performs a per-link prefetch for a segment, all downstream segments are included in the same request. Segments deeper in the tree that are configured with 'force-disabled' will still be prefetched as part of the response.