DEV Community

Cover image for Structuring the Server: Node.js, MongoDB, and User Models for Our CMS
WebCraft Notes
WebCraft Notes

Posted on • Originally published at webcraft-notes.com

Structuring the Server: Node.js, MongoDB, and User Models for Our CMS

If you need a source code for this tutorial you can get it here.

In our previous article, we completed the groundwork for the front-end of our CMS project. We established the main layout, incorporated fonts, and structured the client-side components. Now, it's time to shift our focus to the back-end, which will power our application.

Today, we'll dive into three crucial aspects of our Node.js project:

  1. Structuring our server-side codebase
  2. Establishing a connection to MongoDB

These steps will lay a solid foundation for our CMS's back-end functionality. As we outlined our plan then, let's jump right into the development process.

1. Structuring our server-side codebase

In the project setup process, we already created a server.js file with basic Express.js configurations to define and run our new server. However, it's not optimal to add all our code into a single server.js file, especially for large or complex projects. So in this article, we'll create a structure for our project, including folders to store our main server files, with our server.js acting as the root file. Let's break this down step-by-step, starting with routes:

In a Node.js project, routes define the endpoints of your application and specify how it should respond to client requests. They act as a map that guides incoming HTTP requests to the appropriate handler functions, allowing you to organize your application's functionality into logical sections.

To separate routes we need to create a "routes" folder in the root folder. Inside routes let's create a "users" folder that will store APIs and their controllers, it will be our typical structure and for each section, we will create a separate folder with its controlling files. users.router.js file will import the express router, and our future controller file (we will create it in a few moments later), and store a list of routes related to the user (registration, login, ext...). Also, we need to export usersRoutes for the main API.js file. Here is an example:

const express = require('express');
const usersController = require('./users.controller');
const usersRouter = express.Router();

usersRouter.post('/register', usersController.registerNewUser);

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

Okay, and controllers are responsible for handling the application's business logic and acting as an intermediary between the routes and the data models. They receive requests from the routes, process the data (often interacting with models), and send back the appropriate responses, thus separating the request-handling logic from the route definitions.

As we mentioned, we need to create a users.controller.js file, and this file will store functions that will interact with API requests, then with db (with Mongoose model in our case) and return some sort of data, or modify existing data in the DB.

const usersModel = require('../../models/users/users.model');

async function registerNewUser(req, res) {
    const {name, password, email} = req.body;
    try {
        if (name, password, email) {
            res.status(201).json({
                status: 'success',
                message: 'User created successfully',
            })
        }
    } catch (error) {
        console.log(error);
        res.status(500).json({
            status: 'error',
            message: 'Internal server error'
        });
    }
}

module.exports = {
    registerNewUser
}
Enter fullscreen mode Exit fullscreen mode

Next, we will talk about models, models in a Node.js project represent the data structure of your application and typically correspond to collections in your database. They define the shape of the documents within a collection, including the fields and their data types, and often include methods for interacting with that data.

To store our models we need to create a "models" folder in the root, and inside models we will create a separate folder for each model type. For example, we will create a "users" folder that will store users' models and users' mongoose schema. And simple user model example, that will create new users in our MongoDB database:

const users = require('./users.mongo');

async function createNewUser(payload) {
    try {
        const newUser = await users.create(payload);
        return newUser;
    } catch (error) {
        console.error('Error creating new user:', error);
        throw error;
    }
}

module.exports = {
    createNewUser
}
Enter fullscreen mode Exit fullscreen mode

Schema, our last structure part of Node js server. Mongoose schemas are blueprint definitions for MongoDB documents, specifying the structure of data for a particular collection. They allow you to define fields, validation rules, defaults, and other metadata for your models, providing a powerful way to enforce data consistency and integrity in your MongoDB databases.

We will store schemas with models in the same folders, so we simply need to create users.mongo.js, here is the code example:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    address: {
        type: String,
        default: ''
    },
    email: {
        type: String,
        required: [true, 'Please provide your email!'],
        default: ''
    },
    password: {
        type: String,
        required: [true, 'Please provide your password!'],
        default: ''
    },
    name: {
        type: String,
        default: ''
    },
});

module.exports = mongoose.model('User', userSchema);
Enter fullscreen mode Exit fullscreen mode

A schema is simply an example of a stored data structure or object. Great, now we can move on to more examples of practice.

2. Establishing a connection to MongoDB

Previously we prepared our Node js server structure and installed MongoDB on our local machine, but we still did not connect our server with Mongo, let's fix it.

First, we will create a new "services" folder in the root folder, and inside we will add a mongo.js file that will store all Mongo settings.

Inside Mongo.js file we need to import "mongoose" for using mongoose. Connection object that provides methods and properties for managing the database connection, such as connecting, disconnecting, and checking the connection status. We will create and export two functions to connect and disconnect with MongoDB. Okay let's check our whole settings file, and it will be more clear.

const mongoose = require('mongoose');
const MONGO_URL = "mongodb://0.0.0.0:27017/blog";

mongoose.connection.once('open', () => {
    console.log('MongoDB connection ready!');
});
mongoose.connection.on('error', (err) => {
    console.error(err);
});
async function mongoConnect() {
    await mongoose.connect(MONGO_URL);
}
async function mongoDisconnect() {
    await mongoose.disconnect();
}

module.exports = {
    mongoConnect,
    mongoDisconnect,
}
Enter fullscreen mode Exit fullscreen mode

So, we call the connect function that will connect through MongoDB URL our database to our Node js server, then we use the connection.once function that will log a small message if the database was connected, and connection.on the function that will log error messages if such would appear.

We finished with mongo.js file, but we need to add a connection function to the server.js file so that when the server starts it will be also connected to our database.

We will create and call the startServer function, which will connect our server to the database and after that it will create a server, and listen to our 8443 port.

const http = require('http');
const app = require('./app');
const mongo = require('./services/mongo');
const PORT = 8443;

async function startServer() {
    await mongo.mongoConnect();
    const server = http.createServer(app);
    server.listen(PORT, () => {
        console.log(`Server running on port ${PORT}`);
    })
}

startServer();
Enter fullscreen mode Exit fullscreen mode

In conclusion, we've made significant progress in structuring our Node.js backend for our CMS project. We've covered three crucial aspects:

  • We established a folder structure for our server-side codebase, separating concerns into routes, controllers, models, and schemas. This organization will make our project more maintainable and scalable as it grows.

  • We created our first model and schema for users, laying the groundwork for user management in our CMS.

  • We set up the connection to MongoDB, ensuring our application can persistently store and retrieve data.

These steps have laid a solid foundation for our CMS's backend functionality. With this structure in place, we're now well-positioned to build out more features, add additional models, and create the robust API that will power our CMS.

In our next article, we'll dive deeper into creating more complex routes, implementing authentication, and expanding our data models. Stay tuned as we continue to build our full-stack CMS from the ground up!

If you need a source code for this tutorial you can get it here.

Found this post useful? ☕ A coffee-sized contribution goes a long way in keeping me inspired! Thank you)
Buy Me A Coffee

Next step: "Building a Complete User Registration System with React and Node.js"

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

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

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay