Skip to content
Back to skills

Express

ASecurity

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.s...

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 24, 2026
developmentjavascripttypescriptrustjavanextjsnodenodejsexpressdockertesting

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned September 24, 2026

npx -y skills add chrishuffman5/domain-expert --skill express --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Express?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Express
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/chrishuffman5-express/badge)](https://www.skillsdirectory.com/skills/chrishuffman5-express)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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.md10.7 KB
  • references/architecture.md18.8 KB
  • references/best-practices.md22 KB
  • references/diagnostics.md15.1 KB
  • references/versions/5.x.md9.3 KB
  • scripts/01-dependency-and-security-audit.sh1.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…