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.
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
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
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}`);
});
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
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}`);
});
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;
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}`);
});
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}`);
});
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);
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 })
});
};
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 DocumentationExpress.js Documentation
Official Express.js documentation with guides, API references, and examples.
Visit DocumentationDeployment Guide
Learn how to deploy your Node.js application to various platforms.
View Deployment GuideNeed Help with Node.js?
If you need assistance setting up your Node.js backend or have questions about implementation, I'm here to help.