• This repository has been archived on 25/Sep/2023
  • Stars
    star
    362
  • Rank 117,671 (Top 3 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 4 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ¦€ Express.js/Fastify middleware and virtual host for multi-tenant Next.js applications

Build Status e2e tests codecov NPM Downloads npm Commitizen friendly

Krabs is an enterprise-ready Express.js/Fastify middleware for serving thousands of different websites from a single Next.js instance.

Sponsors

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:

Examples

Express.js example

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!

Fastify example

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!

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.


More Repositories

1

gauguin

🎨 High performances Golang server for generating social share images dynamically (beta).
Go
115
star
2

vue-product-spinner

πŸš— A 3D product spinner for Vue.js with no dependencies
Vue
104
star
3

mjn

⚑️Like loadash.get, but in ~200 bytes
TypeScript
69
star
4

the-quotes-database

The repository containing the code for the "Fulltext search with ElasticSearch and Node on Docker" article
JavaScript
45
star
5

Salvini-Blocker

Simple Chrome extension that replaces Matteo Salvini's face with a cat.
JavaScript
35
star
6

CadregaLisp

🍎 Just another useless programming language, but with inganno.
Haskell
35
star
7

editorjs-go

Fast markdown/HTML generator for Editor.js
Go
33
star
8

coronablocker

🦠 Chrome extension to block any news about Covid-19 on social networks.
JavaScript
32
star
9

Emotion-Detection-ML-Example

πŸ€“ Simple Emotion Detection Neural Network made with brain.js for an article on Hackdoor
JavaScript
31
star
10

personal-website

My personal website, statically generated by Next.js
JavaScript
28
star
11

gosearch

In-memory, full-text search engine built in Go. For no particular reason.
Go
28
star
12

std

My personal TypeScript and JavaScript standard library
TypeScript
27
star
13

Aquarium

A minimalistic blockchain implementation
TypeScript
26
star
14

node-server-clustering

A simple Koa clustering example.
JavaScript
16
star
15

multitenant-nextjs

a test repository for testing Next.js' multi-tenant capabilities with a custom Express.js server
JavaScript
14
star
16

DNN-Pose-Estimator

🎩 Simple pose estimator made in Go Lang using Deep Neural Networks
Go
10
star
17

face-detection

πŸ‘€ Node.js face detection library based on OpenCv
JavaScript
10
star
18

PrimeBot

🐦 A Twitter Bot which tweets a prime number per day
Elixir
8
star
19

HackerRank-my-solutions

🍿My solutions to HackerRank problems
Haskell
8
star
20

aika

β›ˆ In-memory key-value multithreaded database
Haskell
7
star
21

unomi-node

πŸ‘€ Apache Unomi SDK for Node.js
TypeScript
5
star
22

micheleriva

4
star
23

shoulditrust

πŸ€”Check if an IP address is safe or not!
JavaScript
3
star
24

shell-snippets

🐚 Little collection of shell scripts and aliases
Shell
3
star
25

caesar-cipher

πŸ‘‘ Dead Simple Caesar Cipher written in Haskell
Haskell
3
star
26

omnixent-experimental

Experimental Omnixent implementation using Erlang and OTP
Erlang
3
star
27

omgossh

😱 Connect and execute remote SSH commands
Go
3
star
28

quotient

A massively scalable, fast, distributed quotient filter.
Go
3
star
29

H99

99 Haskell Problems (solved)!
Haskell
3
star
30

managing-authentication-in-nextjs-workshop

JavaScript
3
star
31

proposal-array-parallelMap-parallelFilter

HTML
2
star
32

ocaml-assembly-example

πŸ‘ΎJust an Assembly Hello World program compiled from OCaml ocamlopt.
Assembly
2
star
33

WordSearchGame

πŸ”  Word Search Game written in Haskell
Haskell
2
star
34

kek

πŸ—£A supercazzola generator highly inspired by Polygen
JavaScript
2
star
35

range-prototype

Extend your JavaScript Number type with a ~100 bytes polyfill
JavaScript
2
star
36

NeuroPong

πŸ“ Single player pong game controlled by the user's brain!
JavaScript
2
star
37

saferec

Easy and lightweight trampoline for your recursive functions.
JavaScript
2
star
38

ElixirIdenticon

πŸ’ A simple Elixir program which generates Identicons.
Elixir
2
star
39

realworldnextjs.com

TypeScript
2
star
40

c-vs-ts-wasm

πŸ‘½Simple repo I made for myself just to test some WebAssembly compilers.
WebAssembly
1
star
41

dat-theme

πŸ”₯ "Day After Tomorrow" Theme for Sublime Text 3
1
star
42

treesum

Blazing fast library for computing MD5 checksum of large filesystems
Go
1
star
43

high-performance-nextjs-workshop

JavaScript
1
star
44

go-brainfuck

πŸ’₯A Brainfuck compiler written in GoLang
Go
1
star
45

winnie

πŸ’ƒ C++ human detection program using webcam and OpenCV.
C++
1
star
46

introducing-elixir-exercises

πŸ’§ Introducing Elixir Exercises
Elixir
1
star
47

cvTracker

C++
1
star
48

micheleriva-talks-code

TypeScript
1
star
49

real-world-haskell-exercises

πŸ”­ Real World Haskell Exercises
Haskell
1
star