From claude-initial-setup
Express middleware chain patterns including auth middleware, error middleware, rate limiting, CORS configuration, and request validation. Use when the user is building Express.js APIs, configuring middleware, implementing authentication guards, adding rate limiting, or setting up CORS. Trigger on any mention of Express middleware, request pipeline, auth guards, rate limiting, or Express CORS.
npx claudepluginhub versoxbt/claude-initial-setup --plugin claude-initial-setupThis skill uses the workspace's default tool permissions.
Patterns for building robust Express.js middleware chains.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Patterns for building robust Express.js middleware chains.
Middleware executes in the order it is registered. Order matters: authentication must run before authorization, and error handlers must be last.
import express from 'express'
const app = express()
// 1. Built-in middleware
app.use(express.json({ limit: '10kb' }))
app.use(express.urlencoded({ extended: true }))
// 2. Security / CORS
app.use(corsMiddleware)
// 3. Rate limiting
app.use(rateLimiter)
// 4. Request logging
app.use(requestLogger)
// 5. Routes (with route-specific middleware)
app.use('/api/v1/auth', authRoutes)
app.use('/api/v1/users', authenticate, userRoutes)
app.use('/api/v1/admin', authenticate, authorize('admin'), adminRoutes)
// 6. 404 handler
app.use(notFoundHandler)
// 7. Error handler (must be last, must have 4 parameters)
app.use(errorHandler)
Verify tokens and attach user context to the request object.
import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken'
interface AuthRequest extends Request {
user?: { id: string; role: string }
}
function authenticate(req: AuthRequest, res: Response, next: NextFunction): void {
const header = req.headers.authorization
if (!header?.startsWith('Bearer ')) {
res.status(401).json({ error: 'Missing authorization header' })
return
}
const token = header.slice(7)
try {
const payload = jwt.verify(token, process.env.JWT_SECRET!) as { id: string; role: string }
req.user = { id: payload.id, role: payload.role }
next()
} catch {
res.status(401).json({ error: 'Invalid or expired token' })
}
}
function authorize(...roles: string[]) {
return (req: AuthRequest, res: Response, next: NextFunction): void => {
if (!req.user || !roles.includes(req.user.role)) {
res.status(403).json({ error: 'Insufficient permissions' })
return
}
next()
}
}
Protect endpoints from abuse. Use different limits for different routes.
import rateLimit from 'express-rate-limit'
const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100,
standardHeaders: true,
legacyHeaders: false,
message: { error: 'Too many requests, try again later' },
})
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // Strict limit for auth endpoints
message: { error: 'Too many login attempts' },
})
app.use(globalLimiter)
app.use('/api/v1/auth/login', authLimiter)
Configure Cross-Origin Resource Sharing for frontend clients.
import cors from 'cors'
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || []
const corsMiddleware = cors({
origin: (origin, callback) => {
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400,
})
Validate request body, query, and params using Zod. Create a reusable factory.
import { z, ZodSchema } from 'zod'
import { Request, Response, NextFunction } from 'express'
function validate(schema: {
body?: ZodSchema
query?: ZodSchema
params?: ZodSchema
}) {
return (req: Request, res: Response, next: NextFunction): void => {
const errors: Record<string, unknown> = {}
if (schema.body) {
const result = schema.body.safeParse(req.body)
if (!result.success) errors.body = result.error.flatten()
}
if (schema.query) {
const result = schema.query.safeParse(req.query)
if (!result.success) errors.query = result.error.flatten()
}
if (schema.params) {
const result = schema.params.safeParse(req.params)
if (!result.success) errors.params = result.error.flatten()
}
if (Object.keys(errors).length > 0) {
res.status(400).json({ error: 'Validation failed', details: errors })
return
}
next()
}
}
// Usage
const CreateUserSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
})
router.post('/users', validate({ body: CreateUserSchema }), createUser)
next() -- Every middleware must call next() or send a response. Forgetting causes the request to hang indefinitely.(err, req, res, next). Three parameters means it is treated as regular middleware.Middleware signature: (req, res, next) => void
Error middleware: (err, req, res, next) => void
Order: parsing -> security -> rate-limit -> logging -> routes -> 404 -> errors
Route-specific: router.get('/path', middleware1, middleware2, handler)
Router-level: router.use(middleware)
App-level: app.use(middleware)