permanent: false,
        locale: false,
      }
      {
        // this gets converted to /(en|fr|de)/(.*) so will not match the top-level
        // `/` or `/fr` routes like /:path* would
        source: '/(.*)',
        destination: '/another',
        permanent: false,
      },
    ]
  },
}
In some rare cases, you might need to assign a custom status code for older HTTP Clients to properly redirect. In these cases, you can use the statusCode property instead of the permanent property, but not both. To to ensure IE11 compatibility, a Refresh header is automatically added for the 308 status code.
Other Redirects
Inside API Routes, you can use res.redirect().
Inside getStaticProps and getServerSideProps, you can redirect specific pages at request-time.
Version History


Version History
VersionChangesv13.3.0missing added.v10.2.0has added.v9.5.0redirects added.


rewrites
Rewrites allow you to map an incoming request path to a different destination path.
Rewrites act as a URL proxy and mask the destination path, making it appear the user hasn't changed their location on the site. In contrast, redirects will reroute to a new page and show the URL changes.
To use rewrites you can use the rewrites key in next.config.js:
next.config.js module.exports = {
  async rewrites() {
    return [
      {
        source: '/about',
        destination: '/',
      },
    ]
  },
}
Rewrites are applied to client-side routing, a <Link href="/about"> will have the rewrite applied in the above example.
rewrites is an async function that expects to return either an array or an object of arrays (see below) holding objects with source and destination properties:
source: String - is the incoming request path pattern.


source: String - is the incoming request path pattern.
destination: String is the path you want to route to.
basePath: false or undefined - if false the basePath won't be included when matching, can be used for external rewrites only.
locale: false or undefined - whether the locale should not be included when matching.
has is an array of has objects with the type, key and value properties.
missing is an array of missing objects with the type, key and value properties.
When the rewrites function returns an array, rewrites are applied after checking the filesystem (pages and /public files) and before dynamic routes. When the rewrites function returns an object of arrays with a specific shape, this behavior can be changed and more finely controlled, as of v10.1 of Next.js:
next.config.js module.exports = {
  async rewrites() {
    return {
      beforeFiles: [


async rewrites() {
    return {
      beforeFiles: [
        // These rewrites are checked after headers/redirects
        // and before all files including _next/public files which
        // allows overriding page files
        {
          source: '/some-page',
          destination: '/somewhere-else',
          has: [{ type: 'query', key: 'overrideMe' }],
        },
      ],
      afterFiles: [
        // These rewrites are checked after pages/public files
        // are checked but before dynamic routes
        {
          source: '/non-existent',
          destination: '/somewhere-else',
        },
      ],
      fallback: [
        // These rewrites are checked after both pages/public files
        // and dynamic routes are checked
        {
          source: '/:path*',


// and dynamic routes are checked
        {
          source: '/:path*',
          destination: `https://my-old-site.com/:path*`,
        },
      ],
    }
  },
}
Good to know: rewrites in beforeFiles do not check the filesystem/dynamic routes immediately after matching a source, they continue until all beforeFiles have been checked.
The order Next.js routes are checked is:
headers are checked/applied
redirects are checked/applied
beforeFiles rewrites are checked/applied
static files from the public directory, _next/static files, and non-dynamic pages are checked/served
afterFiles rewrites are checked/applied, if one of these rewrites is matched we check dynamic routes/static files after each match


fallback rewrites are checked/applied, these are applied before rendering the 404 page and after dynamic routes/all static assets have been checked. If you use fallback: true/'blocking' in getStaticPaths, the fallback rewrites defined in your next.config.js will not be run.
Rewrite parameters
When using parameters in a rewrite the parameters will be passed in the query by default when none of the parameters are used in the destination.
next.config.js module.exports = {
  async rewrites() {
    return [
      {
        source: '/old-about/:path*',
        destination: '/about', // The :path parameter isn't used here so will be automatically passed in the query
      },
    ]
  },
}
If a parameter is used in the destination none of the parameters will be automatically passed in the query.
next.config.js module.exports = {
  async rewrites() {
    return [
      {


async rewrites() {
    return [
      {
        source: '/docs/:path*',
        destination: '/:path*', // The :path parameter is used here so will not be automatically passed in the query
      },
    ]
  },
}
You can still pass the parameters manually in the query if one is already used in the destination by specifying the query in the destination.
next.config.js module.exports = {
  async rewrites() {
    return [
      {
        source: '/:first/:second',
        destination: '/:first?second=:second',
        // Since the :first parameter is used in the destination the :second parameter
        // will not automatically be added in the query although we can manually add it
        // as shown above
      },
    ]
  },
}


// as shown above
      },
    ]
  },
}
Good to know: Static pages from Automatic Static Optimization or prerendering params from rewrites will be parsed on the client after hydration and provided in the query.
Path Matching
Path matches are allowed, for example /blog/:slug will match /blog/hello-world (no nested paths):
next.config.js module.exports = {
  async rewrites() {
    return [
      {
        source: '/blog/:slug',
        destination: '/news/:slug', // Matched parameters can be used in the destination
      },
    ]
  },
}
Wildcard Path Matching
To match a wildcard path you can use * after a parameter, for example /blog/:slug* will match /blog/a/b/c/d/hello-world:
next.config.js module.exports = {
  async rewrites() {
    return [
      {


async rewrites() {
    return [
      {
        source: '/blog/:slug*',
        destination: '/news/:slug*', // Matched parameters can be used in the destination
      },
    ]
  },
}
Regex Path Matching
To match a regex path you can wrap the regex in parenthesis after a parameter, for example /blog/:slug(\\d{1,}) will match /blog/123 but not /blog/abc:
next.config.js module.exports = {
  async rewrites() {
    return [
      {
        source: '/old-blog/:post(\\d{1,})',
        destination: '/blog/:post', // Matched parameters can be used in the destination
      },
    ]
  },
}


},
    ]
  },
}
The following characters (, ), {, }, :, *, +, ? are used for regex path matching, so when used in the source as non-special values they must be escaped by adding \\ before them:
next.config.js module.exports = {
  async rewrites() {
    return [
      {
        // this will match `/english(default)/something` being requested
        source: '/english\\(default\\)/:slug',
        destination: '/en-us/:slug',
      },
    ]
  },
}
Header, Cookie, and Query Matching
To only match a rewrite when header, cookie, or query values also match the has field or don't match the missing field can be used. Both the source and all has items must match and all missing items must not match for the rewrite to be applied.
has and missing items can have the following fields:


has and missing items can have the following fields:
type: String - must be either header, cookie, host, or query.
key: String - the key from the selected type to match against.
value: String or undefined - the value to check for, if undefined any value will match. A regex like string can be used to capture a specific part of the value, e.g. if the value first-(?<paramName>.*) is used for first-second then second will be usable in the destination with :paramName.
next.config.js module.exports = {
  async rewrites() {
    return [
      // if the header `x-rewrite-me` is present,
      // this rewrite will be applied
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-rewrite-me',
          },
        ],


key: 'x-rewrite-me',
          },
        ],
        destination: '/another-page',
      },
      // if the header `x-rewrite-me` is not present,
      // this rewrite will be applied
      {
        source: '/:path*',
        missing: [
          {
            type: 'header',
            key: 'x-rewrite-me',
          },
        ],
        destination: '/another-page',
      },
      // if the source, query, and cookie are matched,
      // this rewrite will be applied
      {
        source: '/specific/:path*',
        has: [
          {
            type: 'query',
            key: 'page',
            // the page value will not be available in the
            // destination since value is provided and doesn't
            // use a named capture group e.g. (?<page>home)


// use a named capture group e.g. (?<page>home)
            value: 'home',
          },
          {
            type: 'cookie',
            key: 'authorized',
            value: 'true',
          },
        ],
        destination: '/:path*/home',
      },
      // if the header `x-authorized` is present and
      // contains a matching value, this rewrite will be applied
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-authorized',
            value: '(?<authorized>yes|true)',
          },
        ],
        destination: '/home?authorized=:authorized',
      },
      // if the host is `example.com`,
      // this rewrite will be applied
      {
        source: '/:path*',
        has: [


{
        source: '/:path*',
        has: [
          {
            type: 'host',
            value: 'example.com',
          },
        ],
        destination: '/another-page',
      },
    ]
  },
}
Rewriting to an external URL
Examples
Incremental adoption of Next.js
Using Multiple Zones
Rewrites allow you to rewrite to an external url. This is especially useful for incrementally adopting Next.js. The following is an example rewrite for redirecting the /blog route of your main app to an external site.
next.config.js module.exports = {
  async rewrites() {
    return [
      {
        source: '/blog',
        destination: 'https://example.com/blog',
      },
      {
        source: '/blog/:slug',


},
      {
        source: '/blog/:slug',
        destination: 'https://example.com/blog/:slug', // Matched parameters can be used in the destination
      },
    ]
  },
}
If you're using trailingSlash: true, you also need to insert a trailing slash in the source parameter. If the destination server is also expecting a trailing slash it should be included in the destination parameter as well.
next.config.js module.exports = {
  trailingSlash: true,
  async rewrites() {
    return [
      {
        source: '/blog/',
        destination: 'https://example.com/blog/',
      },
      {
        source: '/blog/:path*/',
        destination: 'https://example.com/blog/:path*/',
      },
    ]
  },
}
Incremental adoption of Next.js


},
    ]
  },
}
Incremental adoption of Next.js
You can also have Next.js fall back to proxying to an existing website after checking all Next.js routes.
This way you don't have to change the rewrites configuration when migrating more pages to Next.js
next.config.js module.exports = {
  async rewrites() {
    return {
      fallback: [
        {
          source: '/:path*',
          destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
        },
      ],
    }
  },
}
Rewrites with basePath support
When leveraging basePath support with rewrites each source and destination is automatically prefixed with the basePath unless you add basePath: false to the rewrite:
next.config.js module.exports = {
  basePath: '/docs',

  async rewrites() {
    return [
      {


async rewrites() {
    return [
      {
        source: '/with-basePath', // automatically becomes /docs/with-basePath
        destination: '/another', // automatically becomes /docs/another
      },
      {
        // does not add /docs to /without-basePath since basePath: false is set
        // Note: this can not be used for internal rewrites e.g. `destination: '/another'`
        source: '/without-basePath',
        destination: 'https://example.com',
        basePath: false,
      },
    ]
  },
}
Rewrites with i18n support
When leveraging i18n support with rewrites each source and destination is automatically prefixed to handle the configured locales unless you add locale: false to the rewrite. If locale: false is used you must prefix the source and destination with a locale for it to be matched correctly.


next.config.js module.exports = {
  i18n: {
    locales: ['en', 'fr', 'de'],
    defaultLocale: 'en',
  },

  async rewrites() {
    return [
      {
        source: '/with-locale', // automatically handles all locales
        destination: '/another', // automatically passes the locale on
      },
      {
        // does not handle locales automatically since locale: false is set
        source: '/nl/with-locale-manual',
        destination: '/nl/another',
        locale: false,
      },
      {
        // this matches '/' since `en` is the defaultLocale
        source: '/en',
        destination: '/en/another',
        locale: false,
      },
      {
        // it's possible to match all locales even when locale: false is set


{
        // it's possible to match all locales even when locale: false is set
        source: '/:locale/api-alias/:path*',
        destination: '/api/:path*',
        locale: false,
      },
      {
        // this gets converted to /(en|fr|de)/(.*) so will not match the top-level
        // `/` or `/fr` routes like /:path* would
        source: '/(.*)',
        destination: '/another',
      },
    ]
  },
}
Version History
VersionChangesv13.3.0missing added.v10.2.0has added.v9.5.0Headers added.


Runtime Config
Good to know: This feature is considered legacy and does not work with Automatic Static Optimization, Output File Tracing, or React Server Components. Please use environment variables instead to avoid initialization overhead.
To add runtime configuration to your app, open next.config.js and add the publicRuntimeConfig and serverRuntimeConfig configs:
next.config.js module.exports = {
  serverRuntimeConfig: {
    // Will only be available on the server side
    mySecret: 'secret',
    secondSecret: process.env.SECOND_SECRET, // Pass through env variables
  },
  publicRuntimeConfig: {
    // Will be available on both server and client
    staticFolder: '/static',
  },
}
Place any server-only runtime config under serverRuntimeConfig.
Anything accessible to both client and server-side code should be under publicRuntimeConfig.


Anything accessible to both client and server-side code should be under publicRuntimeConfig.
A page that relies on publicRuntimeConfig must use getInitialProps or getServerSideProps or your application must have a Custom App with getInitialProps to opt-out of Automatic Static Optimization. Runtime configuration won't be available to any page (or component in a page) without being server-side rendered.
To get access to the runtime configs in your app use next/config, like so:
 import getConfig from 'next/config'
import Image from 'next/image'

// Only holds serverRuntimeConfig and publicRuntimeConfig
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig()
// Will only be available on the server-side
console.log(serverRuntimeConfig.mySecret)
// Will be available on both server-side and client-side
console.log(publicRuntimeConfig.staticFolder)

function MyImage() {
  return (
    <div>
      <Image


function MyImage() {
  return (
    <div>
      <Image
        src={`${publicRuntimeConfig.staticFolder}/logo.png`}
        alt="logo"
        layout="fill"
      />
    </div>
  )
}

export default MyImage


serverComponentsExternalPackagesDependencies used inside Server Components and Route Handlers will automatically be bundled by Next.js.
If a dependency is using Node.js specific features, you can choose to opt-out specific dependencies from the Server Components bundling and use native Node.js require.
next.config.js /** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ['@acme/ui'],
  },
}

module.exports = nextConfig
Next.js includes a short list of popular packages that currently are working on compatibility and automatically opt-ed out:
@aws-sdk/client-s3
@aws-sdk/s3-presigned-post
@blockfrost/blockfrost-js
@jpg-store/lucid-cardano
@mikro-orm/core
@mikro-orm/knex
@prisma/client
@sentry/nextjs
@sentry/node
@swc/core
argon2


@sentry/nextjs
@sentry/node
@swc/core
argon2
autoprefixer
aws-crt
bcrypt
better-sqlite3
canvas
cpu-features
cypress
eslint
express
firebase-admin
jest
jsdom
lodash
mdx-bundler
mongodb
mongoose
next-mdx-remote
next-seo
payload
pg
playwright
postcss
prettier
prisma
puppeteer
rimraf
sharp
shiki
sqlite3
tailwindcss
ts-node
typescript
vscode-oniguruma
webpack


trailingSlash
By default Next.js will redirect urls with trailing slashes to their counterpart without a trailing slash. For example /about/ will redirect to /about. You can configure this behavior to act the opposite way, where urls without trailing slashes are redirected to their counterparts with trailing slashes.
Open next.config.js and add the trailingSlash config:
next.config.js module.exports = {
  trailingSlash: true,
}
With this option set, urls like /about will redirect to /about/.
Version History
VersionChangesv9.5.0trailingSlash added.


transpilePackages
Next.js can automatically transpile and bundle dependencies from local packages (like monorepos) or from external dependencies (node_modules). This replaces the next-transpile-modules package.
next.config.js /** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
}

module.exports = nextConfig
Version History
VersionChangesv13.0.0transpilePackages added.


turbo (Experimental)
Warning: These features are experimental and will only work with next --turbo.
webpack loaders
Currently, Turbopack supports a subset of webpack's loader API, allowing you to use some webpack loaders to transform code in Turbopack.
To configure loaders, add the names of the loaders you've installed and any options in next.config.js, mapping file extensions to a list of loaders:
next.config.js module.exports = {
  experimental: {
    turbo: {
      loaders: {
        // Option format
        '.md': [
          {
            loader: '@mdx-js/loader',
            options: {
              format: 'md',
            },
          },
        ],
        // Option-less format
        '.mdx': ['@mdx-js/loader'],
      },
    },
  },
}


},
    },
  },
}
Then, given the above configuration, you can use transformed code from your app:
 import MyDoc from './my-doc.mdx'

export default function Home() {
  return <MyDoc />
}
Resolve Alias
Through next.config.js, Turbopack can be configured to modify module resolution through aliases, similar to webpack's resolve.alias configuration.
To configure resolve aliases, map imported patterns to their new destination in next.config.js:
next.config.js module.exports = {
  experimental: {
    turbo: {
      resolveAlias: {
        underscore: 'lodash',
        mocha: { browser: 'mocha/browser-entry.js' },
      },
    },
  },
}
This aliases imports of the underscore package to the lodash package. In other words, import underscore from 'underscore' will load the lodash module instead of underscore.


Turbopack also supports conditional aliasing through this field, similar to Node.js's conditional exports. At the moment only the browser condition is supported. In the case above, imports of the mocha module will be aliased to mocha/browser-entry.js when Turbopack targets browser environments.
For more information and guidance for how to migrate your app to Turbopack from webpack, see Turbopack's documentation on webpack compatibility.


typedRoutes (experimental)Experimental support for statically typed links. This feature requires using the App Router as well as TypeScript in your project.
next.config.js /** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    typedRoutes: true,
  },
}

module.exports = nextConfig


typescript
Next.js fails your production build (next build) when TypeScript errors are present in your project.
If you'd like Next.js to dangerously produce production code even when your application has errors, you can disable the built-in type checking step.
If disabled, be sure you are running type checks as part of your build or deploy process, otherwise this can be very dangerous.
Open next.config.js and enable the ignoreBuildErrors option in the typescript config:
next.config.js module.exports = {
  typescript: {
    // !! WARN !!
    // Dangerously allow production builds to successfully complete even if
    // your project has type errors.
    // !! WARN !!
    ignoreBuildErrors: true,
  },
}


urlImports
URL imports are an experimental feature that allows you to import modules directly from external servers (instead of from the local disk).
Warning: This feature is experimental. Only use domains that you trust to download and execute on your machine. Please exercise
discretion, and caution until the feature is flagged as stable.
To opt-in, add the allowed URL prefixes inside next.config.js:
next.config.js module.exports = {
  experimental: {
    urlImports: ['https://example.com/assets/', 'https://cdn.skypack.dev'],
  },
}
Then, you can import modules directly from URLs:
 import { a, b, c } from 'https://example.com/assets/some/module.js'
URL Imports can be used everywhere normal package imports can be used.
Security Model


URL Imports can be used everywhere normal package imports can be used.
Security Model
This feature is being designed with security as the top priority. To start, we added an experimental flag forcing you to explicitly allow the domains you accept URL imports from. We're working to take this further by limiting URL imports to execute in the browser sandbox using the Edge Runtime.
Lockfile
When using URL imports, Next.js will create a next.lock directory containing a lockfile and fetched assets.
This directory must be committed to Git, not ignored by .gitignore.
When running next dev, Next.js will download and add all newly discovered URL Imports to your lockfile
When running next build, Next.js will use only the lockfile to build the application for production
Typically, no network requests are needed and any outdated lockfile will cause the build to fail.
One exception is resources that respond with Cache-Control: no-cache.


One exception is resources that respond with Cache-Control: no-cache.
These resources will have a no-cache entry in the lockfile and will always be fetched from the network on each build.
Examples
Skypack
 import confetti from 'https://cdn.skypack.dev/canvas-confetti'
import { useEffect } from 'react'

export default () => {
  useEffect(() => {
    confetti()
  })
  return
Hello

}
Static Image Imports
 import Image from 'next/image'
import logo from 'https://example.com/assets/logo.png'

export default () => (

    <Image src={logo} placeholder="blur" />

)
URLs in CSS
 .className {
  background: url('https://example.com/assets/hero.jpg');
}
Asset Imports


background: url('https://example.com/assets/hero.jpg');
}
Asset Imports
 const logo = new URL('https://example.com/assets/file.txt', import.meta.url)

console.log(logo.pathname)

// prints "/_next/static/media/file.a9727b5d.txt"


Custom Webpack Config
Good to know: changes to webpack config are not covered by semver so proceed at your own risk
Before continuing to add custom webpack configuration to your application make sure Next.js doesn't already support your use-case:
CSS imports
CSS modules
Sass/SCSS imports
Sass/SCSS modules
preact
Some commonly asked for features are available as plugins:
@next/mdx
@next/bundle-analyzer
In order to extend our usage of webpack, you can define a function that extends its config inside next.config.js, like so:
next.config.js module.exports = {
  webpack: (
    config,
    { buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
  ) => {
    // Important: return the modified config
    return config
  },
}


// Important: return the modified config
    return config
  },
}
The webpack function is executed twice, once for the server and once for the client. This allows you to distinguish between client and server configuration using the isServer property.
The second argument to the webpack function is an object with the following properties:
buildId: String - The build id, used as a unique identifier between builds
dev: Boolean - Indicates if the compilation will be done in development
isServer: Boolean - It's true for server-side compilation, and false for client-side compilation
nextRuntime: String | undefined - The target runtime for server-side compilation; either "edge" or "nodejs", it's undefined for client-side compilation.
defaultLoaders: Object - Default loaders used internally by Next.js:
babel: Object - Default babel-loader configuration
Example usage of defaultLoaders.babel:
 // Example config for adding a loader that depends on babel-loader


// Example config for adding a loader that depends on babel-loader
// This source was taken from the @next/mdx plugin source:
// https://github.com/vercel/next.js/tree/canary/packages/next-mdx
module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.mdx/,
      use: [
        options.defaultLoaders.babel,
        {
          loader: '@mdx-js/loader',
          options: pluginOptions.options,
        },
      ],
    })

    return config
  },
}
nextRuntime
Notice that isServer is true when nextRuntime is "edge" or "nodejs", nextRuntime "edge" is currently for middleware and Server Components in edge runtime only.


webVitalsAttribution
When debugging issues related to Web Vitals, it is often helpful if we can pinpoint the source of the problem.
For example, in the case of Cumulative Layout Shift (CLS), we might want to know the first element that shifted when the single largest layout shift occurred.
Or, in the case of Largest Contentful Paint (LCP), we might want to identify the element corresponding to the LCP for the page.
If the LCP element is an image, knowing the URL of the image resource can help us locate the asset we need to optimize.
Pinpointing the biggest contributor to the Web Vitals score, aka attribution,
allows us to obtain more in-depth information like entries for PerformanceEventTiming, PerformanceNavigationTiming and PerformanceResourceTiming.
Attribution is disabled by default in Next.js but can be enabled per metric by specifying the following in next.config.js.
next.config.js experimental: {


next.config.js experimental: {
  webVitalsAttribution: ['CLS', 'LCP']
}
Valid attribution values are all web-vitals metrics specified in the NextWebVitalsMetric type.