From f630ce34fe067bc9990442e8d957d07a4632212e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Wed, 20 May 2026 09:54:44 +0200 Subject: [PATCH] feat(website): mirror prod hostname pattern on dev (apex + www) (#20753) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Drops the `website.` subdomain on dev entirely and serves the marketing site from the bare zone + `www`, mirroring how prod is served at `twenty.com` + `www.twenty.com`. Also fixes a latent root-path substitution bug in the existing www→apex redirect that was masked on prod by a CF-level redirect. ## What changes - `wrangler.jsonc` env.dev routes: `twenty-main.com` (apex) + `www.twenty-main.com` (was `website.twenty-main.com`) - `next.config.ts`: extends host-based www→apex redirect to also cover `www.twenty-main.com`, and adds explicit `source: '/'` rules for both prod + dev before the catch-all `source: '/:path*'` (the `:path*` parameter doesn't substitute properly when it matches the empty root path against an absolute destination URL — Next.js leaves the literal `:path*` in the `Location` header) ## Live verification (after redeploy) | URL | Status | Notes | |---|---|---| | `https://twenty-main.com/` | 200 | `x-opennext: 1`, `x-nextjs-cache: HIT` | | `https://twenty-main.com/pricing` | 200 | Worker SSR | | `https://www.twenty-main.com/` | 308 → `https://twenty-main.com/` | Root-redirect fix applied | | `https://www.twenty-main.com/pricing` | 308 → `https://twenty-main.com/pricing` | Path preserved | | `https://twenty.com/` | 200 | Unchanged | | `https://www.twenty.com/` | 301 → `https://twenty.com/` | Still routed via CF-level redirect, now also covered by the new explicit Next rule as a defense-in-depth | | `https://website.twenty-main.com/` | 503 | DNS record removed by wrangler when route was deleted; hostname effectively retired | ## Companion infra PR https://github.com/twentyhq/twenty-infra/pull/__ — `cloudflare/website/dev.env` + `docs/4-environments.md` updated to the new URL; also bundles the CI fix that should have landed in #683 (was pushed too late). --- packages/twenty-website/next.config.ts | 21 +++++++++++++++++++++ packages/twenty-website/wrangler.jsonc | 6 +++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/twenty-website/next.config.ts b/packages/twenty-website/next.config.ts index e53746f4e8..20b81c8f91 100644 --- a/packages/twenty-website/next.config.ts +++ b/packages/twenty-website/next.config.ts @@ -101,12 +101,33 @@ const nextConfig: LinariaConfig = { async redirects() { return [ // Canonicalise www → apex. Host-based; fires before any locale logic. + // The root-path rule must come before the :path* one — Next.js's + // path-to-regexp leaves a literal `:path*` in the Location header + // when the parameter matches empty against an absolute destination. + { + source: '/', + has: [{ type: 'host', value: 'www.twenty.com' }], + destination: 'https://twenty.com/', + permanent: true, + }, { source: '/:path*', has: [{ type: 'host', value: 'www.twenty.com' }], destination: 'https://twenty.com/:path*', permanent: true, }, + { + source: '/', + has: [{ type: 'host', value: 'www.twenty-main.com' }], + destination: 'https://twenty-main.com/', + permanent: true, + }, + { + source: '/:path*', + has: [{ type: 'host', value: 'www.twenty-main.com' }], + destination: 'https://twenty-main.com/:path*', + permanent: true, + }, // Strip the source-locale prefix: /en/foo → /foo (301). Mirrors proxy.ts Rule 1. { source: '/en', destination: '/', statusCode: 301 }, { source: '/en/:path*', destination: '/:path*', statusCode: 301 }, diff --git a/packages/twenty-website/wrangler.jsonc b/packages/twenty-website/wrangler.jsonc index ac3c9279af..968d4a994a 100644 --- a/packages/twenty-website/wrangler.jsonc +++ b/packages/twenty-website/wrangler.jsonc @@ -16,7 +16,11 @@ "name": "twenty-website-dev", "routes": [ { - "pattern": "website.twenty-main.com", + "pattern": "twenty-main.com", + "custom_domain": true, + }, + { + "pattern": "www.twenty-main.com", "custom_domain": true, }, ],