home / skills / amnadtaowsoam / cerebraskills / express-rest
This skill helps you design robust Express.js REST APIs by applying middleware, routing, validation, and production-ready patterns.
npx playbooks add skill amnadtaowsoam/cerebraskills --skill express-restReview the files below or copy the command above to add this skill to your agents.
---
name: Express.js REST API Patterns
description: Comprehensive patterns for building REST APIs with Express.js including middleware, routing, validation, authentication, and production-ready configurations.
---
# Express.js REST API Patterns
## Overview
Express.js is a minimal and flexible Node.js web application framework for building REST APIs, featuring a powerful middleware system, flexible routing, and a large ecosystem.
Express.js consists of:
- **Minimal Core**: Minimal core with a powerful middleware system
- **Flexible Routing**: Flexible routing with route parameters
- **Middleware Stack**: Middleware stack for request/response processing
- **Error Handling**: Built-in error handling
- **Security**: Security middleware and best practices
- **Production-Ready**: Production-ready with clustering and graceful shutdown
## Why This Matters
- **Increase Development Velocity**: Express.js can increase development velocity by 30-50%
- **Reduce Time to Market**: Flexible framework helps reduce time to market
- **Improve Scalability**: Clustering and middleware improve scalability
- **Reduce Maintenance Cost**: Well-structured code reduces maintenance cost
- **Enhance Performance**: Optimized middleware enhances performance
---
## Core Concepts
### 1. Application Setup
```typescript
import express, { Application } from "express"
export function createApp(): Application {
const app = express()
// Middleware
app.use(express.json())
// Routes
app.use("/api", routes)
return app
}
```
### 2. Middleware Pattern
**Middleware Order is Critical:**
1. Security headers (Helmet)
2. CORS
3. Request logging (Morgan)
4. Body parsing
5. Request ID
6. Rate limiting
7. Authentication
8. Routes
9. Error handler (must be last)
```typescript
export function createApp(): Application {
const app = express()
// 1. Security headers (first)
app.use(helmet())
// 2. CORS
app.use(cors())
// 3. Request logging
app.use(morgan("combined"))
// 4. Body parsing
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// 5. Custom middleware
app.use(requestIdMiddleware)
app.use(loggingMiddleware)
// 6. Authentication (before routes)
app.use(authMiddleware)
// 7. Routes
app.use("/api", routes)
// 8. Error handling (last)
app.use(errorHandler)
return app
}
```
### 3. Routing
```typescript
import { Router } from "express"
const router = Router()
// CRUD routes
router.get("/users", userController.getAll)
router.get("/users/:id", userController.getById)
router.post("/users", userController.create)
router.put("/users/:id", userController.update)
router.delete("/users/:id", userController.delete)
export default router
```
### 4. Error Handling
```typescript
export function errorHandler(
error: Error,
req: Request,
res: Response,
next: NextFunction
): void {
logger.error(error, { path: req.path, method: req.method })
if (error instanceof AppError) {
return res.status(error.statusCode).json({
success: false,
message: error.message,
...(error.details && { details: error.details }),
})
}
res.status(500).json({
success: false,
message: process.env.NODE_ENV === "production"
? "Internal server error"
: error.message,
})
}
```
### 5. Request Validation
**Express Validator:**
```typescript
import { body, validationResult } from "express-validator"
export const validateUser = [
body("name")
.trim()
.notEmpty()
.withMessage("Name is required")
.isLength({ min: 2, max: 50 }),
body("email")
.trim()
.isEmail()
.withMessage("Invalid email address"),
]
export function handleValidationErrors(
req: Request,
res: Response,
next: NextFunction
): void {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return res.status(400).json({
success: false,
message: "Validation failed",
errors: errors.array(),
})
}
next()
}
```
### 6. Authentication
```typescript
import jwt from "jsonwebtoken"
export function authMiddleware(req: Request, res: Response, next: NextFunction): void {
const authHeader = req.headers.authorization
if (!authHeader || !authHeader.startsWith("Bearer ")) {
throw new UnauthorizedError("No token provided")
}
const token = authHeader.substring(7)
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET!)
req.user = decoded
next()
} catch (error) {
throw new UnauthorizedError("Invalid token")
}
}
```
### 7. Rate Limiting
```typescript
import rateLimit from "express-rate-limit"
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests
message: "Too many requests from this IP",
})
app.use("/api", limiter)
```
## Quick Start
1. **Initialize Express app:**
```bash
npm init -y
npm install express typescript @types/express
```
2. **Create basic server:**
```typescript
import express from "express"
const app = express()
app.listen(3000, () => console.log("Server running"))
```
3. **Add middleware:**
```bash
npm install helmet cors morgan
```
4. **Create routes:**
```typescript
const router = express.Router()
router.get("/users", (req, res) => res.json({ users: [] }))
```
5. **Start server:**
```bash
npm run dev
```
## Production Checklist
- [ ] Use TypeScript for type safety
- [ ] Implement proper middleware order
- [ ] Add security headers with Helmet
- [ ] Configure CORS appropriately
- [ ] Implement authentication and authorization
- [ ] Add rate limiting for abuse prevention
- [ ] Validate input with express-validator or Zod
- [ ] Implement proper error handling
- [ ] Add logging with Winston
- [ ] Use async/await for async operations
- [ ] Test routes with Supertest
- [ ] Add health check endpoint
- [ ] Implement graceful shutdown
- [ ] Use clustering for production
- [ ] Monitor performance and errors
## Anti-patterns
1. **Poor Middleware Order**: Don't order middleware incorrectly
2. **Missing Error Handling**: Don't fail to handle errors appropriately
3. **No Input Validation**: Don't skip input validation
4. **Poor Security**: Don't fail to implement security measures
5. **No Logging**: Don't fail to log requests and errors
6. **Poor Performance**: Don't fail to optimize performance
## Integration Points
- **Error Handling**: `03-backend-api/error-handling`
- **Validation**: `03-backend-api/validation`
- **Middleware**: `03-backend-api/middleware`
- **API Design**: `01-foundations/api-design`
- **Monitoring**: `14-monitoring-observability`
## Further Reading
- [Express.js Documentation](https://expressjs.com/)
- [Express Best Practices](https://github.com/goldbergyoni/nodebestpractices)
- [Express Middleware Guide](https://expressjs.com/en/guide/writing-middleware.html)
This skill provides practical, production-ready patterns for building REST APIs with Express.js, covering middleware order, routing, validation, authentication, error handling, rate limiting, and deployment patterns. It distills best practices into actionable code patterns and a production checklist to accelerate reliable API development.
It inspects common Express.js concerns and prescribes a clear middleware ordering, reusable route patterns, and standard handlers for validation, authentication, and errors. The skill includes ready-to-use code samples for app setup, middleware composition, CRUD routing, JWT auth, rate limiting, and validation flows so you can drop them into a project and adapt quickly.
What middleware order should I follow?
Apply security headers and CORS first, then request logging, body parsing, custom middlewares (request id, logging), authentication, routes, and finally the error handler.
How do I handle validation errors consistently?
Use express-validator or Zod at the route level, run a validation error handler that returns a 400 with an errors array, and keep controllers unaware of validation logic.