`trailingSlash` in Next.js: Behavior, SEO Impact, and Redirects

What the trailingSlash option does, the permanent redirect it produces in both directions, why the choice matters for search engines, and what else in your config it changes.

8 min read

trailingSlash in Next.js controls whether a URL ends with a slash, and which form is treated as real. It defaults to false, which means /about is the canonical URL and /about/ redirects to it.

The option lives in the config file and takes a boolean. Nothing else in your app needs to change for it to take effect.

typescripttypescript
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
  trailingSlash: true,
}
export default nextConfig

With this set, the direction reverses. A request to /about now answers with a redirect to /about/, and the slashed form is the one that serves a page.

The redirect is permanent

The normalization is not a rewrite or a silent internal mapping. Setting trailingSlash in Next.js does not quietly serve both forms, it answers the non-canonical one with a 308, the same permanent status code the config redirects use.

That matters more than it first appears. A 308 tells browsers and search engines they can cache the mapping indefinitely, so the rule you choose is one your visitors' browsers will remember.

Requesting the non-canonical form with the default settings shows it directly.

bashbash
curl -I http://localhost:3000/about/

The response is a 308 with a location header pointing at /about. Requesting /about instead returns 200 and the page, with no redirect involved.

Switching later is not instant

Because the redirect is permanent, flipping the option on an established site leaves clients that already cached the old rule following it for a while. Plan the change once rather than experimenting with it in production.

What the option does not touch

Turning the option on does not blanket every URL with a slash. Two categories keep their exact form.

  • URLs for files with an extension, such as a text file or an image, are served as requested.
  • Anything under the well-known directory is left alone, which keeps domain verification and similar files working.

This is why a request for a public file still returns 200 with the option enabled rather than redirecting to a slashed version that does not exist. It is also why you rarely need to special-case assets yourself.

The exemption is based on the path, not on what actually exists, so a route that happens to contain a dot in its final segment will be treated as a file.

To a search engine, /about and /about/ are two different URLs. If both return a page, you have two addresses serving identical content, and any signals pointing at your page are split between them.

The redirect solves this by making only one of them ever return content. Whichever form you choose becomes the single address crawlers index, and the other one hands them a permanent pointer to it.

What the option cannot fix is inconsistency in your own site. Internal links, sitemap entries, and canonical URLs should all use the form you chose, or every internal navigation costs an extra redirect hop.

Setting a canonical URL in your metadata is still worth doing alongside this. The redirect handles the slash, while a canonical tag also covers duplicate shapes it does not touch, such as tracking query strings appended to a shared link.

What else changes in your config

Enabling trailingSlash in Next.js quietly changes what other config rules need to look like, which is where most of the confusion comes from.

Rewrite and redirect source patterns are matched against the normalized URL, so patterns written before the change can stop matching. If the destination server also expects a slash, the destination needs one too.

typescripttypescript
// next.config.ts
const nextConfig: NextConfig = {
  trailingSlash: true,
  async rewrites() {
    return [{ source: '/blog/', destination: 'https://example.com/blog/' }]
  },
}

A rule written as /blog without the slash would no longer match once the option is on. Configuring rewrites covers the pattern syntax those rules share.

Static exports change too. With the option enabled, a page is emitted as an index file inside a directory rather than as a sibling HTML file, which is what most static hosts expect when serving slashed URLs.

Taking over the behavior yourself

Sometimes one site needs both forms, usually during a migration where a legacy section still expects slashes. A separate config flag disables the built-in normalization entirely.

typescripttypescript
// next.config.ts
const nextConfig: NextConfig = {
  skipTrailingSlashRedirect: true,
}

Next.js now stops adding or removing slashes, and both forms reach your routes. That means you own the problem, and doing nothing leaves you with the duplicate URLs the built-in behavior was preventing.

The usual follow-up is to handle it selectively in the proxy file, keeping slashes for the legacy prefixes and normalizing everything else. That is a real use of the proxy file, since the decision depends on the incoming path.

Treat this flag as temporary. Once the migration finishes, removing it and letting the framework normalize again is one less thing to maintain.

Common mistakes

Trailing slash problems tend to be quiet, because the site keeps working while accumulating redirect hops.

  • Linking internally to the non-canonical form, so every click pays for a redirect.
  • Generating a sitemap in one form while the config enforces the other.
  • Flipping the option to test it, then finding cached permanent redirects outlive the experiment.
  • Writing rewrite or redirect sources without the slash after turning the option on.

If a route redirects when you did not expect it, check this option before anything else. Debugging redirect loops covers how to tell a normalization hop apart from a rule of your own.

Rune AI

Rune AI

Key Insights

  • The option defaults to false, so trailing slashes are stripped by a redirect.
  • Setting it to true reverses the direction and appends the slash instead.
  • Either way the normalization is a 308, which clients may cache indefinitely.
  • Files with extensions and paths under the well-known directory are exempt.
  • Turning it on changes the source patterns your redirects and rewrites need to match.
RunePowered by Rune AI

Frequently Asked Questions

What is the default value?

False. Next.js redirects a URL with a trailing slash to the version without one, so /about/ answers with a permanent redirect to /about.

Which status code does the normalization use?

308 Permanent Redirect, in both directions. That means browsers and crawlers may cache it indefinitely, so flipping the option later does not immediately undo what clients already remember.

Are there paths that never get a trailing slash?

Yes. URLs for files with an extension keep their exact form, and anything under the well-known directory is left alone. A path like /file.txt is served as requested.

Do I still need a canonical tag if the redirect handles it?

The redirect is the main fix, since only one form ever returns a page. A canonical URL in your metadata is still worth setting because it also covers query strings and other duplicate shapes the redirect does not touch.

Conclusion

The trailingSlash option decides which URL form is real and makes the other one a permanent redirect. Pick a form early, keep internal links and sitemaps consistent with it, and remember that a 308 is cached, so switching later leaves clients following the old rule for a while.