├── .gitignore
├── README.md
├── components
├── head.js
└── nav.js
├── next.config.js
├── package.json
├── pages
├── admin
│ ├── index.js
│ └── sample-page.js
└── member
│ ├── accounts
│ └── dashboard.js
│ └── index.js
├── server.js
├── static
└── favicon.ico
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 | /dist
12 | /.next
13 |
14 | # misc
15 | .DS_Store
16 | .env
17 | npm-debug.log*
18 | yarn-debug.log*
19 | yarn-error.log*
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Next.js Subdomain Example
2 |
3 | ## It uses the following as references:
4 | * https://nextjs.org/docs/advanced-features/custom-server
5 | * https://github.com/vercel/next.js/tree/canary/examples/custom-server-express
6 | * https://stackoverflow.com/a/50052939/9375533
7 |
8 | ## If we are going to run this using `next dev` we will have the following routes:
9 | * http://lvh.me:3000/admin
10 | * http://lvh.me:3000/admin/sample-page
11 | * http://lvh.me:3000/member
12 | * http://lvh.me:3000/member/accounts/dashboard
13 |
14 | ## But by running `node server.js` we will have the following routes:
15 | * http://admin.lvh.me:3000
16 | * http://admin.lvh.me:3000/sample-page
17 | * http://lvh.me:3000
18 | * http://lvh.me:3000/accounts/dashboard
19 |
20 | ## Development Setup
21 | * `git clone https://github.com/dcangulo/nextjs-subdomain-example.git`
22 | * `cd nextjs-subdomain-example`
23 | * `yarn`
24 | * `yarn dev`
25 |
--------------------------------------------------------------------------------
/components/head.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import NextHead from 'next/head'
3 | import { string } from 'prop-types'
4 |
5 | const defaultDescription = ''
6 | const defaultOGURL = ''
7 | const defaultOGImage = ''
8 |
9 | const Head = props => (
10 |
11 |
12 | {props.title || ''}
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | )
36 |
37 | Head.propTypes = {
38 | title: string,
39 | description: string,
40 | url: string,
41 | ogImage: string
42 | }
43 |
44 | export default Head
45 |
--------------------------------------------------------------------------------
/components/nav.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Link from 'next/link'
3 |
4 | const links = [
5 | { href: 'https://github.com/segmentio/create-next-app', label: 'Github' }
6 | ].map(link => {
7 | link.key = `nav-link-${link.href}-${link.label}`
8 | return link
9 | })
10 |
11 | const Nav = () => (
12 |
57 | )
58 |
59 | export default Nav
60 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | webpack: config => {
3 | // Fixes npm packages that depend on `fs` module
4 | config.node = {
5 | fs: 'empty'
6 | }
7 |
8 | return config
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-next-example-app",
3 | "scripts": {
4 | "dev": "node server.js",
5 | "build": "next build",
6 | "start": "NODE_ENV=production node server.js"
7 | },
8 | "dependencies": {
9 | "express": "^4.17.1",
10 | "next": "^9.5.2",
11 | "react": "^16.13.1",
12 | "react-dom": "^16.13.1",
13 | "vhost": "^3.0.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/pages/admin/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function Admin() {
4 | return
Admin
5 | }
6 |
--------------------------------------------------------------------------------
/pages/admin/sample-page.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function SamplePage() {
4 | return SamplePage
5 | }
6 |
--------------------------------------------------------------------------------
/pages/member/accounts/dashboard.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function MemberDashboard() {
4 | return MEMBER DASHBOARD
5 | }
6 |
--------------------------------------------------------------------------------
/pages/member/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function Member() {
4 | return Member
5 | }
6 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const next = require('next')
3 | const vhost = require('vhost')
4 |
5 | const port = process.env.PORT || 3000
6 | const dev = process.env.NODE_ENV !== 'production'
7 | const app = next({ dev })
8 | const handle = app.getRequestHandler()
9 |
10 | app.prepare().then(() => {
11 | const mainServer = express()
12 | const adminServer = express()
13 | const memberServer = express()
14 |
15 | adminServer.get('/', (req, res) => {
16 | return app.render(req, res, '/admin', req.query)
17 | })
18 |
19 | adminServer.get('/*', (req, res) => {
20 | return app.render(req, res, `/admin${req.path}`, req.query)
21 | })
22 |
23 | adminServer.all('*', (req, res) => {
24 | return handle(req, res)
25 | })
26 |
27 | memberServer.get('/', (req, res) => {
28 | return app.render(req, res, '/member', req.query)
29 | })
30 |
31 | memberServer.get('/*', (req, res) => {
32 | return app.render(req, res, `/member${req.path}`, req.query)
33 | })
34 |
35 | memberServer.all('*', (req, res) => {
36 | return handle(req, res)
37 | })
38 |
39 | mainServer.use(vhost('admin.lvh.me', adminServer))
40 | mainServer.use(vhost('lvh.me', memberServer))
41 | mainServer.use(vhost('www.lvh.me', memberServer))
42 | mainServer.listen(port, (err) => {
43 | if (err) throw err
44 |
45 | console.log(`> Ready on http://lvh.me:${port}`)
46 | })
47 | })
48 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dcangulo/nextjs-subdomain-example/f3cba73d51dbd3349ba10008565049adbee3529e/static/favicon.ico
--------------------------------------------------------------------------------