Redirects and Gone URLs
When you move or delete a page, other sites and search results still link to the old URL.
Use seo.redirects to list each old URL in one place, with the date you added it.
export default defineNuxtConfig({
seo: {
redirects: {
'/blog/old-post': { to: '/blog/new-post', addedAt: '2026-10-13' },
'/spring-sale': { statusCode: 410, addedAt: '2026-10-13', reason: 'The sale ended.' },
},
},
})Learn when to redirect and when to return an error in the HTTP Redirects guide.
Moved URLs
An entry with to is a moved URL. A request for the old URL gets a permanent redirect.
- The default status is
301. - If clients send a form
POSTto the old URL, setstatusCode: 308. A 308 keeps the request method. tois a path on your site, or an absolute URL on another site.- The redirect keeps the request query string.
/blog/old-post?ref=mailredirects to/blog/new-post?ref=mail.
Google treats 301 and 308 the same. It uses both as a signal that the new URL is canonical.
Redirect only to a page that replaces the old one. If you redirect many deleted pages to the home page, Google might treat the redirects as soft 404 errors. If no page replaces the old one, use a gone URL.
Gone URLs
An entry with statusCode and no to is a gone URL. A request for the old URL gets your error page with that status.
- If you deleted the content on purpose, use
410. - If you prefer the plain not found status, use
404.
Google treats 404 and 410 the same, and removes the URL from its index. A 410 also tells clients that the removal is likely permanent.
reason is a private note. The module never sends it to visitors.
Paths and Patterns
Write each key as a path without app.baseURL. The module adds the base URL to each path target.
A trailing /** matches the path and every path below it.
To keep the rest of the path, end to with /**:
export default defineNuxtConfig({
seo: {
redirects: {
// /docs/v1/setup redirects to /docs/setup
'/docs/v1/**': { to: '/docs/**', addedAt: '2026-10-13' },
// every path below /legacy redirects to one page
'/legacy/**': { to: '/archive', addedAt: '2026-10-13' },
},
},
})- A trailing slash on a request does not change the match.
/blog/old-post/matches/blog/old-post. - An exact key wins over a
/**key. A longer/**key wins over a shorter one. - Keys cannot contain a query string, a hash,
:params, or a*in the middle. - A target can contain
/**only at its end.
i18n
If the site uses an i18n prefix strategy, each unprefixed entry also applies under each locale prefix.
With prefix_except_default, /old redirects to /new, and /fr/old redirects to /fr/new.
Sites with differentDomains or multiDomainLocales get no copies.
If a locale uses a translated path, add an entry for it. An entry that starts with a locale prefix applies only to that locale.
export default defineNuxtConfig({
seo: {
redirects: {
'/about-us': { to: '/about', addedAt: '2026-10-13' },
'/fr/a-propos-de-nous': { to: '/fr/a-propos', addedAt: '2026-10-13' },
},
},
})Review Instead of Expiry
No entry expires on its own. A redirect keeps working until you delete it.
Google advises that you keep redirects as long as possible, generally at least one year. For users, Google suggests that you keep them indefinitely. After you remove a redirect, new links to the old URL stop passing signals to the new URL.
So the module schedules a review instead of an expiry.
If an entry is older than redirectReviewAfterDays (365 by default), nuxt dev and nuxt build list it.
The age counts from the later of addedAt and reviewedAt.
[nuxt-seo-utils] WARN 1 seo.redirects entry is due for review (older than 365 days):
- /blog/old-post → /blog/new-post (since 2025-10-13, 365 days)
If an old URL still gets visits or backlinks, keep it and set reviewedAt to today.
If it gets none, you can delete the entry.To review an entry, check the recent visits to the old URL in your server logs or analytics. Also check whether other sites still link to the old URL.
- If the old URL still gets visits or links, keep the entry and set
reviewedAtto today. The review clock restarts from that date. - If the old URL gets no visits and no links, you can delete the entry.
export default defineNuxtConfig({
seo: {
redirects: {
'/blog/old-post': { to: '/blog/new-post', addedAt: '2025-10-13', reviewedAt: '2026-10-13' },
},
},
})To change the window, set redirectReviewAfterDays. To turn off the review, set it to false.
Browser Caching
Chrome can cache a 301 or 308 redirect with no end date.
So each redirect sends Cache-Control: public, max-age=3600.
A later fix or removal then reaches returning visitors within an hour.
If a headers route rule sets Cache-Control for the same path, the module keeps that value.
Redirect Chains
Each hop in a chain adds a request. Google follows up to 10 hops. Google advises that you redirect straight to the final URL.
The module flattens chains in your entries. With /a to /b and /b to /c, a request for /a goes to /c in one hop.
The build lists each chain that it flattened.
- If entries form a loop, such as
/ato/band/bto/a, the build stops with an error. - If a moved URL redirects to a gone URL, the build warns. Pick a live target, or make the old URL a gone URL.
- If an entry is not valid, the build stops with an error.
- If
addedAtorreviewedAtis not a valid date, the build warns. The entry still works, but the review skips it.
Long Lists
For a long list, keep the entries in their own file and import it in your Nuxt config.
The Redirects type checks each entry.
import type { Redirects } from 'nuxt-seo-utils'
export default {
'/blog/old-post': { to: '/blog/new-post', addedAt: '2026-10-13' },
'/spring-sale': { statusCode: 410, addedAt: '2026-10-13' },
} satisfies Redirectsimport redirects from './redirects'
export default defineNuxtConfig({
seo: { redirects },
})Static Hosting
A static host has no Nuxt server, so it cannot run the redirects.
When you run nuxt generate, each exact moved URL becomes an HTML page with an instant meta refresh to the target.
Google treats an instant meta refresh as a permanent redirect.
A static build cannot send a 410 status or match a /** key. The build lists these entries.
If you need them on a static host, add rules to your host configuration. Otherwise the host returns its 404 page.
Client-Side Navigation
The redirects run on the server. A NuxtLink to an old URL behaves in one of two ways:
- If no page matches the old URL, Nuxt loads the URL from the server. The redirect then applies.
- If a catch-all page such as
[...slug].vuematches the old URL, the app renders that page. The redirect does not apply.
Update your links to point at the new URL. Nuxt Link Checker flags links to a 301 redirect.
Other Modules
- With Nuxt Sitemap, the module adds
sitemap: falseto each old URL. The sitemap then leaves it out, including its locale copies. - On a server build, the module adds
prerender: falseto each old URL. The prerender crawler then skips links to old URLs. Without this rule, it writes an HTML file that hides the redirect.
Route Rules
Nuxt routeRules also support redirect. Choose by the kind of redirect:
- For old URLs that you moved or deleted, use
seo.redirects. It adds dates, reviews, chain checks, and 410 support. It also addsapp.baseURLto each path target. - For a temporary redirect, such as a
302during maintenance, userouteRulesredirect.
Verifying
Request the old URL and read the status and location header:
curl -sI https://example.com/blog/old-post | grep -iE '^(http|location)'