Node.js Home
How good Node.js projects usually organize their “home” — the starting point — in 2025–2026 style.
We’ll build it step by step, from simple → clean → professional.
Level 1 – Very simple home (what most tutorials teach)
index.js
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const express = require('express'); const app = express(); app.use(express.json()); app.get('/', (req, res) => { res.json({ message: 'Hello world' }); }); app.listen(3000, () => { console.log('Server running on port 3000'); }); |
→ This is okay for learning. → This is not okay for any real project.
Level 2 – Better: separate routes + basic structure
Folder structure:
|
0 1 2 3 4 5 6 7 8 9 10 |
project/ ├── index.js ├── routes/ │ └── home.route.js └── package.json |
routes/home.route.js
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const express = require('express'); const router = express.Router(); router.get('/', (req, res) => { res.json({ message: 'Welcome to API', status: 'healthy', time: new Date().toISOString() }); }); module.exports = router; |
index.js (now much cleaner)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const express = require('express'); const homeRouter = require('./routes/home.route'); const app = express(); app.use(express.json()); // Routes app.use('/', homeRouter); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server is running → http://localhost:${PORT}`); }); |
Already better. But still very basic.
Level 3 – Modern & clean home (most good projects in 2024–2026)
Folder structure we’ll aim for:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
src/ ├── index.js ← very thin entry point ├── app.js ← express app creation + middlewares ├── config/ ← configuration things │ └── index.js ├── routes/ ← all route groups │ ├── index.js ← combines all routers │ ├── health.route.js │ └── v1/ │ ├── users.route.js │ └── auth.route.js ├── middlewares/ │ ├── error.middleware.js │ └── not-found.middleware.js └── utils/ └── logger.js |
1. src/index.js – The real “home” file (should stay very clean)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// src/index.js import 'dotenv/config'; // loads .env file automatically import app from './app.js'; import { PORT } from './config/index.js'; const startServer = async () => { try { app.listen(PORT, () => { console.log(`───────────────────────────────────────`); console.log(`🚀 Server is running`); console.log(` → http://localhost:${PORT}`); console.log(` → Environment: ${process.env.NODE_ENV || 'development'}`); console.log(`───────────────────────────────────────`); }); } catch (err) { console.error('Failed to start server:', err); process.exit(1); } }; startServer(); |
→ Notice: almost no logic here → Only starts the server
2. src/app.js – Where the express app is actually created
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
// src/app.js import express from 'express'; import morgan from 'morgan'; import helmet from 'helmet'; import cors from 'cors'; import { errorHandler, notFound } from './middlewares/index.js'; import { apiRouter } from './routes/index.js'; const app = express(); // ─── Global Middlewares ────────────────────────────────────── app.use(helmet()); // security headers app.use(cors()); // adjust in production! app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true })); // Logger (only in development) if (process.env.NODE_ENV !== 'production') { app.use(morgan('dev')); } // ─── Routes ────────────────────────────────────────────────── app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', uptime: process.uptime(), timestamp: new Date().toISOString(), environment: process.env.NODE_ENV || 'development' }); }); app.use('/api', apiRouter); // all versioned APIs live here // ─── Error handling ────────────────────────────────────────── app.use(notFound); // 404 handler app.use(errorHandler); // global error handler export default app; |
3. src/routes/index.js – Combining all route groups
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// src/routes/index.js import { Router } from 'express'; import healthRouter from './health.route.js'; // import userRouter from './v1/users.route.js'; // import authRouter from './v1/auth.route.js'; const apiRouter = Router(); // apiRouter.use('/v1/users', userRouter); // apiRouter.use('/v1/auth', authRouter); // For now just health check under /api apiRouter.use('/health', healthRouter); export { apiRouter }; |
4. src/config/index.js (central place for config)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
// src/config/index.js export const PORT = process.env.PORT || 5000; export const NODE_ENV = process.env.NODE_ENV || 'development'; // Later you can add: // export const DATABASE_URL = process.env.DATABASE_URL; // export const JWT_SECRET = process.env.JWT_SECRET; // export const CLIENT_URL = process.env.CLIENT_URL || 'http://localhost:3000'; |
5. Very important middlewares
src/middlewares/not-found.middleware.js
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
export const notFound = (req, res, next) => { res.status(404).json({ success: false, error: 'Route not found', path: req.originalUrl, method: req.method }); }; |
src/middlewares/error.middleware.js
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
export const errorHandler = (err, req, res, next) => { console.error('ERROR:', err); const statusCode = err.statusCode || 500; const message = err.message || 'Internal Server Error'; res.status(statusCode).json({ success: false, error: message, ...(process.env.NODE_ENV !== 'production' && { stack: err.stack }) }); }; |
Summary – What belongs where in a good Node.js home?
| File / Folder | Responsibility | Should be… |
|---|---|---|
| src/index.js | Start server, handle startup crash | Very thin |
| src/app.js | Create express app + middlewares + routes mount | Medium size |
| src/config/ | All configuration values, env parsing | Clean & central |
| src/routes/ | Group routes logically (v1/users, v1/auth, …) | Many small files |
| src/middlewares/ | Reusable request handlers | Small & focused |
| src/utils/ | Logger, response formatter, date helpers, etc. | Helper functions |
Bonus: One more level (what senior teams often do)
They add one more file:
|
0 1 2 3 4 5 6 7 8 9 |
src/ ├── server.js ← only starts http(s) server ├── index.js ← creates app + mounts everything └── app.js ← only express setup (no listen) |
But for 90% of projects → index.js + app.js + routes/ is already excellent.
Question for you — which style do you want to go deeper into next?
- Adding real authentication (JWT + refresh tokens)
- Connecting database (Prisma / Drizzle / Mongoose)
- Proper folder structure for big project (DDD style or feature folders)
- Writing good error handling & response wrapper
- File upload (local + cloud)
- Rate limiting, security headers, CORS in production
- Logging (winston / pino)
- Testing this structure (supertest + jest)
Tell me what you want to see with full code examples next. I’ll continue exactly from this clean home structure.
Happy coding!
