Skip to content

[WIP] Fix bad links and link checker errors#2324

Draft
krzysdz wants to merge 7 commits into
expressjs:mainfrom
krzysdz:fixing-links
Draft

[WIP] Fix bad links and link checker errors#2324
krzysdz wants to merge 7 commits into
expressjs:mainfrom
krzysdz:fixing-links

Conversation

@krzysdz
Copy link
Copy Markdown
Contributor

@krzysdz krzysdz commented May 18, 2026

Fixes #2336

TODO:

@netlify
Copy link
Copy Markdown

netlify Bot commented May 18, 2026

Deploy Preview for expressjscom-preview ready!

Name Link
🔨 Latest commit 56f9ced
🔍 Latest deploy log https://app.netlify.com/projects/expressjscom-preview/deploys/6a10e08b5ea513000822bf45
😎 Deploy Preview https://deploy-preview-2324--expressjscom-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 96 (🔴 down 1 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 100 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown
Member

@jonchurch jonchurch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM as a first pass, the slack 403 is really noisey and we should fix that asap

I dont see any failures on the linkedin share-offsite popping up in the logs though

@jonchurch
Copy link
Copy Markdown
Member

I parsed through the link checker output w/ claude, and after excluding the slack invite ones, this is the report I had it generate w/ the current failures:

Lychee follow-ups

After this PR removes the slack-invite noise (1,221 of 1,608 errors), the remaining 387 are real. Tracking the unique URLs and source locations so they can be split into follow-up PRs.

Bucket 1 — English-source bugs (each appears 10×, once per locale)

These are the highest-leverage fixes: one source edit clears ~10 errors.

  • app-set#app.settings.table (50× total) — broken anchor link in src/content/api/{4x,5x}/api/request/index.mdx. Should reference the app.set() anchor on the application page.
  • api/application/app-settings (30× total) — broken link in src/content/api/{4x,5x}/api/response/index.mdx. Missing version + locale prefix.
  • 5x/api/application/app-settings (20× total) — broken link in src/content/api/5x/api/application/index.mdx.
  • /guide/resources/middleware relative-link bug — in src/content/docs/en/{4x,5x,unversioned}/guide/using-middleware.mdx. Should be absolute (/en/resources/middleware/).
  • <https://msdn.microsoft.com/...> angle-bracket URL escaping — in src/content/docs/en/advanced/best-practice-security.md. Parens in the URL plus markdown angle-bracket autolink syntax confuse the parser.

Bucket 2 — External link rot / Node.js docs URL pattern changes

  • Node.js docs anchors moved (~50× total) in src/content/docs/en/advanced/best-practice-performance.mdx and src/content/docs/en/{4x,5x}/guide/debugging.mdx:
    • nodejs.org/api/util#util_util_inspect_object_options#utilinspectobject-options
    • nodejs.org/api/process#process_event_uncaughtexception#event-uncaughtexception
    • nodejs.org/api/cli#cli_trace_sync_io#--trace-sync-io
    • nodejs.org/api/console#console#console
    • nodejs.org/api/cluster and nodejs.org/api/domain → check current paths
  • nginx.org 404s (20× total) in best-practice-performancenginx.org/en/docs/http/{ngx_http_gzip_module,load_balancing} need updated URLs
  • freedesktop.org/.../systemd.unit 404 — check current docs URL
  • expressjs.com/guide/error-handling.html (10×) in src/content/pages/en/resources/middleware/multer.md — old .html URL format
  • expressjs.com/en/guide/behind-proxies.html (9×) in src/content/pages/en/resources/middleware/cookie-session.md — same issue
  • famfamfam.com + /lab/icons/silk/ in resources/middleware/serve-index.md — domain dead, find replacement
  • sequelizejs.com in resources/middleware/session.md — domain moved to sequelize.org
  • cyclic.sh in resources/middleware/session.md — service shut down, remove
  • mysql.com / oracle.com in resources/middleware/session.md — bot-blocked but URLs work in browser

Bucket 3 — False positives worth ignoring in CI

  • linkedin.com/in/* profile URLs (20× across 2 URLs) in src/content/blog/2026-05-18-a-new-look-for-express.md — LinkedIn 999s bot traffic on profile views. Lychee maintainers recommend --accept 200..=299,999 in workflow args (see Handle unknown status codes lycheeverse/lychee#234).
  • localhost:3000 (10×) in src/content/docs/en/guide/migrating-4.mdx — example URL, not a real link. Either add --exclude '^http://localhost' to args or use a placeholder format.

Bucket 4 — Translation pipeline bugs (Crowdin)

Translators are translating URL slugs as if they were prose. Per-locale broken links:

  • de: ressourcen/{beitragen,Gemeinschaft,Glossar,utils} — German slugs instead of canonical English
  • es: recursos/{comunidad,contribuyendo,glosario,middleware,utils}
  • fr: ressources/{communauté,contribution,glossaire} + 5 logo image paths that don't exist
  • it: resources/{contributor,glossario}
  • ja: resources/contribution
  • pt-br (worst): links to pt/resources/{community,glossário,middleware,utils} — wrong locale prefix entirely
  • pt-br: resources/middleware/cors has literal `http:/example.com"`` — markdown got mangled in translation
  • ja: developer.mozilla.org/...Cross-site_scripting%EF%BC%89... — MDN anchor with Japanese-translated text appended

Crowdin treats href="" values as translatable strings. Two paths forward:

  1. Configure Crowdin to mark URL attributes as non-translatable (its "do-not-translate" / placeholder feature)
  2. Source-side: replace hardcoded href="/de/resources/X" with JS expressions like href={/${lang}/resources/X} so URLs are generated, not translated

Coverage math

Bucket Errors after this PR Effort
1 — English-source bugs ~140 low — single-line edits
2 — Link rot ~110 medium — needs verification of replacement URLs
3 — False positives ~30 low — workflow tweak
4 — Translation slugs ~30 high — Crowdin config + cleanup pass
Total real signal ~310

@krzysdz
Copy link
Copy Markdown
Contributor Author

krzysdz commented May 19, 2026

I dont see any failures on the linkedin share-offsite popping up in the logs though

I knew I saw it somewhere. The commit that ignores it is almost a month old, but I have rebased the branch last night.

https://github.com/expressjs/expressjs.com/actions/runs/24803825545/job/72593188466#step:4:115

Screenshot_2026-05-19-07-32-03-763_org mozilla fenix

@krzysdz krzysdz changed the title [WIP] Fix link checker errors [WIP] Fix bad links and link checker errors May 19, 2026
@krzysdz krzysdz force-pushed the fixing-links branch 5 times, most recently from 1484381 to 9cc6f6c Compare May 21, 2026 00:53
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should links in non-versioned files like this lead to non-versioned API (that renders the "default version") or be hardcoded to a specific version (or maybe it is possible to use a parameter that will reference the latest/default version - e.g. ../../{{ DEFAULT_VERSION }}/api/express)?

## Don't use deprecated or vulnerable versions of Express

Express 2.x and 3.x are no longer maintained. Security and performance issues in these versions won't be fixed. Do not use them! If you haven't moved to version 4, follow the [migration guide](/en/guide/migrating-4) or consider [Commercial Support Options](/en/support#commercial-support-options).
Express 2.x and 3.x are no longer maintained. Security and performance issues in these versions won't be fixed. Do not use them! If you haven't moved to version 4, follow the [migration guide](../../guide/migrating-4) or consider [Commercial Support Options](../../support#commercial-support-options).
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the "Security best practices" docs should suggest updating to Express 4 (released 12 years ago), when Express 5 has been marked as latest for over a year.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be outdated. I know that recent security updates have been announced in blog posts, but I think it would be good to either update this page or at least direct visitors to the blog.

Comment thread src/content/pages/en/guide/migrating-4.mdx
@krzysdz
Copy link
Copy Markdown
Contributor Author

krzysdz commented May 21, 2026

It seems that relative links are not a great idea. While these are easier to run search&replace across versions and do not require changes in translations, it turns out that there are some docs (e.g. guides, but also /en/api/) available under both versioned (https://expressjs.com/en/5x/starter/installing/) and non-versioned (https://expressjs.com/en/starter/installing/) paths.
These non-versioned docs render files from 5x directories, but because the path is shorter, some relative links (that assume version in URL) break. While investigating it, I have noticed that versioned pages load with the menu open, but non-versioned do not. The menu also does not reflect the "category" (Docs, API) if the URL points to a non-versioned page that uses a versioned (5x) fallback.

I can change only the links that cause errors, but I'd like to be consistent.

@bjohansebas @jonchurch do you have any thoughts on this?

krzysdz added 7 commits May 23, 2026 01:01
Internal links have been changed to relative URLs. This should help with redirecting to translated pages (the URL won't have to be localized) and keeping the right version.
Anchors that point to headers that are localized will have to be changed.
- a few HTTP -> HTTPS
- some were updated to the URLs that they redirect to
- a few had `#` anchors updated
- fixed some doc URLs that have moved (Node.js, nginx, systemd)
- things that I could not find an up-to date link for, have been changed to Internet Archive links
- one link to an example of unsupported product has been removed (closes expressjs#2270)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Broken link to "Third-party middleware" page in Express docs

2 participants