Back to skills
SKILL.md
Express
ASecurityExpert skill for Express.js web framework development across Express 4.x and 5.x. Covers middleware chain, routing, error handling, request/response lifecycle, template engines, security (Helmet, CORS), body parsing, TypeScript setup, testing, and deployment. WHEN: \"Express\", \"express.js\", \"express middleware\", \"app.use\", \"app.get\", \"app.post\", \"express router\", \"middleware ordering\", \"express error handler\", \"req.params\", \"req.query\", \"req.body\", \"res.json\", \"res.s...
- 4 stars
- 0 votes
- 0 copies
- 0 views
- Added September 24, 2026
Works with
Security analysis
100/100Pro scans all 6 files and shows the line behind each finding
npx -y skills add chrishuffman5/domain-expert --skill express --agent claude-codeAre you the author of Express?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-express)---
name: express
description: "Expert skill for Express.js web framework development across Express 4.x and 5.x. Covers middleware chain, routing, error handling, request/response lifecycle, template engines, security (Helmet, CORS), body parsing, TypeScript setup, testing, and deployment. WHEN: \"Express\", \"express.js\", \"express middleware\", \"app.use\", \"app.get\", \"app.post\", \"express router\", \"middleware ordering\", \"express error handler\", \"req.params\", \"req.query\", \"req.body\", \"res.json\", \"res.send\", \"express-validator\", \"supertest\", \"helmet\", \"cors middleware\", \"express rate limit\", \"multer\", \"express-session\", \"passport express\", \"Express 5\", \"express TypeScript\". Do NOT use for general Node.js scripting, automation, or CLI-tool questions unrelated to the Express framework — that's the `cli-scripting` plugin's `nodejs` skill."
license: MIT
---
# Express.js
This skill covers Express.js web framework development across Express 4.x and 5.x. Express is a minimal, unopinionated Node.js web framework providing a thin layer of fundamental web application features: routing, middleware composition, and HTTP utilities. Its power comes from composing third-party middleware into a pipeline.
## How to Approach Tasks
1. **Classify** the request:
- **Architecture** -- Load `references/architecture.md` for middleware internals, routing engine, request/response lifecycle, Express 5 breaking changes, error handling patterns
- **Best practices** -- Load `references/best-practices.md` for project structure, security (helmet, cors, rate-limit), testing (supertest), deployment (cluster, PM2, Docker), performance tuning, popular middleware integration
- **Troubleshooting** -- Load `references/diagnostics.md` for common errors (middleware ordering, unhandled rejections, CORS misconfig, body parsing), debugging, memory leaks, async error handling
- **Express 5 specific** -- Read `references/versions/5.x.md` for path-to-regexp v8, removed deprecated methods, promise rejection handling, migration from Express 4
2. **Identify version** -- Determine whether the project targets Express 4.x or 5.x from `package.json`, import style, or explicit mention. Default to Express 5 for new projects.
3. **Load context** -- Read the relevant reference file before answering.
4. **Analyze** -- Apply Express-specific reasoning. Consider middleware ordering, the `(req, res, next)` contract, error handler signature requirements, and the sync/async distinction between Express 4 and 5.
5. **Recommend** -- Provide concrete JavaScript or TypeScript code examples with explanations. Always qualify trade-offs.
6. **Verify** -- Suggest validation steps: running tests with supertest, checking middleware order, verifying error handler registration.
## Core Architecture
### Middleware Chain
Every Express application is a pipeline of middleware functions. Each function receives `(req, res, next)` and must either terminate the response or call `next()`.
```js
const app = express();
// Middleware executes in registration order
app.use(helmet()); // 1. Security headers
app.use(cors(corsOptions)); // 2. CORS
app.use(rateLimit({ windowMs: 15*60*1000, max: 100 })); // 3. Rate limiting
app.use(morgan('combined')); // 4. Logging
app.use(compression()); // 5. Compression
app.use(express.json({ limit: '10mb' })); // 6. Body parsing
app.use(express.urlencoded({ extended: true }));
app.use('/api/v1', apiRouter); // 7. Routes
app.use(notFoundHandler); // 8. 404 -- after all routes
app.use(errorHandler); // 9. Error handler -- always last
```
**Critical rules:**
- Security middleware (helmet, cors) before body parsing
- Body parsing before routes
- 404 handler after all routes
- Error handler (`(err, req, res, next)` -- 4 arguments) always last
### Error Handling
Error-handling middleware is distinguished solely by its 4-parameter signature. Express checks `function.length` to identify it.
```js
// Error handler -- must have exactly 4 params
app.use((err, req, res, next) => {
if (res.headersSent) return next(err);
const status = err.status ?? err.statusCode ?? 500;
res.status(status).json({
error: { message: err.message, code: err.code ?? 'INTERNAL_ERROR' },
});
});
```
**Express 5:** Async errors in route handlers are automatically forwarded to error middleware -- no `try/catch` or `asyncHandler` wrapper needed.
**Express 4:** Requires explicit `next(err)` calls or wrapper libraries like `express-async-errors`.
### Routing
Express Router creates modular, mountable route handlers:
```js
const router = express.Router();
router.use(authenticate);
router.get('/', listUsers);
router.post('/', validate(schema), createUser);
router.route('/:id')
.get(getUser)
.put(validate(schema), updateUser)
.delete(authorize('admin'), deleteUser);
app.use('/api/v1/users', router);
```
### Request and Response
```js
// Request properties
req.params // URL segments (:id)
req.query // Query string (?page=1)
req.body // Parsed body (requires body-parsing middleware)
req.headers // HTTP headers
req.ip // Client IP (respects trust proxy)
req.hostname // Host without port
req.path // URL pathname
// Response methods
res.json(data) // Send JSON
res.status(201).json(data) // Status + JSON
res.send(data) // Auto-detect content type
res.redirect(301, url) // Redirect
res.sendFile(absolutePath) // Serve file
res.cookie(name, val, opts) // Set cookie
```
### TypeScript Setup
```ts
// src/types/express.d.ts -- augment Request
declare global {
namespace Express {
interface Request {
user?: User;
requestId: string;
}
}
}
export {};
```
```json
// tsconfig.json essentials
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true
}
}
```
Development: `tsx watch src/server.ts`. Build: `tsc`. Production: `node dist/server.js`.
## Key Patterns
### App Factory (Required for Testing)
```ts
// app.ts -- no listen()
export function createApp(): Application {
const app = express();
app.use(helmet());
app.use(cors());
app.use(express.json());
app.use('/api/v1/users', usersRouter);
app.use(notFoundHandler);
app.use(errorHandler);
return app;
}
// server.ts -- starts listening
const app = createApp();
app.listen(config.PORT);
```
### Custom Error Classes
```ts
class AppError extends Error {
constructor(
message: string,
public status: number = 500,
public code?: string,
public isOperational: boolean = true,
) {
super(message);
}
}
class NotFoundError extends AppError {
constructor(resource = 'Resource') {
super(`${resource} not found`, 404, 'NOT_FOUND');
}
}
```
### Validation Middleware (Zod)
```ts
const validateBody = (schema: ZodSchema) => (req, res, next) => {
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(422).json({ errors: result.error.issues });
}
req.validatedBody = result.data;
next();
};
```
### Trust Proxy
```js
// Behind a reverse proxy (Nginx, ALB) -- required for correct req.ip, req.protocol
app.set('trust proxy', 1); // trust first hop
app.set('trust proxy', 'loopback'); // trust loopback
```
## Template Engines
Express supports Pug, EJS, and Handlebars via `app.set('view engine', 'pug')`. For API-only services, skip template engines entirely. For SSR, consider Next.js or Remix before raw Express templating.
## Express 4 vs Express 5
| Feature | Express 4 | Express 5 |
|---|---|---|
| Async error handling | Manual `next(err)` required | Automatic -- rejections forwarded |
| Wildcard routes | `*` allowed | Named wildcard `:name*` required |
| Path syntax | Loose (path-to-regexp v0) | Strict (path-to-regexp v8) |
| `req.param()` | Deprecated but available | Removed |
| `res.send(status, body)` | Deprecated but works | Removed |
| Node.js minimum | Node 10+ | Node 18+ |
| Bun/Deno support | Partial | Full |
## Version-specific guidance
| Version | Status | Reference | What's version-specific |
|---|---|---|---|
| Express 5.x | Stable (2024+) | `references/versions/5.x.md` | path-to-regexp v8, auto async errors, removed deprecated APIs, Bun/Deno compat |
| Express 4.x | Maintenance | (none -- covered directly above) | Legacy, manual async error handling, loose path syntax |
**Default to Express 5** for all new projects. Express 4 guidance is for migration and legacy support.
## Express vs Alternatives
| Dimension | Express 5 | Fastify 5 | Koa 2 |
|---|---|---|---|
| Throughput | ~45k req/s | ~75k req/s | ~50k req/s |
| Middleware | `(req, res, next)` | Hooks + plugins | `(ctx, next)` async |
| Async errors | Auto (v5) | Native | Native |
| Schema validation | Manual (zod, joi) | Built-in (ajv) | Manual |
| Ecosystem | Largest | Large, growing | Moderate |
| Learning curve | Lowest | Moderate | Low |
**Choose Express when:** maximum ecosystem compatibility, team expertise, existing codebase, middleware selection matters more than raw throughput.
**Consider Fastify when:** throughput is critical, built-in validation/serialization is valued, TypeScript-first with generics.
## Security Essentials
- **Helmet**: `app.use(helmet())` -- sets CSP, HSTS, X-Frame-Options, X-Content-Type-Options
- **CORS**: Whitelist origins, enable credentials carefully, cache preflight with `maxAge`
- **Rate limiting**: `express-rate-limit` on auth endpoints and API routes
- **Input validation**: `express-validator` or Zod middleware before handlers
- **Body limits**: `express.json({ limit: '10mb' })` to prevent payload abuse
- **Cookie security**: `httpOnly`, `secure`, `sameSite: 'strict'`
## Reference Files
Load these for deep knowledge on specific topics:
- `references/architecture.md` -- Middleware internals, routing engine, request/response lifecycle, Express 5 breaking changes, error handling patterns. **Load when:** architecture questions, middleware ordering, Express 5 migration, routing issues.
- `references/best-practices.md` -- Project structure, security (helmet, cors, rate-limit), testing (supertest), deployment (cluster, PM2, Docker), performance, popular middleware integration (passport, multer, express-validator). **Load when:** "how should I structure", security review, testing setup, deployment patterns.
- `references/diagnostics.md` -- Common errors (middleware ordering, unhandled rejections, CORS, body parsing), debugging, memory leaks, async error handling. **Load when:** troubleshooting errors, debugging issues, diagnosing performance problems.
## Diagnostic Scripts
Ready-made npm/node audit (read-only) in `scripts/`.
- `scripts/01-dependency-and-security-audit.sh` -- npm vulns, outdated deps, security-middleware presence
Files in this skill
- SKILL.md
- references/architecture.md
- references/best-practices.md
- references/diagnostics.md
- references/versions/5.x.md
- scripts/01-dependency-and-security-audit.sh
Attribution
Comments
Loading comments…