I have a nextjs (v13) app with basePath
basePath: /basePath
innextjs.config
NOT using a custom subdomain in production: https://DEPLOYED_URL/basePath/...
pages/
- index.tsx # route: DEPLOYED_URL/basePath
- subpath/index.tsx # route: DEPLOYED_URL/basePath/subpath
- index.tsx # route: DEPLOYED_URL/basePath
That works as expected but I want to add a new route matching a custom subdomain on Vercel WITHOUT showing the base path:
- subdomain: https://subdomain.DEPLOYED_URL) - This is configured via a CNAME and it's valid in "vercel domains"
- page: /new-page
- On localhost I can easily open the page (without a subdomain) at http://localhost:3000/basePath/new-page, by prepending the base path in the url
- When deployed, browser should display:
https://subdomain.DEPLOYED_URL/new-page
WITHOUT the base path
I have tried different approaches to get this to work on Vercel but neither will yield to the expected behaviour (either it's 404 on vercel or next side, or requires the base path in the url for the new page)
nextjs.config.js rewrites
rewrites() {
return {
beforeFiles: [
{
# I have also tried with a catch-all pattern: "source": "/(.*)",
"source": '/new-page'
has: [
{
type: 'host',
value: 'subdomain.DEPLOYED_URL',
},
],
destination: '/basePath/new-page'
},
]
}
}
vercel.json rewrites
{
"rewrites": [
{
"source": "/new-page",
"has": [
{
"type": "host",
"value": "subdomain.DEPLOYED_URL"
}
],
"destination": "/basePath/new-page"
}
]
}
middleware rewrites
import { NextRequest, NextResponse } from "next/server"
export const getSubdomain = (host?: string | null) => {
let subdomain: string | null = null
if (!host && typeof window !== 'undefined') {
host = window.location.host
}
if (host?.includes('.')) {
const candidate = host.split('.')[0]
if (candidate) subdomain = candidate
}
return subdomain
}
export async function middleware(req: NextRequest) {
const url = req.nextUrl.clone()
if (/\.(.*)$/.test(url.pathname) || url.pathname.includes('_next')) return
const host = req.headers.get('host')
const subdomain = getSubdomain(host)
if (subdomain) {
url.pathname = `/${subdomain}${url.pathname}`
}
return NextResponse.rewrite(url)
}
I am aware I can use a custom server for this, but I'd rather avoid that to keep the app clean and scalable.