A well-designed REST API is the backbone of any modern web application. Here's the architecture I've refined through projects like ArenaPro.
Project Structure
src/
controllers/ # Route handlers
models/ # Mongoose schemas
routes/ # Express routers
middleware/ # Auth, error handling
utils/ # Helpers
app.js
server.js
Authentication with JWT
JSON Web Tokens are the standard for stateless authentication. Here's a minimal but secure setup:
// middleware/auth.js
const jwt = require('jsonwebtoken')
module.exports = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1]
if (!token) return res.status(401).json({ message: 'No token' })
try {
req.user = jwt.verify(token, process.env.JWT_SECRET)
next()
} catch {
res.status(401).json({ message: 'Invalid token' })
}
}
Centralised Error Handling
Never scatter try/catch blocks. Use a global error middleware and an async wrapper.
// utils/catchAsync.js
module.exports = fn => (req, res, next) => fn(req, res, next).catch(next)
// app.js — last middleware
app.use((err, req, res, next) => {
const status = err.statusCode || 500
res.status(status).json({ message: err.message })
})
Checklist for Production APIs
- Validate all input with
express-validatoror Zod. - Rate-limit authentication routes.
- Use HTTPS and set proper CORS headers.
- Never return stack traces in production.
- Index your MongoDB fields used in queries.