NextJS Middleware Subdomain Configuration
Next.js middleware allows you to run code before a request is completed, enabling you to modify the response or redirect users based on certain conditions.
Common use case
Suppose you have a portfolio page. By default, it is accessible at http://localhost:3000/portfolio . Later, you want it available under a subdomain, e.g., portfolio.your-domain.com.
A naive approach would be to create a separate Next.js project for the portfolio, but that wastes resources.
Next.js middleware provides a cleaner solution.
You can explicitly redirect or block requests.
For example, requests to your-domain.com/portfolio
can be redirected to your main page (your-domain.com
),
effectively blocking direct access via the path.
At the same time, the middleware can allow requests from portfolio.your-domain.com
to
reach the portfolio resource(your-domain.com/portfolio
).
This ensures the portfolio page is only accessible through the designated subdomain.
Create the middleware
I’m using TypeScript in my project but the code is nearly the same for JavaScript. If you still have problems read the docs for Next.js middleware .
Create the middleware file
In your project’s root directory, create a file named middleware.ts
.
Add the code to the file
This is an example configuration for the portfolio.
subdomain.
If you are using a different subdomain name, change it in the highlighted lines.
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
console.log('MIDDLEWARE IS RUNNING:', request.nextUrl.pathname);
const url = request.nextUrl.clone();
const hostname = request.headers.get('host') || '';
// Check if it's the portfolio subdomain
if (hostname.startsWith('portfolio.')) {
// Rewrite to the portfolio page
url.pathname = `/portfolio${url.pathname}`;
return NextResponse.rewrite(url);
}
// Block direct access to /portfolio route
if (url.pathname.startsWith('/portfolio') && !hostname.startsWith('portfolio.')) {
// Redirect to the main page
return NextResponse.redirect(new URL('/', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
You can now access your page via your configured subdomain.