Awesome
<img src="/misc/krabs-cover.png" />Krabs is an enterprise-ready Express.js/Fastify middleware for serving thousands of different websites from a single Next.js instance.
Sponsors
<div align="center"> <a href="https://graphcms.com?utm_source=https://github.com/micheleriva/krabs"> <img src="/misc/sponsors/sponsor-graphcms.svg" alt="GraphCMS" target="_blank" width="250px" /> </a> <br /> <a align="center" href="https://github.com/sponsors/micheleriva" target="_blank"> <b>Become a sponsor</b> </a> </div>Installation
Krabs is available on npm and can be installed as follows:
For Express.js (see on npm)
yarn add krabs
# or
npm install --save krabs
For Fastify (see on npm)
yarn add fastify-krabs
# or
npm insall --save fastify-krabs
Things to know
- Krabs forces you to use a custom server. Therefore, deployments to Vercel are not supported.
_app
and_document
pages are common to every website.
Getting Started
You can watch a video introduction on YouTube:
<a href="https://www.youtube.com/watch?v=71NRAnT4G4Q" target="_blank"> <img src="/misc/krabs-yt-intro.png" /> </a>Examples
<details> <summary><b>Express.js example</b></summary>Let's say that we want to support two different websites with just one Next.js instance, and serve them using just one Express.js server.
Write the following configuration inside a .krabs.js
or .krabs.config.js
file inside of the root of your project:
module.exports = {
tenants: [
{
name: 'website-1',
domains: [
{
development: /dev\.[a-z]*\.local\.website-1\.com/, // Regex supported!
staging: 'stage.website-1.com',
production: 'website-1.com',
},
],
},
{
name: 'website-2',
domains: [
{
development: 'local.website-2.com',
staging: 'stage.website-2.com',
production: /[\w|\d|-|_]+\.website-2.com/, // Regex supported!
},
],
},
],
};
Create an index.js
file and fill it with the following content:
const express = require('express');
const next = require('next');
const krabs = require('krabs').default;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
async function main() {
try {
await app.prepare();
const handle = app.getRequestHandler();
const server = express();
server
.get('*', (req, res) => krabs(req, res, handle, app))
.listen(3000, () => console.log('server ready'));
} catch (err) {
console.log(err.stack);
}
}
main();
Inside our .krabs.js
file, we configured two tenants with two different name
properties: website-1
and website-2
.
So now let's create two new folders inside of the Next.js' default pages/
directory:
pages/
- _app.js
- website-1
- website-2
Feel free to add any page you want inside both of these folders, as they will be treated as they were the default Next.js' pages/
folder.
Let's add the following content to pages/website-1/about.js
:
function About() {
return <div> About website 1 </div>;
}
export default About;
and the following code to pages/website-2/about.js
:
function About() {
return <div> This is website 2 </div>;
}
export default About;
Map local.website-1.com
and local.website-2.com
in your hosts file, then boot the server by typing:
node index.js
going to http://dev.pizza.local.website-1.com/about and http://local.website-2.com/about, you will see the components above rendered by the same Next.js instance!
</details> <details> <summary><b>Fastify example</b></summary>Let's say that we want to support two different websites with just one Next.js instance, and serve them using just one Express.js server.
Write the following configuration inside a .krabs.js
or .krabs.config.js
file inside of the root of your project:
module.exports = {
tenants: [
{
name: 'website-1',
domains: [
{
development: /dev\.[a-z]*\.local\.website-1\.com/, // Regex supported!
staging: 'stage.website-1.com',
production: 'website-1.com',
},
],
},
{
name: 'website-2',
domains: [
{
development: 'local.website-2.com',
staging: 'stage.website-2.com',
production: /[\w|\d|-|_]+\.website-2.com/, // Regex supported!
},
],
},
],
};
Create an index.js
file and fill it with the following content:
const fastify = require('fastify')({ trustProxy: true });
const next = require('next');
const krabs = require('../dist/fastify-krabs').default;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
async function main() {
try {
await app.prepare();
const handle = app.getRequestHandler();
fastify
.get('*', (request, reply) => krabs(request, reply, handle, app))
.listen(3000, () => console.log('server ready'));
} catch (err) {
console.log(err.stack);
}
}
main();
Inside our .krabs.js
file, we configured two tenants with two different name
properties: website-1
and website-2
.
So now let's create two new folders inside of the Next.js' default pages/
directory:
pages/
- _app.js
- website-1
- website-2
Feel free to add any page you want inside both of these folders, as they will be treated as they were the default Next.js' pages/
folder.
Let's add the following content to pages/website-1/about.js
:
function About() {
return <div> About website 1 </div>;
}
export default About;
and the following code to pages/website-2/about.js
:
function About() {
return <div> This is website 2 </div>;
}
export default About;
Map local.website-1.com
and local.website-2.com
in your hosts file, then boot the server by typing:
node index.js
going to http://dev.pizza.local.website-1.com/about and http://local.website-2.com/about, you will see the components above rendered by the same Next.js instance!
</details>Documentation
You can find the full documentation (with real code examples) here!
License
Krabs is free as in freedom and licensed under the MIT license.
<br /> <img src="/misc/krabs-bottom.png" />