Reputation:
I want to build a new platform using Next.js (React.js and React-router). There will be a two spaces. One front-end for users and one for the owner to allow them manage all users. I want to split both areas into two subdomains, like this:
front.domain.com panel.domain.com
React-router does not support sub-domain routing, so I tried to find another approach. I found something like that, but I am not sure that this is what I want. Please advice.
<BrowserRouter>
<Route path="/" render={props => {
const [subdomain] = window.location.hostname.split('.');
if (subdomain === 'panel') return <PanelLayout {...props}/>;
return <FrontLayout {...props}/>;
}}/>
</BrowserRouter>
Upvotes: 15
Views: 36534
Reputation: 2049
If you host on Vercel now, you can use their wildcard subdomains and have your client-side React code mount the component tree relevant to the subdomain.
Upvotes: 1
Reputation: 1387
As of today you should be able to achieve this with Vercel's Next.js multi-tenancy middleware. To read more about it have a look here https://vercel.com/guides/nextjs-multi-tenant-application
Side note: Middleware is available from Next.js's version 12 and up.
Upvotes: 3
Reputation: 1130
You check to see if the pathname
from Next's router starts with a pre-defined list of allowed sub-paths
e.g.
const subdomainPaths = {
request: '/request',
company: '/company',
};
const isSubdomainRoute = () => {
const paths = Object.values(subdomainPaths).filter((path) => router.pathname.startsWith(path));
return !!paths.length;
};
if (window.location.host.includes('subdomain.mysite') && !isSubdomainRoute()) {
// show 404 or redirect somewhere else
return <div>404 - not found</div>;
}
Full example:
export const isSSR = typeof window === 'undefined';
export default function App(props: Props) {
const { Component, pageProps } = props;
const router = useRouter();
const subdomainPaths = {
request: '/request',
company: '/company',
};
const isSubdomainRoute = () => {
const paths = Object.values(subdomainPaths).filter((path) => router.pathname.startsWith(path));
return !!paths.length;
};
if (!isSSR) {
if (window.location.host.includes('subdomain.mysite') && !isSubdomainRoute()) {
// show 404 or redirect somewhere else
return <div>404 - not found</div>;
}
}
// otherwise fallthrough to the normal Next.js return
return (
<>
<Head>
<title>My Site</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<AllTheProviders>
<Component {...pageProps} />
</AllTheProviders>
</>
);
}
Upvotes: 0
Reputation: 4747
Here’s an example of hosting multiple domains on the same Next.js site (while maintaining multiple languages and static site generation/SSG), using Next.js’ i18n system:
https://github.com/tomsoderlund/nextjs-multi-domain-locale
Vercel now supports wildcard domains (*.mysite.com) which is cool!
Upvotes: 10
Reputation: 35503
You can't split 1 Next.js app between sub-domains for several reasons. From an experience, I had a similar requirement (3 areas) I started with one app split into 3 (using sub paths)
Ended up with 3 separate Next.js apps which managed inside yarn workspaces and get deployed by a specific area.
After I've explained my experience, you can achieve a setup with a reverse-proxy such as nginx to map sub-domain to subpath in your next app.
Let's say you have 3 areas, front, admin, users.
www.domain.com/some-page
=> should be mapped to localhost:3000/front/some-page
.
users.domain.com/some-page
=> should be mapped to localhost:3000/users/some-page
.
admin.domain.com/some-page
=> should be mapped to localhost:3000/admin/some-page
.
// www.domain.com.conf
server {
listen 80;
server_name www.domain.com;
access_log /var/log/nginx/access.log main;
root html;
location / {
proxy_pass http://127.0.0.1:3000/front/; // <-- the last slash is important
}
}
// users.domain.com.conf
server {
listen 80;
server_name users.domain.com;
access_log /var/log/nginx/access.log main;
root html;
location / {
proxy_pass http://127.0.0.1:3000/users/; // <-- the last slash is important
}
}
Pay attention
Upvotes: 9
Reputation: 2107
I manage to create subdomains using a custom express server. This is a blank app with no assets, I haven't tried this yet on a real app with assets (CSS, images, etc)
I have the following pages folder structure:
pages/
├── admin/
│ ├── index.js
│ └── sample-page.js
└── member/
├── index.js
└── accounts/
└── dashboard.js
When you are using next dev
which is the default. This will produce the following routes:
But using the custom server.js
file and running our dev server using node server.js
this will produce the following routes:
The content of our server.js
file:
const express = require('express')
const next = require('next')
const vhost = require('vhost')
const port = process.env.PORT || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const mainServer = express()
const adminServer = express()
const memberServer = express()
adminServer.get('/', (req, res) => {
return app.render(req, res, '/admin', req.query)
})
adminServer.get('/*', (req, res) => {
return app.render(req, res, `/admin${req.path}`, req.query)
})
adminServer.all('*', (req, res) => {
return handle(req, res)
})
memberServer.get('/', (req, res) => {
return app.render(req, res, '/member', req.query)
})
memberServer.get('/*', (req, res) => {
return app.render(req, res, `/member${req.path}`, req.query)
})
memberServer.all('*', (req, res) => {
return handle(req, res)
})
mainServer.use(vhost('admin.lvh.me', adminServer))
mainServer.use(vhost('lvh.me', memberServer))
mainServer.use(vhost('www.lvh.me', memberServer))
mainServer.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://lvh.me:${port}`)
})
})
See the repo to see this in action.
Repo: https://github.com/dcangulo/nextjs-subdomain-example
Upvotes: 11