nuxt-link-checker
Tested against the nuxt-link-checker release after 5.3.0 on Nuxt 4.5 (peer range Nuxt 3.9 to 5).
The module inspects every <a href> in rendered HTML with 15 rules, at build time and in dev.
It also ships two ESLint rules. Docs: https://nuxtseo.com/docs/link-checker
Setup
Config key: linkChecker. The module installs nuxt-site-config for you.
@nuxtjs/seo already includes this module. Do not add it twice.
Set site.url to the production origin. The checker resolves internal links against it (see Traps).
The trailing-slash rule reads site.trailingSlash, not a linkChecker option.
Automatic behaviour
- Build scan. After prerendering, the module inspects the links on each prerendered HTML page. It prints a tree per page, then a summary.
- Only prerendered pages are scanned. A plain
nuxt buildwith no prerendered routes runs no inspections and logsNuxt Link Checker scanned no pages. Usenuxt generate, or add routes tonitro.prerender.routes. - The whole page is scanned, including
<Teleport to="body">links. An<a>withouthrefgets ano-missing-hrefwarning unless it hasrole="button". - Default exclusions.
excludeLinksstarts with/^\/_/and/^\/llms(-[\w-]+)?\.txt$/. Your entries are added to these; they do not replace them. With a non rootapp.baseURL, the base URL is also excluded. - External links are not fetched.
fetchRemoteUrlsisfalse, so every absolute external link counts as a 200. - Links to files in
public/pass without a request. - Dev. With Nuxt DevTools on, the module adds a Link Checker DevTools tab and
/__link-checker__/*server routes. On page squiggles needshowLiveInspections: true. - ESLint. With
@nuxt/eslint, the module registerslink-checker/valid-route(error) andlink-checker/valid-sitemap-link(warn) for.vue,.ts, and.mdfiles.
Fail CI on broken links
export default defineNuxtConfig({
modules: ['nuxt-link-checker'],
site: { url: 'https://example.com' },
nitro: { prerender: { routes: ['/'], crawlLinks: true } },
linkChecker: {
failOnError: true,
report: { json: true, markdown: true },
},
})Only errors fail the build. Errors come from no-error-response, missing-hash, and no-javascript. Every other rule is a warning.
The count is the number of links with an error, not the number of errors.
With crawlLinks: true, Nitro crawls the broken link too and fails the build on its 404 before failOnError matters. To keep the build green and still get the report, set nitro.prerender.failOnError: false.
Reports
report.html, report.markdown, and report.json write link-checker-report.<ext> to .output/.
When any report is on, the console shows only the summary. Read the report file for the link list.
report.storage: a path relative to the root, orunstorageoptions.report.publish: truewrites to.output/public/__link-checker__/. It addsX-Robots-Tag: noindexand a robots.txt disallow. The report is still public.
The JSON report is an array of { route, reports }. Each report has link, textContent, error[], warning[], and fix. fix is the suggested link, such as /about for a typo /abot.
Exclude links and pages
export default defineNuxtConfig({
linkChecker: {
excludeLinks: ['/admin/**', '/api/*', /\.(pdf|zip)$/],
excludePages: ['/embed/**'],
skipInspections: ['link-text', 'no-underscores'],
},
})excludeLinksmatches the link.excludePagesmatches the page that contains the link and skips all its links.- String patterns are radix3 routes, not globs.
*is one whole segment and**is any depth./_nuxt/file_*.pdfnever matches. Use a RegExp for part of a segment. skipInspectionstakes rule ids. The ids are:absolute-site-urls,link-text,missing-hash,no-baseless,no-double-slashes,no-duplicate-query-params,no-error-response,no-javascript,no-missing-href,no-non-ascii-chars,no-underscores,no-uppercase-chars,no-whitespace,redirects,trailing-slash. An unknown id does nothing and gives no warning.
ESLint without @nuxt/eslint
// eslint.config.mjs
import linkCheckerPlugin from 'nuxt-link-checker/eslint'
import vueParser from 'vue-eslint-parser'
export default [
{
files: ['**/*.vue', '**/*.ts'],
languageOptions: { parser: vueParser },
plugins: { 'link-checker': linkCheckerPlugin },
rules: {
'link-checker/valid-route': 'error',
'link-checker/valid-sitemap-link': 'warn',
},
},
// Markdown: same plugin and rules, plus processor: 'link-checker/markdown'
]The rules read .nuxt/link-checker/routes.json. Run nuxt prepare or nuxt dev before eslint in CI.
valid-sitemap-link checks nothing until nuxt dev merges the @nuxtjs/sitemap URLs into that file.
Pass { rootDir } or { routesFile } as the rule option when ESLint runs from another directory.
Only literal links that start with / are checked. Skip one link with rel="nofollow" or an eslint-disable-next-line comment.
Traps
- No
routes.json, no ESLint errors. Withoutnuxt prepare, both ESLint rules pass every link. ESLint prints one[nuxt-link-checker] ... not foundwarning, and still exits 0. - Links to pages that are not prerendered are checked against the live site. The module sends a
HEADrequest tosite.url+ path. A new SSR only page that is not deployed yet reports a 404. A page that exists only in production passes. Add such pages toexcludeLinks, or prerender them. - Read the failure message, not only the rule id. An HTTP error reports the status the server sent. A server that rejects
HEADwith 405 or 501 gets aGETretry. A DNS error or a refused connection reportsCould not reach the link (ENOTFOUND)with the cause code. A timeout reports 408. - Rules chain on the fix. When one rule proposes a fix, later rules test the fixed link.
/about/that 404s reports only the 404, not the trailing slash. - Different results per mode. Build scans read prerender status codes. Dev scans fetch the dev server. ESLint reads route patterns only and ignores
excludeLinks.
Version limits
These v1 options are gone. The module logs a warning that names the replacement, then ignores them:
exclude: useexcludeLinks.failOn404: usefailOnError.siteUrlandtrailingSlash: setsite.urlandsite.trailingSlash.
The ESLint rules and nuxt-link-checker/eslint exist from v5.0.0.
Config
enabled(true),runOnBuild(true),failOnError(false),debug(false).fetchTimeout(10000ms),fetchRemoteUrls(false). WithfetchRemoteUrls: truethe module checks that you are online first and turns itself off if not.- Full reference: https://nuxtseo.com/docs/link-checker/api/config
Debug
/__link-checker__/debug.jsonin dev shows the resolved config, including the serialized exclude patterns.debug: truewritesdebug-link-responses.jsonnext to the reports, with the status the module used for each link.