From 9a354ee62a24034bee233d35f0c1a54030fdb342 Mon Sep 17 00:00:00 2001 From: Djeex Date: Sat, 5 Sep 2026 17:55:36 +0200 Subject: [PATCH] Fix the 301 redirects to match the production URL scheme --- nuxt.config.ts | 132 +++++++++++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 48 deletions(-) diff --git a/nuxt.config.ts b/nuxt.config.ts index 957d4f8..78c0b6b 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -118,53 +118,89 @@ export default defineNuxtConfig({ ctx.content.contributors = getContributors(ctx.file.path) }, }, - // Permanent (301) redirects from the old site's French URLs (root-level, - // no locale prefix) to their new /fr/... equivalents, so bookmarks and - // search engine rankings carry over. + // Permanent (301) redirects from the production site's URLs to their v2 + // equivalents. Production serves English at the root (/serveex/introduction/) + // and French under /fr/ with French slugs (/fr/serveex/coeur/installation/), + // so both sets need rules. Targets carry the trailing slash to match + // `site.trailingSlash` and avoid a second hop. + // + // French pages whose old slug already matches the new one (/fr/serveex/dozzle + // and friends, where the words are the same in both languages) are absent on + // purpose: a rule there would redirect the page to itself. routeRules: { - '/apropos/bienvenue': { redirect: { to: '/fr/about/welcome', statusCode: 301 } }, - '/generalites/reseau/nat': { redirect: { to: '/fr/general/networking/nat', statusCode: 301 } }, - '/generalites/reseau/dns': { redirect: { to: '/fr/general/networking/dns', statusCode: 301 } }, - '/generalites/reseau/samba': { redirect: { to: '/fr/general/networking/samba', statusCode: 301 } }, - '/generalites/stockage/raid': { redirect: { to: '/fr/general/storage/raid', statusCode: 301 } }, - '/generalites/stockage/zfs': { redirect: { to: '/fr/general/storage/zfs', statusCode: 301 } }, - '/generalites/hardware/bases': { redirect: { to: '/fr/general/hardware/basics', statusCode: 301 } }, - '/generalites/hardware/reseau': { redirect: { to: '/fr/general/hardware/network', statusCode: 301 } }, - '/generalites/hardware/prolonas': { redirect: { to: '/fr/general/hardware/prolonas', statusCode: 301 } }, - '/serveex/introduction': { redirect: { to: '/fr/serveex/introduction', statusCode: 301 } }, - '/serveex/coeur/installation': { redirect: { to: '/fr/serveex/core/installation', statusCode: 301 } }, - '/serveex/coeur/docker': { redirect: { to: '/fr/serveex/core/docker', statusCode: 301 } }, - '/serveex/coeur/swag': { redirect: { to: '/fr/serveex/core/swag', statusCode: 301 } }, - '/serveex/securite/wireguard': { redirect: { to: '/fr/serveex/security/wireguard', statusCode: 301 } }, - '/serveex/securite/authentik': { redirect: { to: '/fr/serveex/security/authentik', statusCode: 301 } }, - '/serveex/securite/cloudflare': { redirect: { to: '/fr/serveex/security/cloudflare', statusCode: 301 } }, - '/serveex/monitoring/uptime-kuma': { redirect: { to: '/fr/serveex/monitoring/uptime-kuma', statusCode: 301 } }, - '/serveex/monitoring/dozzle': { redirect: { to: '/fr/serveex/monitoring/dozzle', statusCode: 301 } }, - '/serveex/monitoring/speedtest-tracker': { redirect: { to: '/fr/serveex/monitoring/speedtest-tracker', statusCode: 301 } }, - '/serveex/monitoring/beszel': { redirect: { to: '/fr/serveex/monitoring/beszel', statusCode: 301 } }, - '/serveex/monitoring/upsnap': { redirect: { to: '/fr/serveex/monitoring/upsnap', statusCode: 301 } }, - '/serveex/media/plex': { redirect: { to: '/fr/serveex/media/plex', statusCode: 301 } }, - '/serveex/media/qbittorrent': { redirect: { to: '/fr/serveex/media/qbittorrent', statusCode: 301 } }, - '/serveex/media/servarr': { redirect: { to: '/fr/serveex/media/servarr', statusCode: 301 } }, - '/serveex/cloud/immich': { redirect: { to: '/fr/serveex/cloud/immich', statusCode: 301 } }, - '/serveex/cloud/nextcloud': { redirect: { to: '/fr/serveex/cloud/nextcloud', statusCode: 301 } }, - '/serveex/files/file-browser': { redirect: { to: '/fr/serveex/files/file-browser', statusCode: 301 } }, - '/serveex/files/pingvin': { redirect: { to: '/fr/serveex/files/pingvin', statusCode: 301 } }, - '/serveex/development/code-server': { redirect: { to: '/fr/serveex/development/code-server', statusCode: 301 } }, - '/serveex/development/gitea': { redirect: { to: '/fr/serveex/development/gitea', statusCode: 301 } }, - '/serveex/development/it-tools': { redirect: { to: '/fr/serveex/development/it-tools', statusCode: 301 } }, - '/serveex/apps/adguard': { redirect: { to: '/fr/serveex/apps/adguard', statusCode: 301 } }, - '/serveex/apps/vaultwarden': { redirect: { to: '/fr/serveex/apps/vaultwarden', statusCode: 301 } }, - '/stockeex/introduction': { redirect: { to: '/fr/stockeex/introduction', statusCode: 301 } }, - '/betises/python/nvidia-stock-bot': { redirect: { to: '/fr/nonsense/python/nvidia-stock-bot', statusCode: 301 } }, - '/betises/python/adguard-cidre': { redirect: { to: '/fr/nonsense/python/adguard-cidre', statusCode: 301 } }, - '/betises/python/lumeex': { redirect: { to: '/fr/nonsense/python/lumeex', statusCode: 301 } }, - '/betises/python/instameex': { redirect: { to: '/fr/nonsense/python/instameex', statusCode: 301 } }, - '/betises/bash/servarr-doublons': { redirect: { to: '/fr/nonsense/bash/servarr-duplicates', statusCode: 301 } }, - '/betises/bash/luks-backup': { redirect: { to: '/fr/nonsense/bash/luks-backup', statusCode: 301 } }, - '/betises/bash/socat-proxy': { redirect: { to: '/fr/nonsense/bash/socat-proxy', statusCode: 301 } }, - '/betises/bash/hotdisk': { redirect: { to: '/fr/nonsense/bash/hotdisk', statusCode: 301 } }, - '/betises/bash/backrest-docker-stop': { redirect: { to: '/fr/nonsense/bash/backrest-docker-stop', statusCode: 301 } }, - '/Poubelle/obsolete/wireguard-14': { redirect: { to: '/fr/recycled/deprecated/wireguard-14', statusCode: 301 } }, + // English, previously served at the site root. + '/about/welcome': { redirect: { to: '/en/about/welcome/', statusCode: 301 } }, + '/general/networking/nat': { redirect: { to: '/en/general/networking/nat/', statusCode: 301 } }, + '/general/networking/dns': { redirect: { to: '/en/general/networking/dns/', statusCode: 301 } }, + '/general/networking/samba': { redirect: { to: '/en/general/networking/samba/', statusCode: 301 } }, + '/general/storage/raid': { redirect: { to: '/en/general/storage/raid/', statusCode: 301 } }, + '/general/storage/zfs': { redirect: { to: '/en/general/storage/zfs/', statusCode: 301 } }, + '/general/hardware/basics': { redirect: { to: '/en/general/hardware/basics/', statusCode: 301 } }, + '/general/hardware/network': { redirect: { to: '/en/general/hardware/network/', statusCode: 301 } }, + '/general/hardware/prolonas': { redirect: { to: '/en/general/hardware/prolonas/', statusCode: 301 } }, + '/serveex/introduction': { redirect: { to: '/en/serveex/introduction/', statusCode: 301 } }, + '/serveex/core/installation': { redirect: { to: '/en/serveex/core/installation/', statusCode: 301 } }, + '/serveex/core/docker': { redirect: { to: '/en/serveex/core/docker/', statusCode: 301 } }, + '/serveex/core/swag': { redirect: { to: '/en/serveex/core/swag/', statusCode: 301 } }, + '/serveex/security/wireguard': { redirect: { to: '/en/serveex/core/wireguard/', statusCode: 301 } }, + '/serveex/security/authentik': { redirect: { to: '/en/serveex/advanced/authentik/', statusCode: 301 } }, + '/serveex/security/cloudflare': { redirect: { to: '/en/serveex/security/cloudflare/', statusCode: 301 } }, + '/serveex/monitoring/uptime-kuma': { redirect: { to: '/en/serveex/monitoring/uptime-kuma/', statusCode: 301 } }, + '/serveex/monitoring/dozzle': { redirect: { to: '/en/serveex/monitoring/dozzle/', statusCode: 301 } }, + '/serveex/monitoring/speedtest-tracker': { redirect: { to: '/en/serveex/monitoring/speedtest-tracker/', statusCode: 301 } }, + '/serveex/monitoring/beszel': { redirect: { to: '/en/serveex/monitoring/beszel/', statusCode: 301 } }, + '/serveex/monitoring/upsnap': { redirect: { to: '/en/serveex/monitoring/upsnap/', statusCode: 301 } }, + '/serveex/media/plex': { redirect: { to: '/en/recycled/alternatives/plex/', statusCode: 301 } }, + '/serveex/media/qbittorrent': { redirect: { to: '/en/serveex/media/qbittorrent/', statusCode: 301 } }, + '/serveex/media/servarr': { redirect: { to: '/en/serveex/media/servarr/', statusCode: 301 } }, + '/serveex/cloud/immich': { redirect: { to: '/en/serveex/cloud/immich/', statusCode: 301 } }, + '/serveex/cloud/nextcloud': { redirect: { to: '/en/serveex/cloud/nextcloud/', statusCode: 301 } }, + '/serveex/files/file-browser': { redirect: { to: '/en/recycled/deprecated/file-browser/', statusCode: 301 } }, + '/serveex/files/pingvin': { redirect: { to: '/en/serveex/files/pingvin/', statusCode: 301 } }, + '/serveex/development/code-server': { redirect: { to: '/en/serveex/development/code-server/', statusCode: 301 } }, + '/serveex/development/gitea': { redirect: { to: '/en/recycled/alternatives/gitea/', statusCode: 301 } }, + '/serveex/development/it-tools': { redirect: { to: '/en/serveex/development/it-tools/', statusCode: 301 } }, + '/serveex/apps/adguard': { redirect: { to: '/en/serveex/apps/adguard/', statusCode: 301 } }, + '/serveex/apps/vaultwarden': { redirect: { to: '/en/serveex/apps/vaultwarden/', statusCode: 301 } }, + '/stockeex/introduction': { redirect: { to: '/en/stockeex/introduction/', statusCode: 301 } }, + '/nonsense/python/nvidia-stock-bot': { redirect: { to: '/en/nonsense/python/nvidia-stock-bot/', statusCode: 301 } }, + '/nonsense/python/adguard-cidre': { redirect: { to: '/en/nonsense/python/adguard-cidre/', statusCode: 301 } }, + '/nonsense/python/lumeex': { redirect: { to: '/en/nonsense/python/lumeex/', statusCode: 301 } }, + '/nonsense/python/instameex': { redirect: { to: '/en/nonsense/python/instameex/', statusCode: 301 } }, + '/nonsense/bash/servarr-duplicates': { redirect: { to: '/en/nonsense/bash/servarr-duplicates/', statusCode: 301 } }, + '/nonsense/bash/luks-backup': { redirect: { to: '/en/nonsense/bash/luks-backup/', statusCode: 301 } }, + '/nonsense/bash/socat-proxy': { redirect: { to: '/en/nonsense/bash/socat-proxy/', statusCode: 301 } }, + '/nonsense/bash/hotdisk': { redirect: { to: '/en/nonsense/bash/hotdisk/', statusCode: 301 } }, + '/nonsense/bash/backrest-docker-stop': { redirect: { to: '/en/nonsense/bash/backrest-docker-stop/', statusCode: 301 } }, + '/recycled/deprecated/wireguard-14': { redirect: { to: '/en/recycled/deprecated/wireguard-14/', statusCode: 301 } }, + // French, previously served under /fr/ with French slugs. + '/fr/apropos/bienvenue': { redirect: { to: '/fr/about/welcome/', statusCode: 301 } }, + '/fr/generalites/reseau/nat': { redirect: { to: '/fr/general/networking/nat/', statusCode: 301 } }, + '/fr/generalites/reseau/dns': { redirect: { to: '/fr/general/networking/dns/', statusCode: 301 } }, + '/fr/generalites/reseau/samba': { redirect: { to: '/fr/general/networking/samba/', statusCode: 301 } }, + '/fr/generalites/stockage/raid': { redirect: { to: '/fr/general/storage/raid/', statusCode: 301 } }, + '/fr/generalites/stockage/zfs': { redirect: { to: '/fr/general/storage/zfs/', statusCode: 301 } }, + '/fr/generalites/hardware/bases': { redirect: { to: '/fr/general/hardware/basics/', statusCode: 301 } }, + '/fr/generalites/hardware/reseau': { redirect: { to: '/fr/general/hardware/network/', statusCode: 301 } }, + '/fr/generalites/hardware/prolonas': { redirect: { to: '/fr/general/hardware/prolonas/', statusCode: 301 } }, + '/fr/serveex/coeur/installation': { redirect: { to: '/fr/serveex/core/installation/', statusCode: 301 } }, + '/fr/serveex/coeur/docker': { redirect: { to: '/fr/serveex/core/docker/', statusCode: 301 } }, + '/fr/serveex/coeur/swag': { redirect: { to: '/fr/serveex/core/swag/', statusCode: 301 } }, + '/fr/serveex/securite/wireguard': { redirect: { to: '/fr/serveex/core/wireguard/', statusCode: 301 } }, + '/fr/serveex/securite/authentik': { redirect: { to: '/fr/serveex/advanced/authentik/', statusCode: 301 } }, + '/fr/serveex/securite/cloudflare': { redirect: { to: '/fr/serveex/security/cloudflare/', statusCode: 301 } }, + '/fr/serveex/media/plex': { redirect: { to: '/fr/recycled/alternatives/plex/', statusCode: 301 } }, + '/fr/serveex/files/file-browser': { redirect: { to: '/fr/recycled/deprecated/file-browser/', statusCode: 301 } }, + '/fr/serveex/development/gitea': { redirect: { to: '/fr/recycled/alternatives/gitea/', statusCode: 301 } }, + '/fr/betises/python/nvidia-stock-bot': { redirect: { to: '/fr/nonsense/python/nvidia-stock-bot/', statusCode: 301 } }, + '/fr/betises/python/adguard-cidre': { redirect: { to: '/fr/nonsense/python/adguard-cidre/', statusCode: 301 } }, + '/fr/betises/python/lumeex': { redirect: { to: '/fr/nonsense/python/lumeex/', statusCode: 301 } }, + '/fr/betises/python/instameex': { redirect: { to: '/fr/nonsense/python/instameex/', statusCode: 301 } }, + '/fr/betises/bash/servarr-doublons': { redirect: { to: '/fr/nonsense/bash/servarr-duplicates/', statusCode: 301 } }, + '/fr/betises/bash/luks-backup': { redirect: { to: '/fr/nonsense/bash/luks-backup/', statusCode: 301 } }, + '/fr/betises/bash/socat-proxy': { redirect: { to: '/fr/nonsense/bash/socat-proxy/', statusCode: 301 } }, + '/fr/betises/bash/hotdisk': { redirect: { to: '/fr/nonsense/bash/hotdisk/', statusCode: 301 } }, + '/fr/betises/bash/backrest-docker-stop': { redirect: { to: '/fr/nonsense/bash/backrest-docker-stop/', statusCode: 301 } }, + '/fr/poubelle/obsolete/wireguard-14': { redirect: { to: '/fr/recycled/deprecated/wireguard-14/', statusCode: 301 } }, }, -}) \ No newline at end of file +})