Express Setup — Pehla Express Server
Express is the most popular Node.js framework — it makes building web servers much easier than raw http.createServer.
Express.js is a lightweight, unopinionated web framework for Node.js. It's the most popular Node.js framework on npm — used by companies like Swiggy, Uber, Twitter, and Netflix in their Node.js services.
Think of it like this: raw Node.js http.createServer is like cooking biryani at home — you have to do everything yourself: buy the ingredients (parse request body, handle routes, set headers), prepare (write utility functions), and cook (handle every aspect of HTTP). It's messy and takes forever.
Express is like ordering from Swiggy — you just tell it what you want (define routes), and it handles all the boilerplate (parsing, routing, headers, error handling). Swiggy's own backend is built with a similar approach — structured, scalable, and maintainable.
Here's what Express gives you out of the box:
- Routing — Clean URL-based route definitions (GET /menu, POST /orders)
- Middleware — Functions that process requests before they reach your route handlers (authentication, logging, parsing)
- Request parsing — Built-in JSON, URL-encoded, and multipart body parsing
- Error handling — Centralized error handling middleware
- Static files — Serve HTML, CSS, JS files easily
By the end of this chapter, you'll have a working Express server that can handle menu and order routes — just like a Swiggy backend!
Before we write Express code, we need to install it. Just like Swiggy needs to onboard restaurants before taking orders, we need to add Express to our project.
Step 1: Initialize a new Node.js project
mkdir swiggy-backend
cd swiggy-backend
npm init -y
This creates a package.json — your project's menu card listing all your restaurant partners (dependencies).
Step 2: Install Express
npm install express
This downloads Express and adds it to node_modules. You'll also see it added to package.json under dependencies.
Step 3: Install Nodemon (for development)
npm install --save-dev nodemon
Nodemon automatically restarts your server when you make changes — like a Swiggy delivery partner who instantly picks up new orders without you having to call them.
Your package.json should look like this:
{
"name": "swiggy-backend",
"version": "1.0.0",
"description": "Swiggy-style backend with Express",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"nodemon": "^3.0.0"
}
}
Step 4: Create a .gitignore
node_modules/
.env
Always add node_modules to .gitignore — it's like not storing all the raw ingredients inside your restaurant menu. Anyone who clones your repo runs npm install to get them.
Time to write code! Here's how you create your first Express server — your Swiggy kitchen that's ready to take orders.
server.js — The Entry Point
// server.js — Swiggy Backend Entry Point
const express = require('express');
// Create an Express application
const app = express();
// Define a port (like Swiggy's phone line for taking orders)
const PORT = 3000;
// Basic route — like Swiggy's homepage
app.get('/', (req, res) => {
res.send('🍔 Welcome to Swiggy Backend API!');
});
// Menu route — list all restaurants/menu items
app.get('/menu', (req, res) => {
res.json({
restaurant: 'Hyderabad Biryani House',
items: [
{ id: 1, name: 'Chicken Biryani', price: 250 },
{ id: 2, name: 'Mutton Biryani', price: 350 },
{ id: 3, name: 'Veg Biryani', price: 200 }
]
});
});
// Start the server — kitchen ab khula!
app.listen(PORT, () => {
console.log('🍽️ Swiggy Backend running on port ' + PORT);
});
Run it:
npm run dev # or: node server.js
Test it:
- Open
http://localhost:3000in your browser — you'll see "Welcome to Swiggy Backend API!" - Open
http://localhost:3000/menu— you'll see the JSON menu
Understanding the code:
require('express')— Import Express (like Swiggy onboarding you as a restaurant partner)express()— Creates the app (your kitchen is now set up)app.get(path, handler)— Defines a GET route (a menu item on Swiggy's menu)res.send()— Sends text/html responseres.json()— Sends JSON responseapp.listen(port, callback)— Starts the server on a specific port
That's it! 20 lines of code and you have a working API server. Now try the same with raw http.createServer... 😅
Let's see why Express is better by comparing it with raw Node.js http.createServer. It's like comparing Swiggy's automated ordering system with a home kitchen that has no system at all.
Raw Node.js version (home kitchen style):
// raw-server.js — Bina Express ke, sab kuch manually!
const http = require('http');
const server = http.createServer((req, res) => {
const { method, url } = req;
// Manually parse the URL and route it
if (url === '/' && method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('🍔 Welcome to Swiggy Backend API!');
}
else if (url === '/menu' && method === 'GET') {
const menu = {
restaurant: 'Hyderabad Biryani House',
items: [
{ id: 1, name: 'Chicken Biryani', price: 250 },
{ id: 2, name: 'Mutton Biryani', price: 350 }
]
};
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(menu));
}
else if (url === '/orders' && method === 'POST') {
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', () => {
try {
const order = JSON.parse(body);
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'Order received!', order }));
} catch (err) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid JSON' }));
}
});
}
else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
server.listen(3000, () => {
console.log('Raw server running on port 3000');
});
Express version (Swiggy style):
// express-server.js — Swiggy Style!
const express = require('express');
const app = express();
// Built-in JSON body parsing — raw Node me khud karna padta!
app.use(express.json());
app.get('/', (req, res) => {
res.send('🍔 Welcome to Swiggy Backend API!');
});
app.get('/menu', (req, res) => {
res.json({
restaurant: 'Hyderabad Biryani House',
items: [
{ id: 1, name: 'Chicken Biryani', price: 250 },
{ id: 2, name: 'Mutton Biryani', price: 350 }
]
});
});
app.post('/orders', (req, res) => {
// Body already parsed by express.json() middleware!
const order = req.body;
res.status(201).json({ status: 'Order received!', order });
});
// 404 handler — Express style
app.use((req, res) => {
res.status(404).json({ error: 'Not Found' });
});
app.listen(3000, () => {
console.log('Express server running on port 3000');
});
Key differences:
| Feature | Raw Node.js | Express |
|---|---|---|
| Routing | Manual if-else chains on URL | Clean app.get(), app.post() |
| JSON Parsing | Manual body parsing with events | app.use(express.json()) |
| Response Headers | Manual res.writeHead() | Automatic + res.status() helper |
| Error Handling | Manual try-catch everywhere | Centralized error middleware |
| 404 Handling | Last else-if in the chain | app.use() after all routes |
| Code Readability | 10 lines = 1 route | 3-4 lines per route |
Express handles 80% of HTTP boilerplate for you. You focus on writing business logic — like Swiggy focuses on delivery, not on building roads.
Now that you know Express basics, let's look at how a real Swiggy-like backend would be structured. As your app grows, you can't put everything in one file — you need a proper project structure.
Recommended project structure for a Swiggy backend:
swiggy-backend/
├── server.js # Entry point — Express app setup
├── package.json
├── .gitignore
├── .env # Environment variables (API keys, DB URLs)
├── routes/
│ ├── menu.routes.js # Menu-related routes
│ ├── order.routes.js # Order-related routes
│ └── user.routes.js # User/auth routes
├── controllers/
│ ├── menu.controller.js # Menu business logic
│ ├── order.controller.js # Order processing logic
│ └── user.controller.js # User management logic
├── models/
│ ├── menu.model.js # Menu data structure
│ ├── order.model.js # Order data structure
│ └── user.model.js # User data structure
├── middleware/
│ ├── auth.middleware.js # Authentication middleware
│ ├── logger.middleware.js # Request logging
│ └── error.middleware.js # Error handling middleware
├── utils/
│ ├── helpers.js # Helper functions
│ └── constants.js # App constants
└── config/
└── db.config.js # Database configuration
How a structured Express app works:
// server.js — Structured Express App
const express = require('express');
const menuRoutes = require('./routes/menu.routes');
const orderRoutes = require('./routes/order.routes');
const app = express();
// Global middleware
app.use(express.json());
// Routes — clean and separated
app.use('/api/menu', menuRoutes);
app.use('/api/orders', orderRoutes);
// Error handling middleware (always at the end)
app.use((err, req, res, next) => {
console.error('Error:', err.message);
res.status(500).json({ error: 'Kuch to gadbad hai bhai!' });
});
app.listen(3000);
// routes/menu.routes.js — Separate route file
const express = require('express');
const router = express.Router();
// GET /api/menu — All menu items
router.get('/', (req, res) => {
res.json({ items: ['Biryani', 'Kebabs', 'Curries'] });
});
// GET /api/menu/:id — Single menu item
router.get('/:id', (req, res) => {
res.json({ id: req.params.id, name: 'Chicken Biryani', price: 250 });
});
module.exports = router;
Why this structure matters:
- Separation of concerns — Routes define URLs, controllers handle logic, models define data
- Scalability — 100+ routes? Each in its own file, grouped by feature
- Team collaboration — 5 developers can work on 5 different route files simultaneously
- Testability — Each module can be tested in isolation
This MVC-like pattern is used by thousands of production Express apps — including Swiggy's backend services.
Key Takeaways
- ✅ Express is the most popular Node.js framework — like Swiggy for web servers
- ✅ Install with: npm install express. Use nodemon for auto-reload during development
- ✅ app.get(), app.post(), etc. define routes — much cleaner than manual if-else URL matching
- ✅ express.json() middleware handles JSON body parsing automatically
- ✅ Express vs raw Node = Swiggy vs home kitchen — Express handles 80% of HTTP boilerplate
- ✅ Use express.Router() to organize routes into separate files for scalability
- ✅ Structured projects: routes/ → controllers/ → models/ → middleware/
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login