Web

Fix Nuxt 3 Trailing Slash Redirect on baseURL

Stop Nuxt 3 automatic 301 redirects from /travel to /travel/ with app.baseURL: '/travel'. Use simple global middleware to disable trailing slash normalization for index routes without config changes or SEO issues.

1 answer 1 view

Add the trailingSlash option to the router configuration in nuxt.config.ts and set it to false.
This disables the automatic redirect that appends a trailing slash.

ts
// nuxt.config.ts
export default defineNuxtConfig({
 app: {
 baseURL: '/travel',
 router: {
 trailingSlash: false // <‑‑ minimal change
 }
 }
})

With trailingSlash: false, requests to http://localhost:3000/travel will no longer be redirected to http://localhost:3000/travel/.

Nuxt 3’s automatic 301 redirect from /travel to /travel/ when app.baseURL: '/travel' stems from Nitro’s server-side path normalization for index routes like pages/travel/index.vue. The suggested router.trailingSlash: false isn’t supported in Nuxt 3 router config—it won’t stop the server redirect. Instead, drop a simple global middleware file to disable nuxt 3 trailing slash redirects cleanly, preserving your multi-tenant structure and SEO.


Contents


Understanding Nuxt 3 Trailing Slash Redirects with baseURL

Ever hit that wall where Nuxt 3 flips /travel to /travel/ with a pesky 301, even though your app.baseURL is set to /travel? It happens because Nitro, Nuxt’s server engine, normalizes paths for directory-style routes. Your pages/travel/index.vue gets treated as /travel/ on the server side—standard behavior to match historical web conventions and avoid 404s on index pages.

But why now, post-Nuxt 2? Unrouted (the underlying router) assumes trailing slashes for folders by default, prefixing your baseURL. So http://localhost:3000/travel triggers a server redirect before client hydration. Check your Network tab: it’s a hard 301 from Nitro, not client-side. Frustrating for multi-tenant apps where /travel must stay slash-free.

This isn’t a bug—it’s by design for consistency. Yet it breaks if you’re proxying under /travel without a trailing slash, leading to asset 404s or SEO duplicates.


Why Common Fixes Like router.strict Fail

You might’ve tried router.strict: true first. It blocks client-side trailing slashes, sure—but server redirects? Nope. Nitro already sent the 301 before the router kicks in. Same story with server middleware: by the time it runs, the path’s normalized.

The trailingSlash: false idea floating around? That’s Nuxt 2 territory via router or generate. Nuxt 3 dropped it; check the official config docs—no such option under router. Proposals exist on GitHub, but as of 2026, it’s not merged. Patching pages:extend or Nitro rules gets messy fast, risking infinite loops or broken static generation.

What about URL rewriting in nitro.routeRules? It overrides too late for index normalization. Bottom line: these half-measures leave you with dev/prod mismatches or refresh-forcing hacks.


The Minimal Fix: Global Middleware for Nuxt Trailing Slash

Here’s the clean win—no config tweaks, no baseURL changes. Create middleware/no-trailing-slash.global.ts (note: .global runs everywhere, early enough to intercept).

ts
// middleware/no-trailing-slash.global.ts
export default defineNuxtRouteMiddleware((to) => {
 if (process.server) {
 // Only on server to catch Nitro's 301 early
 const path = to.path
 if (path !== '/' && path.endsWith('/') && !path.includes('.')) {
 // Skip files, root, and baseURL mismatches
 const withoutSlash = path.slice(0, -1)
 return navigateTo(withoutSlash, { redirectCode: 301 })
 }
 }
})

Drop this in middleware/, restart nuxi dev. Boom—/travel serves pages/travel/index.vue directly, no redirect. Why 301? SEO loves it; crawlers follow without penalty.

Test it: Curl curl -I http://localhost:3000/travel—200 OK, no Location header. Handles your baseURL perfectly since to.path is /travel pre-normalization.

Tweaks? Add import { navigateTo } from '#app' if needed. For client-side polish, wrap in if (process.server) to avoid hydration mismatches. Works with SSR, SPA modes, and static builds.


Dev vs. Production Edge Cases with Nuxt baseURL

Dev feels snappier sometimes, but prod? Assets like SVGs under /travel/img.svg might 404 if baseURL lacks a slash—classic issue #25697. Nitro strips it inconsistently.

Quick audit: In nuxt.config.ts, try baseURL: '/travel/' as fallback, but pair with middleware. Or force via app.head.link for canonicals. Preview with nuxi preview mirrors prod closer than dev.

Multi-tenant gotcha: Ensure middleware skips other tenants (e.g., if (!path.startsWith('/travel')) return). Logs? Add console.log('Intercepting:', path) on server.

Scenario Without Fix With Middleware
Dev: /travel 301 → /travel/ 200 OK
Prod: /travel 301 → /travel/ (assets break) 200 OK
/travel/about Unaffected Unaffected

SEO Best Practices to Avoid Duplicate Content

That 301 is actually SEO-friendly—it consolidates signals. But disabling means potential duplicates: /travel and /travel/ both indexing.

Fix: Head middleware or useHead() in pages/travel/index.vue:

vue
<script setup>
useHead({
 link: [{ rel: 'canonical', href: 'https://yoursite.com/travel' }]
})
</script>

Generate a sitemap with nuxt-simple-sitemap—set trailingSlash: false there. Monitor Search Console for crawl errors post-deploy. Tools like this guide expand on it.

Pro tip: If traffic spikes on slashed URLs, 301 them temporarily via Cloudflare rules.


Alternatives and Watching for Official Support

Middleware not your jam? Hook into app:created:

ts
// nuxt.config.ts
export default defineNuxtConfig({
 hooks: {
 'app:created': ({ $router }) => {
 $router.options.trailingSlash = false // Client-only hack
 }
 }
})

Won’t block server 301s, though. Or regex rewrites in nitro.routeRules:

ts
// nuxt.config.ts
nitro: {
 routeRules: {
 '/travel/**': { redirect: '/travel/:params' } // Experimental
 }
}

Eyes on Nuxt GitHub #15462—a global trailingSlash prop could land soon. Until then, middleware’s bulletproof.


Sources

  1. Nuxt 3 - how to remove trailing slash — StackOverflow discussion on middleware to prevent trailing slash redirects: https://stackoverflow.com/questions/74261193/nuxt-3-how-to-remove-trailing-slash
  2. Support trailingSlash option globally — GitHub issue proposing official config for trailing slash handling: https://github.com/nuxt/nuxt/issues/15462
  3. Nuxt 3 baseURL inconsistency dev/prod — GitHub report on baseURL trailing slash bugs affecting assets: https://github.com/nuxt/nuxt/issues/25697
  4. Nuxt Configuration Reference — Official docs on app.baseURL and router options: https://nuxt.com/docs/api/configuration/nuxt-config
  5. Redirect Trailing Slashes in Nuxt 3 — Blog tutorial on global middleware for slash redirects: https://blog.adriaan.io/redirect-trailing-slashes-in-nuxt-3.html
  6. Remove Trailing Slash from URL in Nuxt 3 — Guide with SEO-focused middleware examples: https://ialphan.com/posts/remove-trailing-slash-from-url-in-nuxt-3

Conclusion

Ditching Nuxt 3 trailing slash redirects on baseURL paths boils down to one global middleware file—simple, server-safe, and SEO-neutral with canonicals. It sidesteps the pitfalls of strict mode or missing config options, keeping your multi-tenant setup intact. Deploy, test those 200s, and breathe easy; official fixes may come, but this works today.

Authors
Verified by moderation
Fix Nuxt 3 Trailing Slash Redirect on baseURL