From 9ad8ff073d52b5bf33747a6314c8d0f678f5b05b Mon Sep 17 00:00:00 2001 From: Dan Cormier Date: Mon, 28 Sep 2026 11:48:16 -0400 Subject: [PATCH] chore(svelte): prepare v0 docs hostname routing --- packages/stacks-svelte/netlify.toml | 16 ++++++ .../tools/netlify-config.test.js | 50 +++++++++++++++++-- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/packages/stacks-svelte/netlify.toml b/packages/stacks-svelte/netlify.toml index 813a2bc909..17dd014f71 100644 --- a/packages/stacks-svelte/netlify.toml +++ b/packages/stacks-svelte/netlify.toml @@ -17,3 +17,19 @@ to = "https://svelte.stackoverflow.design/:splat" status = 301 force = true + +# Add v0 as a production domain alias only after these rules are deployed. +# Upgrade explicitly: Netlify's automatic HTTPS redirect may not apply to proxies. +[[redirects]] + from = "http://v0.svelte.stackoverflow.design/*" + to = "https://v0.svelte.stackoverflow.design/:splat" + status = 301 + force = true + +# Keep the v2 branch deploy enabled: it remains the legacy content source. +# Use its Netlify hostname, not a custom domain that may redirect back to v0. +[[redirects]] + from = "https://v0.svelte.stackoverflow.design/*" + to = "https://v2--stacks-svelte.netlify.app/:splat" + status = 200 + force = true diff --git a/packages/stacks-svelte/tools/netlify-config.test.js b/packages/stacks-svelte/tools/netlify-config.test.js index 81759a021a..43cb0de09e 100644 --- a/packages/stacks-svelte/tools/netlify-config.test.js +++ b/packages/stacks-svelte/tools/netlify-config.test.js @@ -9,12 +9,54 @@ const netlifyConfig = readFileSync( join(toolsDirectory, "..", "netlify.toml"), "utf8" ); +const redirects = netlifyConfig + .split(/^\s*\[\[redirects\]\]\s*$/m) + .slice(1) + .map((block) => block.split("\n").map((line) => line.trim())); + +const expectedRules = [ + { + name: "redirects the beta hostname to the current documentation", + from: "https://beta.svelte.stackoverflow.design/*", + to: "https://svelte.stackoverflow.design/:splat", + status: 301, + }, + { + name: "upgrades the v0 hostname to HTTPS before proxying", + from: "http://v0.svelte.stackoverflow.design/*", + to: "https://v0.svelte.stackoverflow.design/:splat", + status: 301, + }, + { + name: "serves the existing v2 branch deploy behind the HTTPS v0 hostname", + from: "https://v0.svelte.stackoverflow.design/*", + to: "https://v2--stacks-svelte.netlify.app/:splat", + status: 200, + }, +]; describe("Netlify configuration", () => { - test("redirects the beta hostname to the current documentation", () => { - assert.match( - netlifyConfig, - /\[\[redirects\]\][\s\S]*from = "https:\/\/beta\.svelte\.stackoverflow\.design\/\*"[\s\S]*to = "https:\/\/svelte\.stackoverflow\.design\/:splat"[\s\S]*status = 301[\s\S]*force = true/ + test("limits routing rules to the beta and v0 hostnames", () => { + assert.deepStrictEqual( + redirects.map((rule) => + rule.find((line) => line.startsWith("from = ")) + ), + expectedRules.map(({ from }) => `from = "${from}"`) ); }); + + for (const { name, from, to, status } of expectedRules) { + test(name, () => { + const rule = redirects.find((lines) => + lines.includes(`from = "${from}"`) + ); + + assert.ok(rule, `Missing routing rule for ${from}`); + // Check each block independently so another rule cannot satisfy it. + // No target query string means Netlify passes query parameters through. + assert.ok(rule.includes(`to = "${to}"`)); + assert.ok(rule.includes(`status = ${status}`)); + assert.ok(rule.includes("force = true")); + }); + } });