A production-ready Express.js TypeScript boilerplate featuring enterprise-grade architecture with comprehensive authentication, note management, and advanced security implementations.
This boilerplate provides a solid foundation for building scalable REST APIs using modern development practices, clean architecture principles, and industry-standard security measures. Perfect for developers who want to kickstart their projects with a well-structured, maintainable codebase.
- Object-Oriented Programming (OOP) with TypeScript classes and interfaces
- Repository Pattern for data access abstraction
- Service Layer Architecture for business logic separation
- Dependency Injection Container for loose coupling
- Clean Architecture with proper separation of concerns
- SOLID Principles implementation throughout the codebase
- JWT-based Authentication with access and refresh tokens
- HttpOnly Cookies for enhanced security
- Password Hashing using bcrypt with salt rounds
- Rate Limiting to prevent abuse and DDoS attacks
- Input Validation with express-validator
- CORS Protection with configurable origins
- Helmet.js for security headers
- Environment Variables protection
- PostgreSQL with Prisma ORM
- Database Migrations with version control
- Connection Pooling for optimal performance
- Database Seeding for development/testing
- Type-Safe Database Queries with Prisma Client
- Full TypeScript Support with strict type checking
- Hot Reload with nodemon for development
- Comprehensive Error Handling with custom error classes
- Request Logging with morgan
- API Documentation ready structure
- Production Build optimization
- Pagination Support for large datasets
- Search Functionality with optimized queries
- Cookie Management with security best practices
- Efficient Database Indexing for performance
- Middleware Pipeline for request processing
- Node.js - JavaScript runtime environment
- Express.js - Fast, unopinionated web framework
- TypeScript - Static type checking and enhanced developer experience
- PostgreSQL - Robust, enterprise-grade relational database
- Prisma ORM - Next-generation Node.js and TypeScript ORM
- Prisma Client - Type-safe database client
- JSON Web Tokens (JWT) - Stateless authentication
- bcrypt.js - Password hashing and salting
- Helmet.js - Security headers middleware
- express-rate-limit - Rate limiting middleware
- CORS - Cross-origin resource sharing
- express-validator - Server-side validation
- cookie-parser - Cookie parsing middleware
- morgan - HTTP request logging
- dotenv - Environment variable management
- nodemon - Development server with hot reload
- ts-node - TypeScript execution for Node.js
- pnpm - Fast, disk space efficient package manager
This boilerplate follows Clean Architecture principles with a well-defined separation of concerns:
src/
βββ controllers/ # HTTP request handlers
β βββ base.controller.ts # Base controller with common methods
β βββ auth.controller.ts # Authentication endpoints
β βββ note.controller.ts # Note management endpoints
βββ services/ # Business logic layer
β βββ base.service.ts # Base service with common utilities
β βββ auth.service.ts # Authentication business logic
β βββ note.service.ts # Note management business logic
βββ repository/ # Data access layer
β βββ base.repository.ts # Base repository with common DB operations
β βββ user.repository.ts # User data access methods
β βββ note.repository.ts # Note data access methods
βββ middleware/ # Custom middleware functions
β βββ auth.middleware.ts # JWT authentication middleware
β βββ error.middleware.ts # Global error handling
β βββ limiter.middleware.ts # Rate limiting
β βββ pagination.middleware.ts # Pagination helper
βββ validations/ # Input validation schemas
β βββ auth.validation.ts # Authentication validation rules
β βββ note.validation.ts # Note validation rules
βββ utils/ # Helper functions and utilities
β βββ generateToken.ts # JWT token generation
β βββ error.ts # Custom error classes
β βββ userNames.ts # Username generation utilities
βββ types/ # TypeScript type definitions
β βββ index.ts # Application-wide types and interfaces
βββ constants/ # Application constants
β βββ index.ts # Common constants and configuration
βββ container/ # Dependency injection container
β βββ index.ts # IoC container implementation
βββ routes/ # API route definitions
β βββ auth.routes.ts # Authentication routes
β βββ note.routes.ts # Note management routes
βββ database/ # Database configuration
β βββ prismaClient.ts # Prisma client setup
βββ index.ts # Application entry point
// Abstract data access layer
interface IUserRepository {
findById(id: string): Promise<User | null>;
findByEmail(email: string): Promise<User | null>;
create(userData: CreateUserDTO): Promise<User>;
update(id: string, userData: UpdateUserDTO): Promise<User>;
delete(id: string): Promise<void>;
}
// Business logic encapsulation
class AuthService {
constructor(private userRepository: IUserRepository) {}
async signup(userData: SignUpDTO): Promise<AuthResponseDTO> {
// Business logic implementation
// Validation, password hashing, user creation
}
}
// IoC Container for managing dependencies
class Container {
private static instance: Container;
public static getInstance(prisma: PrismaClient): Container {
if (!Container.instance) {
Container.instance = new Container(prisma);
}
return Container.instance;
}
// Dependency registration and resolution
}
// HTTP request handling with proper error management
class AuthController extends BaseController {
constructor(private authService: IAuthService) {
super();
}
public signup = async (req: Request, res: Response, next: NextFunction) => {
// Request validation, service call, response formatting
};
}
- Single Responsibility Principle: Each class has one reason to change
- Open/Closed Principle: Open for extension, closed for modification
- Liskov Substitution Principle: Derived classes must be substitutable for base classes
- Interface Segregation Principle: Clients shouldn't depend on interfaces they don't use
- Dependency Inversion Principle: Depend on abstractions, not concretions
- JWT Token Strategy: Access tokens (short-lived) + Refresh tokens (long-lived)
- HttpOnly Cookies: Prevents XSS attacks by making tokens inaccessible to client-side scripts
- Secure Cookie Configuration:
SameSite=Strict
,Secure=true
in production - Password Security: bcrypt hashing with configurable salt rounds
- Token Expiration: Automatic token refresh mechanism
- Express-validator: Comprehensive input validation with custom rules
- Email Domain Blocking: Prevents registration from disposable email services
- Password Complexity: Enforces strong password requirements
- SQL Injection Prevention: Prisma ORM provides built-in protection
- XSS Protection: Input sanitization and output encoding
- Configurable Rate Limits: Different limits for auth and API endpoints
- IP-based Tracking: Prevents abuse from specific IP addresses
- Memory-efficient Storage: Optimized for production environments
- Graceful Degradation: Proper error responses when limits are exceeded
- Helmet.js Integration: Comprehensive security headers
- CORS Configuration: Configurable allowed origins
- Content Security Policy: Prevents XSS and data injection attacks
- HSTS: HTTP Strict Transport Security for HTTPS enforcement
// Custom Error Classes Hierarchy
class AppError extends Error {
public statusCode: number;
public isOperational: boolean;
// Error categorization and handling
}
class ValidationError extends AppError {
public errors?: Array<{
field: string;
message: string;
value?: any;
}>;
// Detailed validation error information
}
- ValidationError (400): Input validation failures
- AuthenticationError (401): Authentication failures
- AuthorizationError (403): Permission denied
- NotFoundError (404): Resource not found
- ConflictError (409): Resource conflicts
- InternalServerError (500): Unexpected server errors
{
"statusCode": 400,
"message": "Validation failed",
"errors": [
{
"field": "email",
"message": "Invalid email format",
"value": "invalid-email"
}
],
"stack": "..." // Only in development
}
-- Users table with optimized indexing
CREATE TABLE users (
id TEXT PRIMARY KEY,
username TEXT UNIQUE NOT NULL,
email TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Notes table with foreign key relationships
CREATE TABLE notes (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Optimized indexes for performance
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_notes_user_id ON notes(user_id);
CREATE INDEX idx_notes_title ON notes(title);
- ACID Compliance: Full transaction support
- Cascade Deletes: Automatic cleanup of related records
- Optimized Indexing: Enhanced query performance
- Connection Pooling: Efficient database connections
- Migration System: Version-controlled schema changes
# Database setup and migrations
pnpm prisma:generate # Generate Prisma client
pnpm prisma:migrate # Run migrations
pnpm prisma:studio # Open Prisma Studio
pnpm prisma:db:seed # Seed database with test data
pnpm prisma:migrate:reset # Reset and re-migrate database
# Development server with hot reload
pnpm dev
# Type checking without compilation
pnpm type-check
# Production build
pnpm build
# Production server
pnpm start
- Node.js
- PostgreSQL
- pnpm -
npm install -g pnpm
-
Clone the repository
git clone https://github.com/KhaledSaeed18/node-express-boilerplate.git cd node-express-boilerplate
-
Install dependencies
pnpm install
-
Environment Configuration
Create a
.env
file in the root directory:# Server Configuration PORT=3000 API_VERSION=v1 BASE_URL=/api NODE_ENV=development # Database Configuration DATABASE_URL=postgresql://username:password@localhost:5432/notes-app # JWT Configuration JWT_SECRET=your-super-secret-jwt-key-here JWT_REFRESH_SECRET=your-refresh-secret-key-here JWT_EXPIRE_TIME=15m JWT_REFRESH_EXPIRE_TIME=7d # Client Configuration CLIENT_URL=http://localhost:3000
-
Database Setup
# Generate Prisma client pnpm prisma:generate # Run database migrations pnpm prisma:migrate # Seed the database with sample data pnpm prisma:db:seed
-
Start Development Server
pnpm dev
The server will start on
http://localhost:3000
-
Build the application
pnpm build
-
Deploy database migrations
pnpm prisma:migrate:deploy
-
Start production server
pnpm start
http://localhost:3000/api/v1
Method | Endpoint | Description | Body |
---|---|---|---|
POST | /auth/signup |
Register new user | { "email": "[email protected]", "password": "SecurePass123!" } |
POST | /auth/signin |
Login user | { "email": "[email protected]", "password": "SecurePass123!" } |
POST | /auth/refresh-token |
Refresh access token | No body required |
POST | /auth/logout |
Logout user | No body required |
Method | Endpoint | Description | Headers | Body |
---|---|---|---|---|
POST | /note/create-note |
Create new note | Authorization: Bearer <token> |
{ "title": "Note Title", "content": "Note content" } |
GET | /note/get-notes |
Get all notes (paginated) | Authorization: Bearer <token> |
- |
GET | /note/get-note/:id |
Get specific note | Authorization: Bearer <token> |
- |
GET | /note/search-notes |
Search notes | Authorization: Bearer <token> |
Query: ?q=search term |
PUT | /note/update-note/:id |
Update note | Authorization: Bearer <token> |
{ "title": "Updated Title", "content": "Updated content" } |
DELETE | /note/delete-note/:id |
Delete note | Authorization: Bearer <token> |
- |
page
: Page number (default: 1)limit
: Items per page (default: 10, max: 100)
q
: Search query stringsortBy
: Sort field (title, createdAt, updatedAt)sortOrder
: Sort order (asc, desc)
{
"statusCode": 200,
"message": "Success message",
"data": {
// Response data
},
"pagination": {
"totalItems": 100,
"totalPages": 10,
"currentPage": 1,
"pageSize": 10,
"hasNext": true,
"hasPrevious": false,
"nextPage": 2,
"previousPage": null
}
}
curl -X POST http://localhost:3000/api/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!"
}'
curl -X POST http://localhost:3000/api/v1/auth/signin \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!"
}'
curl -X POST http://localhost:3000/api/v1/note/create-note \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{
"title": "My First Note",
"content": "This is the content of my first note."
}'
curl -X GET "http://localhost:3000/api/v1/note/get-notes?page=1&limit=10" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Access the database GUI:
pnpm prisma:studio
Open http://localhost:5555
to view and edit your database records.
# View migration status
pnpm prisma:migrate:status
# Reset database (development only)
pnpm prisma:migrate:reset
# Pull schema from existing database
pnpm prisma:db:pull
# Push schema changes without migrations
pnpm prisma:db:push
# Validate Prisma schema
pnpm prisma:validate
Variable | Description | Default | Required |
---|---|---|---|
PORT |
Server port | 3000 | No |
NODE_ENV |
Environment mode | development | No |
DATABASE_URL |
PostgreSQL connection string | - | Yes |
JWT_SECRET |
JWT signing secret | - | Yes |
JWT_REFRESH_SECRET |
JWT refresh secret | - | Yes |
JWT_EXPIRE_TIME |
Access token expiration | 15m | No |
JWT_REFRESH_EXPIRE_TIME |
Refresh token expiration | 7d | No |
CLIENT_URL |
Frontend URL for CORS | - | Yes |
BCRYPT_SALT_ROUNDS |
Password hashing rounds | 12 | No |
The application uses PostgreSQL with the following connection format:
postgresql://[username]:[password]@[host]:[port]/[database]
Example:
postgresql://myuser:mypassword@localhost:5432/notes-app
β Star this repository if you find it helpful! β