A production-ready REST API built with Express, TypeScript, and Clean Architecture principles.
- ✅ Clean Architecture by feature (Domain → Application → Infrastructure → Presentation)
- ✅ TypeScript with strict mode
- ✅ Express.js REST API
- ✅ PostgreSQL database with Drizzle ORM
- ✅ Docker Compose for local development
- ✅ Input validation with Zod
- ✅ Comprehensive error handling
- ✅ Security headers with Helmet
- ✅ CORS enabled
- ✅ Structured logging
src/
├── modules/
│ ├── user/
│ │ ├── domain/ # Entities & Repository Interfaces
│ │ ├── application/ # Use Cases (Business Logic)
│ │ ├── infrastructure/ # Repository Implementation & DB Schema
│ │ └── presentation/ # Controllers, Routes, DTOs
│ └── post/
│ ├── domain/
│ ├── application/
│ ├── infrastructure/
│ └── presentation/
└── shared/
├── domain/ # Base entities
├── infrastructure/ # Database client, Error handlers
└── utils/ # Logger, Validators
- Node.js 18+
- Docker & Docker Compose
- npm or yarn
npm installcp .env.example .envdocker-compose up -dnpm run db:migratenpm run devServer runs at: http://localhost:3000
GET /health# Create user
POST /api/users
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}
# Get all users
GET /api/users
# Get user by ID
GET /api/users/:id
# Update user
PATCH /api/users/:id
Content-Type: application/json
{
"name": "John Updated"
}
# Delete user
DELETE /api/users/:id# Create post
POST /api/posts
Content-Type: application/json
{
"title": "My First Post",
"content": "This is the content of my post"
}
# Get all posts
GET /api/posts
# Get post by ID
GET /api/posts/:id
# Update post
PATCH /api/posts/:id
Content-Type: application/json
{
"title": "Updated Title"
}
# Delete post
DELETE /api/posts/:id# Create a user
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com"}'
# Create a post
curl -X POST http://localhost:3000/api/posts \
-H "Content-Type: application/json" \
-d '{"title": "Hello World", "content": "This is my first post"}'
# Get all users
curl http://localhost:3000/api/users# Generate migration files
npm run db:generate
# Run migrations
npm run db:migrate
# Push schema to database (dev only)
npm run db:push
# Open Drizzle Studio
npm run db:studio# Start dev server with hot reload
npm run dev
# Build for production
npm run build
# Start production server
npm start
# Run linting
npm run lint
# Format code
npm run format
# Run tests
npm testNODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://postgres:postgres@localhost:54322/cleanapi- Runtime: Node.js
- Language: TypeScript
- Framework: Express.js
- Database: PostgreSQL
- ORM: Drizzle ORM
- Validation: Zod
- Security: Helmet, CORS
- Logging: Custom structured logger
The project follows Clean Architecture principles:
- Domain Layer: Business entities and repository interfaces
- Application Layer: Use cases containing business logic
- Infrastructure Layer: External concerns (database, APIs)
- Presentation Layer: HTTP controllers and routes
Dependency Rule: Inner layers don't depend on outer layers.
The API returns consistent error responses:
{
"success": false,
"error": "Error Type",
"message": "Detailed error message",
"details": []
}Input validation using Zod schemas:
- User: name (1-100 chars), email (valid format, unique)
- Post: title (1-200 chars), content (1-5000 chars)
- Follow Clean Architecture principles
- Keep files under 500 lines
- Follow YAGNI, KISS, DRY principles
- Write tests for new features
- Run linting before commit
MIT