From 3f994d4e143c027ccdb3b8291f500070d586d433 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 6 Jul 2026 14:20:50 -0400 Subject: [PATCH] Re-land /policybench vanity redirect on app-v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The /policybench and /:countryId/policybench vanity redirects to policybench.org were added to policyengine-app (v1) in #2842 after v2 took over serving policyengine.org (domain shift, 2026-03-30), so they never went live — both paths 404 on production today. Re-land them on the Next.js website host: - website/next.config.ts redirects() — the authoritative layer (this is where /pe84 resolves on prod, verified via 308 → /us/pe84). - vercel.json (root) — mirror, matching how /pe84 exists in both layers. - Cover both entries in website/src/__tests__/config/next-config.test.ts. External destination and permanent: false (307), matching the /pe84 root vercel.json entry — avoids browsers hard-caching a cross-domain jump if the vanity target ever moves. Co-Authored-By: Claude Fable 5 --- changelog_entry.yaml | 1 + vercel.json | 10 +++++++ website/next.config.ts | 13 ++++++++ .../src/__tests__/config/next-config.test.ts | 30 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/changelog_entry.yaml b/changelog_entry.yaml index eaceeef42..805a8fe31 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -5,6 +5,7 @@ - Add the Introducing PolicyBench research post - Add UK Universal Credit rebalancing analysis dashboard at /uk/uc-rebalancing - Add UK fuel duty rise cancellation analysis dashboard at /uk/cancelling-fuel-duty-rise + - Redirect the /policybench and /:countryId/policybench vanity paths to policybench.org changed: - Proxy UK Python package docs at /uk/python and UK API docs at /uk/api so the country-parameterized "Python" and "API" nav links work on UK pages - Align the calculator app header (e.g. /us/reports) with the main website header — hover-open dropdowns, per-item underline, Model dropdown with sub-items, Python link, and Events under About diff --git a/vercel.json b/vercel.json index e8677a0cf..ff31225c0 100644 --- a/vercel.json +++ b/vercel.json @@ -23,6 +23,16 @@ "source": "/pe84", "destination": "/us/pe84", "permanent": false + }, + { + "source": "/policybench", + "destination": "https://policybench.org", + "permanent": false + }, + { + "source": "/:countryId/policybench", + "destination": "https://policybench.org", + "permanent": false } ], "rewrites": [ diff --git a/website/next.config.ts b/website/next.config.ts index 9ed6f4c55..5ff5d67f2 100644 --- a/website/next.config.ts +++ b/website/next.config.ts @@ -84,6 +84,19 @@ const nextConfig: NextConfig = { destination: "/us/pe84", permanent: true, }, + // Vanity redirects to the standalone PolicyBench site (external). + // policybench.org is country-agnostic, so both the bare and + // country-prefixed paths land on its root. + { + source: "/policybench", + destination: "https://policybench.org", + permanent: false, + }, + { + source: "/:countryId/policybench", + destination: "https://policybench.org", + permanent: false, + }, { source: "/uk/ads-dashboard", destination: "/us/ads-dashboard", diff --git a/website/src/__tests__/config/next-config.test.ts b/website/src/__tests__/config/next-config.test.ts index 0bcc100df..389ec77d3 100644 --- a/website/src/__tests__/config/next-config.test.ts +++ b/website/src/__tests__/config/next-config.test.ts @@ -53,6 +53,14 @@ async function getBeforeFileRewrites() { return rewrites.beforeFiles ?? []; } +async function getRedirects() { + if (!nextConfig.redirects) { + throw new Error("Expected Next config to define redirects."); + } + + return nextConfig.redirects(); +} + describe("nextConfig rewrites", () => { test("serves PolicyEngine icon fallbacks before app-zone proxies", async () => { const beforeFiles = await getBeforeFileRewrites(); @@ -68,3 +76,25 @@ describe("nextConfig rewrites", () => { ).toBeGreaterThan(expectedPolicyEngineIconRewrites.length - 1); }); }); + +describe("nextConfig redirects", () => { + test("redirects the bare /policybench vanity path to policybench.org", async () => { + const redirects = await getRedirects(); + + expect(redirects).toContainEqual({ + source: "/policybench", + destination: "https://policybench.org", + permanent: false, + }); + }); + + test("redirects the country-prefixed /policybench vanity path to policybench.org", async () => { + const redirects = await getRedirects(); + + expect(redirects).toContainEqual({ + source: "/:countryId/policybench", + destination: "https://policybench.org", + permanent: false, + }); + }); +});