---
title: "Trailing Slashes in Vue · Nuxt SEO"
canonical_url: "https://nuxtseo.com/learn-seo/vue/routes-and-rendering/trailing-slashes"
last_updated: "2026-07-16T12:00:00.000Z"
meta:
  author: "Harlan Wilton"
  description: "Fix duplicate content from /about vs /about/ with Vue Router strict mode, edge redirects, and matching canonical tags."
  "og:description": "Fix duplicate content from /about vs /about/ with Vue Router strict mode, edge redirects, and matching canonical tags."
  "og:title": "Trailing Slashes in Vue · Nuxt SEO"
---

Nuxt SEO on GitHub

# **Trailing Slashes in Vue**

Fix duplicate content from /about vs /about/ with Vue Router strict mode, edge redirects, and matching canonical tags.

[Harlan Wilton](https://x.com/harlan-zw)6 mins read Published **Nov 6, 2024** Updated **Jul 16, 2026**

**What you'll learn**

- Pick one URL format, with or without the trailing slash, and enforce it everywhere
- Redirect the wrong format at the server or edge layer with a 301; client-side redirects happen too late for crawlers
- Your canonical tag must match your chosen format exactly

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

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

Trailing slashes don't directly affect rankings, but they create technical problems:

- Duplicate content: `**/about**` and `**/about/**` can serve the same page without canonicalization, forcing search engines to pick which version to index
- Wasted [**~~crawl budget~~**](https://nuxtseo.com/learn-seo/vue/controlling-crawlers#improve-organic-traffic) on large sites, where multiple URLs for one page eat into how much a bot crawls
- Split analytics: different URL formats fragment traffic data for the same page

Pick one format and stick to it: [**~~redirect~~**](https://nuxtseo.com/learn-seo/vue/controlling-crawlers/redirects) the other, and set [**~~canonical URLs~~**](https://nuxtseo.com/learn-seo/vue/controlling-crawlers/canonical-urls) to match.

## 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()
})
```

Client-side redirects don't send real HTTP 301 status codes to search engines. Use server-side or edge redirects for SEO.

## Server-Side & Edge Redirects

For proper SEO, redirects must happen **before** the Vue app loads. 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, such as `**netlify.toml**` or `**vercel.json**`. Use this first, since 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>
```

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).

Also make sure all internal links (`**<RouterLink>**` or `**<NuxtLink>**`) generate the correct format. If your canonical is `**/about**` but your menu links to `**/about/**`, you're sending mixed signals.

**Checklist**

- Pick one URL format, with or without the trailing slash, for the whole site
- Enforce it in Vue Router with `**strict: true**`
- Redirect the wrong format with a 301 at the edge or server, not client-side
- Set canonical tags that match your chosen format exactly
- Audit internal links ( `**<RouterLink>**`) so they match your canonical
- Keep sitemap URLs consistent with your chosen format

If you're using Nuxt instead of Vue, it provides automatic trailing slash handling through site config: [**~~Trailing Slashes in Nuxt~~**](https://nuxtseo.com/learn-seo/nuxt/routes-and-rendering/trailing-slashes).

[**The 2026 SEO Checklist for Nuxt & Vue ** Pre-launch setup, post-launch verification, and ongoing monitoring. Interactive checklist with links to every guide.](https://nuxtseo.com/learn-seo/checklist) [Haven't launched yet? Start with the **Pre-Launch Warmup**](https://nuxtseo.com/learn-seo/pre-launch-warmup)

---

### **Related **

[**Redirects**](https://nuxtseo.com/learn-seo/vue/controlling-crawlers/redirects)

[**Canonical URLs**](https://nuxtseo.com/learn-seo/vue/controlling-crawlers/canonical-urls)

[**Trailing Slashes in Nuxt**](https://nuxtseo.com/learn-seo/nuxt/routes-and-rendering/trailing-slashes)

[**Pagination** Google indexes page 1 and buries the rest when canonicals point the wrong way. Fix pagination in Vue with self-referencing canonicals and crawlable links.](https://nuxtseo.com/learn-seo/vue/routes-and-rendering/pagination) [**Query Parameters** Query parameters create duplicate content and waste crawl budget. Here's how to handle filters, sorting, and tracking params in Vue Router.](https://nuxtseo.com/learn-seo/vue/routes-and-rendering/query-parameters)

**On this page**

- [Vue Router Configuration](#vue-router-configuration)
- [Server-Side & Edge Redirects](#server-side-edge-redirects)
- [Canonical URLs](#canonical-urls)