🚀 Startup Express
A comprehensive, production-ready Express.js starter package with Zod validation, advanced middleware, and TypeScript-first design.

✨ Features
- 🔐 Zod Validation: TypeScript-first schema validation with automatic type inference
- 🆔 Request Tracking: Unique ID for every request with automatic logging correlation
- ⏱️ Performance Monitoring: Request timing with slow request detection
- 🧹 Input Sanitization: Automatic NoSQL injection protection
- 🛡️ Error Handling: Structured error codes with detailed error responses
- 📊 Response Helpers: Consistent API responses with pagination support
- 🔒 Security: Helmet, CORS, rate limiting out of the box
- 📝 Logging: Winston + Morgan with context-aware logging
- ⚡ Performance: Compression and optimized middleware stack
- 🏥 Health Checks: Built-in
/health and /ready endpoints
📦 Installation
npm install startup-express express zod
🚀 Quick Start
import express from 'express';
import { setupExpress, addErrorHandlers, z, validate, catchAsync, sendSuccess } from 'startup-express';
const app = express();
setupExpress(app);
const userSchema = z.object({
email: z.string().email(),
name: z.string().min(2),
age: z.number().int().min(18),
});
app.post('/users',
validate(userSchema, 'body'),
catchAsync(async (req, res) => {
const { email, name, age } = req.body;
const user = { id: 1, email, name, age };
sendSuccess(res, user, 'User created', 201, req);
})
);
addErrorHandlers(app);
app.listen(3000, () => console.log('Server running on port 3000'));
🎯 Core Features
Zod Validation with Type Inference
import { z, validate, commonSchemas } from 'startup-express';
const createUserSchema = z.object({
email: commonSchemas.email,
password: commonSchemas.password,
name: z.string().min(2).max(50),
age: z.number().int().min(18).optional(),
});
app.post('/users',
validate(createUserSchema, 'body'),
async (req, res) => {
}
);
Available Common Schemas:
commonSchemas.email - Email with lowercase normalization
commonSchemas.password - Strong password (8+ chars, complexity requirements)
commonSchemas.objectId - MongoDB ObjectId
commonSchemas.uuid - UUID v4
commonSchemas.url - Valid URL
commonSchemas.dateString - ISO 8601 date
commonSchemas.pagination - Page and limit with defaults
commonSchemas.search - Search query with sort/order
Advanced Error Handling
import { AppError, ErrorCode, catchAsync } from 'startup-express';
app.get('/users/:id',
catchAsync(async (req, res) => {
const user = await findUser(req.params.id);
if (!user) {
throw AppError.notFound('User not found', { userId: req.params.id });
}
res.json({ success: true, data: user });
})
);
Error Response Format:
{
"success": false,
"message": "User not found",
"errorCode": "NOT_FOUND",
"requestId": "V1StGXR8_Z5jdHi6B-myT",
"timestamp": "2024-01-15T10:30:00.000Z",
"errors": [{ "userId": "123" }]
}
Available Error Methods:
AppError.badRequest(message, details?) - 400
AppError.unauthorized(message, details?) - 401
AppError.forbidden(message, details?) - 403
AppError.notFound(message, details?) - 404
AppError.conflict(message, details?) - 409
AppError.validation(message, details?) - 422
AppError.internal(message, details?) - 500
Response Helpers
import { sendSuccess, sendPaginated, sendCreated } from 'startup-express';
sendSuccess(res, data, 'Operation successful', 200, req);
sendCreated(res, newUser, 'User created', req);
sendPaginated(res, users, { page: 1, limit: 10, total: 100 }, req);
Response Format:
{
"success": true,
"data": { ... },
"message": "Operation successful",
"meta": {
"timestamp": "2024-01-15T10:30:00.000Z",
"requestId": "V1StGXR8_Z5jdHi6B-myT",
"pagination": {
"page": 1,
"limit": 10,
"total": 100,
"totalPages": 10,
"hasNext": true,
"hasPrev": false
}
}
}
Request Tracking
Every request automatically gets a unique ID:
app.get('/api/users', (req, res) => {
console.log(req.requestId);
logger.info('Fetching users', { requestId: req.requestId });
});
Multiple Source Validation
import { validateAll, z } from 'startup-express';
app.put('/users/:id',
validateAll({
params: z.object({ id: z.string() }),
body: z.object({ name: z.string() }),
query: z.object({ notify: z.boolean().optional() }),
}),
handler
);
⚙️ Configuration
setupExpress(app, {
cors: {
origin: ['https://example.com'],
credentials: true,
},
helmet: {
enabled: true,
},
rateLimit: {
windowMs: 15 * 60 * 1000,
max: 100,
},
logging: {
format: 'combined',
},
requestId: {
enabled: true,
header: 'X-Request-Id',
},
});
🔧 Individual Middleware Usage
import {
helmetMiddleware,
corsMiddleware,
rateLimitMiddleware,
strictRateLimitMiddleware,
requestIdMiddleware,
timingMiddleware,
sanitizeMiddleware,
} from 'startup-express';
app.use(helmetMiddleware());
app.use(corsMiddleware({ origin: 'https://example.com' }));
app.use(requestIdMiddleware());
app.use(timingMiddleware({ slowRequestThreshold: 2000 }));
app.post('/auth/login', strictRateLimitMiddleware(), loginHandler);
📝 Logging
import { logger } from 'startup-express';
logger.info('User created', {
userId: user.id,
email: user.email,
requestId: req.requestId,
});
logger.error('Database error', {
error: err.message,
stack: err.stack,
requestId: req.requestId,
});
🏥 Health Checks
Built-in health check endpoints:
GET /health
{
"success": true,
"message": "Server is healthy",
"timestamp": "2024-01-15T10:30:00.000Z",
"uptime": 3600.5,
"environment": "production",
"requestId": "abc123"
}
GET /ready
{
"success": true,
"message": "Server is ready"
}
📚 Documentation
🎯 What's Included
Middleware
- ✅ Helmet (security headers)
- ✅ CORS (cross-origin resource sharing)
- ✅ Compression (gzip responses)
- ✅ Rate limiting (standard and strict)
- ✅ Body parser (JSON and URL-encoded)
- ✅ Request ID tracking
- ✅ Request timing
- ✅ Input sanitization
- ✅ HTTP request logging
Validation
- ✅ Zod schema validation
- ✅ Multi-source validation
- ✅ Common validation schemas
- ✅ Type-safe request handlers
- ✅ Automatic error formatting
Error Handling
- ✅ Structured error codes
- ✅ Custom AppError class
- ✅ Static error methods
- ✅ Async error handling
- ✅ Global error handlers
- ✅ 404 handler
Response Helpers
- ✅ Success responses
- ✅ Paginated responses
- ✅ Created responses (201)
- ✅ Accepted responses (202)
- ✅ No content responses (204)
Utilities
- ✅ Environment config helpers
- ✅ Winston logger with file rotation
- ✅ TypeScript type definitions
- ✅ Request/response interfaces
🚀 Use Cases
Perfect for:
- REST APIs: Build type-safe REST APIs quickly
- Microservices: Consistent setup across services
- Prototyping: Get from zero to production fast
- Learning: Best practices for Express.js
- Boilerplates: Foundation for your templates
🌟 Why Startup Express?
- ⚡ Fast Setup: One function call to configure everything
- 🔒 Secure: Security best practices included
- 📦 Type-Safe: Full TypeScript with Zod validation
- 🎨 Flexible: Use complete package or individual pieces
- 📝 Well Documented: Extensive guides and examples
- 🧪 Production Ready: Battle-tested patterns
- 🔄 Modern: Latest tools and best practices
💡 Examples
Basic CRUD API
See EXAMPLE.md for complete REST API example with:
- User CRUD operations
- Pagination and filtering
- Error handling
- Request validation
- Type-safe handlers
Simple API
import express from 'express';
import { setupExpress, addErrorHandlers, z, validate, sendSuccess } from 'startup-express';
const app = express();
setupExpress(app);
const schema = z.object({ name: z.string() });
app.post('/items',
validate(schema, 'body'),
(req, res) => sendSuccess(res, req.body, 'Item created')
);
addErrorHandlers(app);
app.listen(3000);
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
📄 License
MIT © [Nakeebovic]
🙏 Acknowledgments
Built with these amazing packages:
👨💻 Author
Ahmed El Nakeeb (Nakeebovic)
Made with ❤️ for the Express.js community
⭐ Star this repo if you find it helpful!