---
title: "Trailing Slashes in Vue"
description: "Trailing slashes can cause duplicate content issues. Here's how to handle them in Vue Router."
canonical_url: "https://nuxtseo.com/learn-seo/vue/routes-and-rendering/trailing-slashes"
last_updated: "2026-01-29"
---

<key-takeaways>

- **Consistency is King**: Pick one format (slash or no-slash) and enforce it everywhere.
- **Server/Edge Redirects**: Always use 301 redirects at the server or edge layer. Client-side redirects are too late for SEO.
- **Canonical Tags**: Your canonical URL must strictly match your chosen format.

</key-takeaways>

A trailing slash is the "/" at the end of a URL:

- With trailing slash: `/about/`
- Without trailing slash: `/about`

While trailing slashes don't directly impact SEO rankings, they can create technical challenges:

1. **Duplicate Content**: When both `/about` and `/about/` serve the same content without proper canonicalization, search engines have to choose which version to index. While Google is generally good at figuring this out, it's better to be explicit.
2. **Crawl Budget**: On large sites, having multiple URLs for the same content can waste your [crawl budget](/learn-seo/vue/controlling-crawlers#improve-organic-traffic).
3. **Analytics Accuracy**: Different URL formats can split your analytics data, making it harder to track page performance.

The solution is simple: pick one format and stick to it by [redirecting](/learn-seo/vue/controlling-crawlers/redirects) the other and set
[canonical URLs](/learn-seo/vue/controlling-crawlers/canonical-urls).

## Vue Router Configuration

### Enforcing Trailing Slashes

Vue Router has a `strict` mode that enforces exact path matching:

```ts
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // Define all routes with trailing slashes
    { path: '/about/', component: About },
    { path: '/products/', component: Products },
    { path: '/blog/:slug/', component: BlogPost }
  ],
  strict: true // Enforce exact path matching
})
```

With `strict: true`, `/about` and `/about/` are treated as different routes.

### Removing Trailing Slashes

To remove trailing slashes consistently:

```ts
const router = createRouter({
  history: createWebHistory(),
  routes: [
    // Define all routes without trailing slashes
    { path: '/about', component: About },
    { path: '/products', component: Products },
    { path: '/blog/:slug', component: BlogPost }
  ],
  strict: true
})
```

### Client-Side Redirects

Add a navigation guard to redirect inconsistent URLs:

```ts
router.beforeEach((to, from, next) => {
  // Remove trailing slashes
  if (to.path !== '/' && to.path.endsWith('/')) {
    next({ path: to.path.slice(0, -1), query: to.query, hash: to.hash })
    return
  }

  // Or add trailing slashes
  // if (to.path !== '/' && !to.path.endsWith('/')) {
  //   next({ path: to.path + '/', query: to.query, hash: to.hash })
  //   return
  // }

  next()
})
```

**Important:** Client-side redirects don't send proper HTTP 301 status codes to search engines. Use server-side redirects for SEO.

## Server-Side & Edge Redirects

For proper SEO, redirects must happen **before** the Vue app loads.

### Edge / Platform Config (Recommended)

Modern hosting platforms (Cloudflare Pages, [Vercel](https://vercel.com), [Netlify](https://netlify.com)) often have a "Trailing Slash" setting in their dashboard or config file (e.g., `netlify.toml`, `vercel.json`). **Use this first.** It handles the redirect at the network edge, which is the fastest method.

### Nginx

Remove trailing slashes:

```nginx
rewrite ^/(.*)/$ /$1 permanent;
```

Add trailing slashes:

```nginx
rewrite ^([^.]*[^/])$ $1/ permanent;
```

### Apache

Remove trailing slashes:

```apache
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
```

Add trailing slashes:

```apache
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [R=301,L]
```

## Canonical URLs

Set canonical URLs to indicate your preferred URL format:

```vue
<script setup lang="ts">
import { useHead } from '@unhead/vue'

useHead({
  link: [
    {
      rel: 'canonical',
      href: 'https://example.com/about' // or /about/
    }
  ]
})
</script>
```

### Canonicalization Strategy

Don't just rely on redirects. Your `rel="canonical"` tag is a strong hint to Google about which version you prefer.

If you choose **no trailing slash**:

- Redirect `/about/` -> `/about` (301)
- Page `/about` should have `<link rel="canonical" href=".../about">`
- Page `/about/` (before redirect) should *technically* also point to `/about` (but the 301 handles this).

**Crucially**, ensure all internal links (`<RouterLink>` or `<NuxtLink>`) generate the correct format. If your canonical is `/about` but your menu links to `/about/`, you are sending mixed signals.

## Best Practices

1. **Choose One Format**: Pick with or without trailing slashes and stick to it site-wide.
2. **Edge/Server Redirects**: Use 301 redirects at the network level.
3. **Canonical Tags**: Always set canonical URLs to your preferred format.
4. **Internal Links**: Audit your navigation to ensure it matches your canonicals.
5. **Sitemap**: Use consistent URLs in your sitemap.

## Using Nuxt?

If you're using Nuxt, it provides automatic trailing slash handling through site config.

[Learn more in Nuxt →](/learn-seo/nuxt/routes-and-rendering/trailing-slashes)
