Back to Project Setup Guides

Node.js Backend Setup Guide

A comprehensive guide to setting up a Node.js backend with Express, including project structure, routing, controllers, and database integration.

1

Initialize a Node.js Project

Create a new directory for your project, navigate into it, and initialize a new Node.js project with default settings.

mkdir my-node-app
cd my-node-app
npm init -y
2

Install Required Dependencies

Install essential packages for your Node.js application. We'll use dotenv for environment variables and cors for handling cross-origin requests.

npm install dotenv cors
3

Create Basic Server

Create a basic HTTP server using Node.js built-in modules. This server handles basic routing and CORS.

// src/index.js
// Import required modules
const http = require('http');
const { URL } = require('url');

// Create server configuration
const PORT = process.env.PORT || 3000;

// Create a simple HTTP server
const server = http.createServer((req, res) => {
  // Parse the request URL
  const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
  
  // Set CORS headers
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  
  // Handle OPTIONS method for CORS preflight
  if (req.method === 'OPTIONS') {
    res.writeHead(204);
    res.end();
    return;
  }

  // Basic routing
  if (parsedUrl.pathname === '/') {
    // Home route
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Welcome to the Node.js API' }));
  } else if (parsedUrl.pathname === '/api/users' && req.method === 'GET') {
    // Sample users endpoint
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify([
      { id: 1, name: 'John Doe', email: 'john@example.com' },
      { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
    ]));
  } else {
    // Not found
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Not found' }));
  }
});

// Start the server
server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
4

Project Structure

Here's a recommended structure for a Node.js/Express project:

my-node-app/
├── node_modules/
├── src/
│   ├── config/         # Configuration files
│   ├── controllers/    # Route controllers
│   ├── middleware/     # Custom middleware
│   ├── models/         # Database models
│   ├── routes/         # Route definitions
│   ├── services/       # Business logic
│   ├── utils/          # Utility functions
│   └── index.js        # Entry point
├── .env                # Environment variables
├── .gitignore         # Git ignore file
├── package.json       # Dependencies
└── README.md          # Documentation
5

Setting Up Routes

Organize your routes in a separate module:

// src/routes/users.js
const users = [
  { id: 1, name: 'John Doe', email: 'john@example.com' },
  { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];

function handleUsersRoutes(req, res) {
  // Get all users
  if (req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    return res.end(JSON.stringify(users));
  }
  
  // Create a new user
  if (req.method === 'POST') {
    let body = '';
    
    req.on('data', chunk => {
      body += chunk.toString();
    });
    
    req.on('end', () => {
      try {
        const userData = JSON.parse(body);
        const newUser = {
          id: users.length + 1,
          name: userData.name,
          email: userData.email
        };
        
        users.push(newUser);
        
        res.writeHead(201, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify(newUser));
      } catch (error) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Invalid JSON' }));
      }
    });
    
    return;
  }
  
  // Method not allowed
  res.writeHead(405, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ error: 'Method not allowed' }));
}

module.exports = handleUsersRoutes;

// src/index.js
const http = require('http');
const { URL } = require('url');
const handleUsersRoutes = require('./routes/users');

const PORT = process.env.PORT || 3000;

const server = http.createServer((req, res) => {
  // Parse the request URL
  const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
  
  // Set CORS headers
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  
  // Handle OPTIONS method for CORS preflight
  if (req.method === 'OPTIONS') {
    res.writeHead(204);
    res.end();
    return;
  }

  // Basic routing
  if (parsedUrl.pathname === '/') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Welcome to the Node.js API' }));
  } else if (parsedUrl.pathname === '/api/users') {
    handleUsersRoutes(req, res);
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Not found' }));
  }
});

server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
6

Adding Controllers

Separate route handlers into controller files:

// src/controllers/userController.js
const users = [
  { id: 1, name: 'John Doe', email: 'john@example.com' },
  { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];

exports.getAllUsers = (req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(users));
};

exports.getUserById = (req, res, id) => {
  const user = users.find(u => u.id === parseInt(id));
  
  if (user) {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(user));
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'User not found' }));
  }
};

exports.createUser = (req, res) => {
  let body = '';
  
  req.on('data', chunk => {
    body += chunk.toString();
  });
  
  req.on('end', () => {
    try {
      const userData = JSON.parse(body);
      const newUser = {
        id: users.length + 1,
        name: userData.name,
        email: userData.email
      };
      
      users.push(newUser);
      
      res.writeHead(201, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(newUser));
    } catch (error) {
      res.writeHead(400, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ error: 'Invalid JSON' }));
    }
  });
};

// src/routes/users.js
const userController = require('../controllers/userController');

function handleUsersRoutes(req, res) {
  const pathSegments = req.url.split('/');
  const id = pathSegments[3]; // /api/users/:id
  
  if (req.method === 'GET') {
    if (id) {
      return userController.getUserById(req, res, id);
    }
    return userController.getAllUsers(req, res);
  }
  
  if (req.method === 'POST') {
    return userController.createUser(req, res);
  }
  
  res.writeHead(405, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ error: 'Method not allowed' }));
}

module.exports = handleUsersRoutes;
7

Environment Variables

Use environment variables for configuration:

npm install dotenv

// .env
PORT=3000
MONGODB_URI=mongodb://localhost:27017/myapp
JWT_SECRET=your_jwt_secret

// src/config/config.js
require('dotenv').config();

module.exports = {
  port: process.env.PORT || 3000,
  mongodbUri: process.env.MONGODB_URI,
  jwtSecret: process.env.JWT_SECRET
};

// src/index.js
const express = require('express');
const config = require('./config/config');

const app = express();

app.use(express.json());

// Routes

app.listen(config.port, () => {
  console.log(`Server running on port ${config.port}`);
});
8

Database Connection (MongoDB)

Connect to MongoDB using Mongoose:

npm install mongoose

// src/config/db.js
const mongoose = require('mongoose');
const config = require('./config');

const connectDB = async () => {
  try {
    await mongoose.connect(config.mongodbUri, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    });
    console.log('MongoDB connected');
  } catch (error) {
    console.error('MongoDB connection error:', error.message);
    process.exit(1);
  }
};

module.exports = connectDB;

// src/index.js
const express = require('express');
const connectDB = require('./config/db');
const config = require('./config/config');

// Connect to database
connectDB();

const app = express();

app.use(express.json());

// Routes

app.listen(config.port, () => {
  console.log(`Server running on port ${config.port}`);
});
9

Creating Models

Define Mongoose models for your data:

// src/models/User.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  email: {
    type: String,
    required: true,
    unique: true,
    trim: true,
    lowercase: true
  },
  password: {
    type: String,
    required: true
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('User', userSchema);
10

Middleware

Create custom middleware for authentication, error handling, etc.:

// src/middleware/auth.js
const jwt = require('jsonwebtoken');
const config = require('../config/config');

module.exports = (req, res, next) => {
  // Get token from header
  const token = req.header('x-auth-token');

  // Check if no token
  if (!token) {
    return res.status(401).json({ message: 'No token, authorization denied' });
  }

  // Verify token
  try {
    const decoded = jwt.verify(token, config.jwtSecret);
    req.user = decoded.user;
    next();
  } catch (err) {
    res.status(401).json({ message: 'Token is not valid' });
  }
};

// src/middleware/errorHandler.js
module.exports = (err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({
    message: 'Server Error',
    ...(process.env.NODE_ENV === 'development' && { error: err.message })
  });
};
11

Running in Development

Use nodemon for automatic server restarts during development:

npm install nodemon --save-dev

// Add to package.json
{
  "scripts": {
    "start": "node src/index.js",
    "dev": "nodemon src/index.js"
  }
}

// Run development server
npm run dev

Additional Resources

Node.js Documentation

Official Node.js documentation with comprehensive guides and API references.

Visit Documentation

Express.js Documentation

Official Express.js documentation with guides, API references, and examples.

Visit Documentation

Deployment Guide

Learn how to deploy your Node.js application to various platforms.

View Deployment Guide

Need Help with Node.js?

If you need assistance setting up your Node.js backend or have questions about implementation, I'm here to help.