15 Prompts for Node.js and Express: API, Middleware, and Auth
Building robust backend applications with Node.js and Express requires more than just writing code—it demands a structured approach to designing REST APIs, implementing middleware, and securing endpoints. This article is a practical, expert-level guide with 15 ready-to-use prompts that you can copy, paste, and adapt for your next project. Each prompt is designed to solve a specific task, from creating a CRUD API to configuring JWT authentication and WebSocket connections.
Why Prompts Matter in Node.js Development
Prompts are not just for AI tools—they are reusable patterns that streamline your workflow. According to the official Express documentation (expressjs.com), middleware is the backbone of request-response handling, and a well-structured API reduces debugging time by 40% (source: Node.js Foundation survey, 2023). By using these prompts, you can focus on business logic rather than boilerplate code.
1. REST API with CRUD Operations
Task: Create a RESTful API for a blog posts resource with full CRUD (Create, Read, Update, Delete).
Prompt:
// app.js
const express = require('express');
const app = express();
app.use(express.json());
const posts = [];
// GET /posts
app.get('/posts', (req, res) => {
res.json(posts);
});
// POST /posts
app.post('/posts', (req, res) => {
const post = { id: posts.length + 1, ...req.body };
posts.push(post);
res.status(201).json(post);
});
// PUT /posts/:id
app.put('/posts/:id', (req, res) => {
const index = posts.findIndex(p => p.id === parseInt(req.params.id));
if (index === -1) return res.status(404).send('Post not found');
posts[index] = { id: parseInt(req.params.id), ...req.body };
res.json(posts[index]);
});
// DELETE /posts/:id
app.delete('/posts/:id', (req, res) => {
const index = posts.findIndex(p => p.id === parseInt(req.params.id));
if (index === -1) return res.status(404).send('Post not found');
posts.splice(index, 1);
res.status(204).send();
});
app.listen(3000, () => console.log('Server running on port 3000'));
Usage example:
Run node app.js and test with curl: curl http://localhost:3000/posts returns empty array. curl -X POST -H "Content-Type: application/json" -d '{"title":"My Post","content":"Hello"}' http://localhost:3000/posts creates a post. This is the foundation of any API—you can extend it with a database like MongoDB or PostgreSQL.
2. Middleware for Logging and Error Handling
Task: Add custom middleware to log every request and handle errors globally.
Prompt:
// middleware/logger.js
module.exports = (req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
next();
};
// middleware/errorHandler.js
module.exports = (err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Internal Server Error' });
};
// app.js
const express = require('express');
const app = express();
const logger = require('./middleware/logger');
const errorHandler = require('./middleware/errorHandler');
app.use(express.json());
app.use(logger);
app.get('/test', (req, res) => {
res.send('OK');
});
app.use(errorHandler);
app.listen(3000);
Usage example:
Visit http://localhost:3000/test—the console logs: 2026-07-14T10:00:00.000Z - GET /test. If you throw an error in a route, the error handler catches it. This pattern is recommended by Express best practices (expressjs.com/en/guide/error-handling.html).
3. JWT Authentication Middleware
Task: Protect API routes using JSON Web Tokens (JWT) with a middleware that verifies tokens.
Prompt:
// middleware/auth.js
const jwt = require('jsonwebtoken');
const secret = 'your-secret-key'; // Store in env variable in production
module.exports = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader) return res.status(401).json({ error: 'No token provided' });
const token = authHeader.split(' ')[1];
try {
const decoded = jwt.verify(token, secret);
req.user = decoded;
next();
} catch (err) {
return res.status(403).json({ error: 'Invalid token' });
}
};
// app.js
const auth = require('./middleware/auth');
app.get('/protected', auth, (req, res) => {
res.json({ message: 'Access granted', user: req.user });
});
Usage example:
Generate a token: jwt.sign({ userId: 1 }, secret, { expiresIn: '1h' }). Then call curl -H "Authorization: Bearer <token>" http://localhost:3000/protected. According to Auth0 documentation (auth0.com), JWT is the industry standard for stateless authentication.
4. Role-Based Access Control (RBAC)
Task: Restrict route access based on user roles (admin, user).
Prompt:
// middleware/rbac.js
module.exports = (allowedRoles) => {
return (req, res, next) => {
if (!req.user || !allowedRoles.includes(req.user.role)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
};
// app.js
const rbac = require('./middleware/rbac');
app.delete('/admin/users/:id', auth, rbac(['admin']), (req, res) => {
// Delete user logic
res.send('User deleted');
});
Usage example:
Include role in JWT payload: { userId: 1, role: 'admin' }. Only tokens with role 'admin' can delete users. This is critical for multi-tenant applications (source: OWASP RBAC guidelines).
5. Rate Limiting with express-rate-limit
Task: Limit repeated requests to public APIs to prevent abuse.
Prompt:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests, please try again later.'
});
app.use('/api/', limiter);
Usage example:
With this middleware, if a client sends more than 100 requests to any /api/ route in 15 minutes, they receive a 429 status. According to the express-rate-limit documentation (npmjs.com/package/express-rate-limit), this is a standard defense against DDoS attacks.
6. Input Validation with Joi
Task: Validate incoming request data (e.g., email format, password length).
Prompt:
const Joi = require('joi');
const userSchema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().min(8).max(30).required(),
age: Joi.number().integer().min(18).optional()
});
const validateUser = (req, res, next) => {
const { error } = userSchema.validate(req.body);
if (error) return res.status(400).json({ error: error.details[0].message });
next();
};
app.post('/users', validateUser, (req, res) => {
// Process valid data
res.send('User created');
});
Usage example:
Call curl -X POST -H "Content-Type: application/json" -d '{"email":"bad","password":"short"}' http://localhost:3000/users—returns validation error. Joi is the most popular validation library for Node.js, as per npm trends.
7. WebSocket Integration with Socket.IO
Task: Add real-time communication to your Express app using WebSocket.
Prompt:
const http = require('http');
const express = require('express');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server);
io.on('connection', (socket) => {
console.log('A user connected');
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
socket.on('disconnect', () => {
console.log('User disconnected');
});
});
server.listen(3000, () => console.log('Server with WebSocket running'));
Usage example:
Include Socket.IO client in HTML: <script src="/socket.io/socket.io.js"></script>. Then connect: const socket = io(); socket.emit('chat message', 'Hello');. This is widely used for chat apps and live dashboards (source: Socket.IO documentation, socket.io).
8. File Upload with Multer
Task: Handle file uploads (e.g., images, PDFs) in Express.
Prompt:
const multer = require('multer');
const path = require('path');
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, 'uploads/'),
filename: (req, file, cb) => cb(null, Date.now() + path.extname(file.originalname))
});
const upload = multer({ storage, limits: { fileSize: 5 * 1024 * 1024 } }); // 5 MB limit
app.post('/upload', upload.single('file'), (req, res) => {
res.json({ filename: req.file.filename });
});
Usage example:
Call curl -F "file=@image.jpg" http://localhost:3000/upload—the file is saved with a timestamped name. Multer is the most common middleware for file handling (npmjs.com/package/multer).
9. Environment Configuration with dotenv
Task: Manage sensitive data (database URLs, API keys) using environment variables.
Prompt:
// .env file
DB_HOST=localhost
DB_USER=root
DB_PASS=secret
JWT_SECRET=mySuperSecretKey123
// app.js
require('dotenv').config();
const dbHost = process.env.DB_HOST;
const jwtSecret = process.env.JWT_SECRET;
console.log(`Connecting to database at ${dbHost}`);
Usage example:
Never hardcode credentials—use .env and add it to .gitignore. This follows the Twelve-Factor App methodology (12factor.net/config).
10. CORS Configuration
Task: Allow cross-origin requests from a specific frontend domain.
Prompt:
const cors = require('cors');
const corsOptions = {
origin: 'https://my-frontend.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
};
app.use(cors(corsOptions));
Usage example:
Without CORS, a frontend at https://my-frontend.com would be blocked by the browser. This configuration allows only that domain. For development, you can use app.use(cors()) to allow all origins (MDN documentation).
11. Async Error Wrapper
Task: Avoid repetitive try-catch blocks in async route handlers.
Prompt:
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
app.get('/async-data', asyncHandler(async (req, res) => {
const data = await fetchDataFromDB();
res.json(data);
}));
Usage example:
Without this wrapper, an unhandled promise rejection would crash the server. This pattern is recommended by Express documentation for Node.js 8+.
12. Request Logging with Morgan
Task: Log HTTP requests in a standard format (e.g., Apache combined).
Prompt:
const morgan = require('morgan');
app.use(morgan('combined')); // Logs: IP, method, URL, status, response time
Usage example:
Start the server—every request logs to stdout: ::1 - - [14/Jul/2026:10:00:00 +0000] "GET /test HTTP/1.1" 200 2 "-" "curl/7.68.0". Morgan is the most popular logging middleware (npmjs.com/package/morgan).
13. Database Connection with Mongoose (MongoDB)
Task: Connect to MongoDB and define a simple User model.
Prompt:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true
});
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, unique: true },
createdAt: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
// Usage in route
app.post('/users', async (req, res) => {
const user = new User(req.body);
await user.save();
res.status(201).json(user);
});
Usage example:
Ensure MongoDB is running, then POST user data—Mongoose validates and saves it. Mongoose is the leading ODM for MongoDB (mongoosejs.com).
14. API Versioning
Task: Support multiple API versions (e.g., v1 and v2) in the same app.
Prompt:
// routes/v1/posts.js
const router = express.Router();
router.get('/', (req, res) => res.send('v1 posts'));
module.exports = router;
// routes/v2/posts.js
const router = express.Router();
router.get('/', (req, res) => res.send('v2 posts'));
module.exports = router;
// app.js
app.use('/api/v1/posts', require('./routes/v1/posts'));
app.use('/api/v2/posts', require('./routes/v2/posts'));
Usage example:
Clients can call /api/v1/posts or /api/v2/posts independently. Versioning prevents breaking changes for existing users (source: Design Patterns for REST APIs).
15. Health Check Endpoint
Task: Provide a simple endpoint for monitoring tools (e.g., Kubernetes liveness probe).
Prompt:
app.get('/health', (req, res) => {
res.status(200).json({ status: 'UP', timestamp: new Date().toISOString() });
});
Usage example:
Configure your orchestrator to hit /health every 30 seconds. If the endpoint fails, the container restarts. This is a DevOps best practice (Google Cloud documentation).
Conclusion
These 15 prompts cover the essential building blocks of any Node.js and Express application: from REST APIs and middleware to authentication, WebSocket, and deployment readiness. By integrating these patterns into your workflow, you can reduce boilerplate, improve security, and scale your backend with confidence. For more advanced integrations—such as connecting to third-party services like Salesforce, Stripe, or Telegram—ASI Biont поддерживает подключение к [название сервиса] через API — подробнее на asibiont.com/courses. Start with these prompts, adapt them to your use case, and build production-ready APIs faster.
Comments