From ef2e3050242aa98e49bbcd84d89bd53dccc3e650 Mon Sep 17 00:00:00 2001 From: krzysdz Date: Fri, 29 May 2026 01:30:08 +0200 Subject: [PATCH 1/7] Switch from directory to file format in Astro The "file" format generates "name.html" files instead of default "name/index.html". This would make old links work, even without redirects on Cloudflare level, while still allowing the current link format with no extension. https://docs.astro.build/en/reference/configuration-reference/#buildformat --- astro.config.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/astro.config.mjs b/astro.config.mjs index 557730f332..2ca7ab9029 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -21,6 +21,9 @@ const site = NETLIFY_PREVIEW_SITE || 'https://expressjs.com'; export default defineConfig({ redirects, site, + build: { + format: 'file', + }, markdown: { rehypePlugins: [ rehypeSlug, From 384eb8f1af46579db00702728f1be7e426eff1d3 Mon Sep 17 00:00:00 2001 From: krzysdz Date: Fri, 29 May 2026 01:53:39 +0200 Subject: [PATCH 2/7] Fix sidebar --- src/components/patterns/Sidebar/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/patterns/Sidebar/utils.ts b/src/components/patterns/Sidebar/utils.ts index 973e41120f..f9943cc200 100644 --- a/src/components/patterns/Sidebar/utils.ts +++ b/src/components/patterns/Sidebar/utils.ts @@ -12,7 +12,7 @@ export type SubmenuData = { }; export function normalizePath(path: string): string { - return path.replace(/\/$/, ''); + return path.replace(/(?:\/|\.html)$/, ''); } export function isVersioned(versioned: VersionPrefix[] | undefined, version: string): boolean { From 164f932721425b2706d87d2e3e6a6c7b797947b7 Mon Sep 17 00:00:00 2001 From: krzysdz Date: Fri, 29 May 2026 02:16:24 +0200 Subject: [PATCH 3/7] Fix language switching on home page --- src/i18n/utils.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts index 562188a1f8..739408ad26 100644 --- a/src/i18n/utils.ts +++ b/src/i18n/utils.ts @@ -1,7 +1,8 @@ import { ui, defaultLang, languages } from './locales'; export function getLangFromUrl(url: URL) { - const [, lang] = url.pathname.split('/'); + const strippedPathname = url.pathname.replace(/\.html$/, ''); + const [, lang] = strippedPathname.split('/'); if (lang in ui) return lang as keyof typeof ui; return defaultLang; } @@ -34,7 +35,7 @@ export function getLanguageCodes(): string[] { */ export function createLanguagePathRegex(): RegExp { const codes = getLanguageCodes().join('|'); - return new RegExp(`^/(${codes})/`); + return new RegExp(`^/(${codes})(?:/|$)`); } /** @@ -43,9 +44,10 @@ export function createLanguagePathRegex(): RegExp { export function replaceLanguageInPath(path: string, newLang: string): string { const langRegex = createLanguagePathRegex(); - if (langRegex.test(path)) { - return path.replace(langRegex, `/${newLang}/`); + const strippedPath = path.replace(/\.html$/, ''); + if (langRegex.test(strippedPath)) { + return strippedPath.replace(langRegex, `/${newLang}/`); } else { - return `/${newLang}${path}`; + return `/${newLang}${strippedPath}`; } } From 598b82aa8a06c5ce01cfbb90eeeec32e547a451b Mon Sep 17 00:00:00 2001 From: krzysdz Date: Fri, 29 May 2026 02:52:27 +0200 Subject: [PATCH 4/7] Make link checker recognize the new structure --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35c2fb19b1..9ca03ded07 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -93,10 +93,10 @@ jobs: with: args: | --root-dir $PWD/dist + --fallback-extensions html --exclude-path dist/llms.txt --exclude-path dist/llms/ --exclude-private - --remap "https://expressjs\.com\/((?:[^\/]+\/)*[^\/\.]+)\/?$ file://$PWD/dist/\$1/index.html" - --remap "https://expressjs\.com\/(.*\.html)$ file://$PWD/dist/\$1" + --remap "^https://expressjs\.com\/ file://$PWD/dist/" dist/ fail: true From d6a491a5e83e288829e200b0fa3aae08167c8c2a Mon Sep 17 00:00:00 2001 From: krzysdz Date: Fri, 29 May 2026 14:55:08 +0200 Subject: [PATCH 5/7] Fix canonical and OG URLs --- src/layouts/Layout.astro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index bfe6e71174..d53ff2f5e5 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -24,9 +24,9 @@ const pageTitle = title ? `${title} · Express.js` : 'Express.js · Node.js web application framework'; -const canonicalUrl = new URL(Astro.url.pathname, Astro.site || Astro.url.origin); +const pathname = Astro.url.pathname.replace(/\.html$/, ''); +const canonicalUrl = new URL(pathname, Astro.site || Astro.url.origin); -const pathname = Astro.url.pathname.replace(/\/$/, ''); const segments = pathname.split('/').filter(Boolean); const langSegment = segments[0] || 'en'; const restSegments = segments.slice(1); From 7c86c48b323efe7aa2d42e71b56b3f1e3d0abf07 Mon Sep 17 00:00:00 2001 From: krzysdz Date: Fri, 29 May 2026 15:00:38 +0200 Subject: [PATCH 6/7] Fix breadcrumbs --- src/utils/content.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/content.ts b/src/utils/content.ts index e656027b59..bf755936fd 100644 --- a/src/utils/content.ts +++ b/src/utils/content.ts @@ -74,7 +74,7 @@ function resolveLabel(t: (key: string) => string, labelKey?: string, segment?: s * Build breadcrumbs */ export function buildBreadcrumbs(pathname: string, t: (key: string) => string): BreadcrumbItem[] { - const segments = pathname.replace(/^\/|\/$/g, '').split('/'); + const segments = pathname.replace(/^\/|\/$|\.html$/g, '').split('/'); // Need at least lang + one content segment if (segments.length < 2) return []; From b81b00c07083e5366b3b75704c10a7f994a2bdb9 Mon Sep 17 00:00:00 2001 From: krzysdz Date: Fri, 29 May 2026 23:19:21 +0200 Subject: [PATCH 7/7] Update 404 page pattern in exclusion list --- .lycheeignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.lycheeignore b/.lycheeignore index 29bed0cc5d..8eb2faa0bf 100644 --- a/.lycheeignore +++ b/.lycheeignore @@ -10,8 +10,7 @@ https://www.npmjs.org/.* https://github.com/.* # Exclude 404 pages -dist/.*/404/index.html$ -dist/404/index.html$ +dist/(.*/)?404(\.html|/)?$ # Exclude Open Collective links https://opencollective.com/.*