diff --git a/app/services/site/domain-request-service.test.ts b/app/services/site/domain-request-service.test.ts index 493600e8..1d5e0f32 100644 --- a/app/services/site/domain-request-service.test.ts +++ b/app/services/site/domain-request-service.test.ts @@ -4,7 +4,7 @@ import * as domainRequestService from "./domain-request-service"; // Mock the domain import vi.mock("@/lib/domain", () => ({ - RESERVED_SUBDOMAINS: ["app", "www", "blog", "api"] + RESERVED_SUBDOMAINS: ["app", "www", "blog", "api", "sites"] })); describe("DomainRequestService", () => { diff --git a/lib/domain.ts b/lib/domain.ts index bc48ed28..a80b5649 100644 --- a/lib/domain.ts +++ b/lib/domain.ts @@ -26,7 +26,8 @@ export const RESERVED_SUBDOMAINS = [ "settings", "legal", "admin", - "studio" + "studio", + "sites" ]; /** diff --git a/middleware.ts b/middleware.ts index 0e2c5bbc..82e81343 100644 --- a/middleware.ts +++ b/middleware.ts @@ -3,6 +3,7 @@ import { NextResponse } from "next/server"; import { isHomePagePath, isPublicPath } from "./app/services/public-path-service"; import { getGhUsernameFromRequest, + getHostnameFromRequest, getReservedSubdomainFromRequest, isVercelPreview } from "./app/services/site/domain-request-service"; @@ -31,12 +32,35 @@ export const config = { export default withAuth( async function middleware(req: NextRequestWithAuth) { const path = req.nextUrl.pathname; + const host = (await getHostnameFromRequest(req))?.toLowerCase(); const sessionUser = req.nextauth.token?.user as SessionUser | undefined; // Helper constants for domain names, makes it easy to change later const isDevelopment = process.env.NODE_ENV === "development"; const APP_HOST = isDevelopment ? "app.market.local:3000" : "app.market.dev"; const HOMEPAGE_HOST = isDevelopment ? "studio.market.local:3000" : "studio.market.dev"; + const SITES_HOST = isDevelopment ? "sites.market.local:3000" : "sites.market.dev"; + + if (host === SITES_HOST) { + if (path.startsWith("/api")) { + return NextResponse.next(); + } + + const segments = path.split("/").filter(Boolean); + const [handle, ...rest] = segments; + + if (!handle) { + const redirectUrl = new URL(req.url); + redirectUrl.host = HOMEPAGE_HOST; + redirectUrl.pathname = "/"; + return NextResponse.redirect(redirectUrl); + } + + const remainingPath = rest.length > 0 ? `/${rest.join("/")}` : ""; + const rewritePath = `/maintainer-site/${handle}${remainingPath}${req.nextUrl.search}`; + + return NextResponse.rewrite(new URL(rewritePath, req.url)); + } // --- Decision 1: Is this the main "app" subdomain? --- const reservedSubdomain = await getReservedSubdomainFromRequest(req); @@ -135,6 +159,13 @@ export default withAuth( return true; } + const currentHost = (await getHostnameFromRequest(req))?.toLowerCase(); + const isDevelopment = process.env.NODE_ENV === "development"; + const sitesHost = isDevelopment ? "sites.market.local:3000" : "sites.market.dev"; + if (currentHost === sitesHost) { + return true; + } + // Check if the path is in the public paths list if (await isPublicPath(req.nextUrl.pathname)) { return true;