DEV Community

Cover image for White Labelling
Abayomi Ogunnusi
Abayomi Ogunnusi

Posted on

4

White Labelling

White Label Application

White Labelling is a common practice in software development. It allows a single application to be used by multiple clients. Each client can have their own branding, logo, color scheme, etc. This allows the client to feel like they have their own application. The application can be customized for each client without having to create a separate application for each client. This is a common practice in the SaaS (Software as a Service) industry.

Let's create a white labelling application using Node.js, Express, and MongoDB.
We will create a simple application that allows us to create clients and users. Each client will have their own users. The User can be a Merchant or even a separate application. For simplicity, we will just call them users and keep them in the same database.

Step 1 - Create a new project

mkdir white-label-app
cd white-label-app
npm init -y
Enter fullscreen mode Exit fullscreen mode
npm install express mongoose
Enter fullscreen mode Exit fullscreen mode

Client Model

models/client.js

const mongoose = require('mongoose');

const clientSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true,
        unique: true
    },
    logo: {
        type: String,
        required: true
    },
    primaryColor: {
        type: String,
        required: true
    },
    secondaryColor: {
        type: String,
        required: true
    },
    font: {
        type: String,
        required: true
    },
    users: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    }]
});

const Client = mongoose.model('Client', clientSchema);

module.exports = Client;
Enter fullscreen mode Exit fullscreen mode

User Model

models/user.js

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const userSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: true,
        minlength: 6
    },
    client: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Client',
        required: true
    }
});

userSchema.pre('save', async function(next) {
    const user = this;
    if (user.isModified('password')) {
        user.password = await bcrypt.hash(user.password, 8);
    }
    next();
});


const User = mongoose.model('User', userSchema);

module.exports = User;
Enter fullscreen mode Exit fullscreen mode

Create the routes

routes/client.js

const express = require('express');
const router = express.Router();
const Client = require('../models/client');


router.post("/", async(req,res)=>{
    try{
        const client = new Client(req.body);
        await client.save();
        res.status(201).send(client);
    }catch(e){
        return res.status(400).json({error: e.message});

}
});


router.get("/", async(req,res)=>{
    try{
        const clients = await Client.find({});
        res.send(clients);
    }catch(e){
        return res.status(400).json({error: e.message});

}
});

router.get("/:id", async(req,res)=>{
    try{
        const client = await Client.findById(req.params.id);
        res.send(client);
    }catch(e){
        return res.status(400).json({error: e.message});

}
});


module.exports = router;
Enter fullscreen mode Exit fullscreen mode

routes/user.js

const express = require("express");
const router = express.Router();
const User = require("../models/user");
const Client = require("../models/client");

router.post("/", async (req, res) => {
  try {
    const { username, password, client } = req.body;
    if (!username || !password || !client) {
      return res.status(400).json({ error: "Please provide all fields" });
    }

    const userExist = await User.findOne({ username });
    if (userExist) {
      return res.status(400).json({ error: "User already exists" });
    }

    const clientExists = await Client.findById(client);
    console.log(clientExists);
    if (!clientExists) {
      return res.status(400).json({ error: "Client does not exist" });
    }
    const user = new User({ username, password, client: clientExists._id });
    await user.save();

    clientExists.users.push(user._id);
    await clientExists.save();

    res.status(201).send(user);
  } catch (e) {
    return res.status(400).json({ error: e.message });
  }
});

router.get("/", async (req, res) => {
  try {
    const users = await User.find({});
    res.send(users);
  } catch (e) {
    return res.status(400).json({ error: e.message });
  }
});

module.exports = router;

Enter fullscreen mode Exit fullscreen mode

index.js

const express = require('express');
const mongoose = require('mongoose');
const clientRouter = require('./routes/client');
const userRouter = require('./routes/user');

const app = express();
const port = process.env.PORT || 3000;

app.use(express.json());
app.use("/clients", clientRouter);
app.use("/users", userRouter);

mongoose.connect('mongodb://
localhost:27017/white-label-app');

app.listen(port, () => {
    console.log(`Server is up on port ${port}`);
});

mongoose.connection.on('connected', () => {
    console.log('Connected to MongoDB');
});

mongoose.connection.on('error', (error) => {
    console.log(error);
});

Enter fullscreen mode Exit fullscreen mode
node index.js
Enter fullscreen mode Exit fullscreen mode
curl -X POST -H "Content-Type: application/json" -d '{"name":"Client 1","logo":"https://via.placeholder.com/150","primaryColor":"#000000","secondaryColor":"#ffffff","font":"Arial"}' http://localhost:3000/clients
Enter fullscreen mode Exit fullscreen mode
curl -X POST -H "Content-Type: application/json" -d '{"username":"user1","password":"password","client":"5f9e9c9b9c9b9c9b9c9b9c9b"}' http://localhost:3000/users
Enter fullscreen mode Exit fullscreen mode
curl -X GET http://localhost:3000/users
Enter fullscreen mode Exit fullscreen mode
curl -X GET http://localhost:3000/users/5f9e9c9b9c9b9c9b9c9b9c9b
Enter fullscreen mode Exit fullscreen mode
curl -X GET http://localhost:3000/clients
Enter fullscreen mode Exit fullscreen mode
curl -X GET http://localhost:3000/clients/5f9e9c9b9c9b9c9b9c9b9c9b
Enter fullscreen mode Exit fullscreen mode

Break it down

Let's break it down again.

  • An application can have multiple clients.
  • Each client can have multiple users.
  • Each user can have their own username and password. Each client can have their own logo, color scheme, and font.

Conclusion

This is a very simple example of a white labelling application. You can take this further and create a more complex application. You can add more features to the application. Thank you for reading. I hope you learned something new today. Happy coding!

Questions

What approach do you take when creating a white labelling application? Do you have any tips or tricks? Let me know in the comments below.

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (1)

Collapse
 
itadorisan profile image
Itadori • Edited

Nice info and great breakdown of white labeling in SaaS! For scalability, I ensure clean separation of client-specific data and branding. Private labeling vs white labeling teqblaze.com/blog/white-label-vs-p... matters—white labeling offers broader use with fewer customizations, while private labeling targets exclusivity. Modular design and middleware for client-specific configs also streamline development.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay