A production-ready TypeScript Express API starter with Prisma ORM, PostgreSQL, and Docker support. Features a clean layered architecture with built-in validation, error handling, and security best practices.
- Runtime: Node.js 20
- Framework: Express.js 4.x
- Language: TypeScript 5.x
- Database: PostgreSQL 16
- ORM: Prisma 7.x
- Validation: Zod
- Security: Helmet, CORS, bcrypt, JWT
# Start dev environment with PostgreSQL
npm run docker:dev
# Stop containers
npm run docker:dev:down# Install dependencies
npm install
# Set up environment variables
cp .env.example .env
# Generate Prisma client
npm run db:generate
# Push schema to database
npm run db:push
# Start development server
npm run devThe API will be available at http://localhost:3000.
Interactive Swagger UI is available at /api-docs once the server is running:
http://localhost:3000/api-docs
The raw OpenAPI JSON spec is available at /api-docs.json.
| Variable | Description | Default |
|---|---|---|
NODE_ENV |
Environment mode | development |
PORT |
Server port | 3000 |
DATABASE_URL |
PostgreSQL connection string | - |
CORS_ORIGIN |
Allowed origins (comma-separated or *) |
* |
JWT_SECRET |
JWT signing secret (min 32 chars) | - |
JWT_EXPIRES_IN |
Token expiration | 7d |
JWT_REFRESH_EXPIRES_IN |
Refresh token expiration | 30d |
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
API health status |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /register |
Register a new user | No |
| POST | /login |
Login and get tokens | No |
| POST | /refresh |
Refresh access token | No |
| POST | /logout |
Logout current user | Yes |
| GET | /me |
Get current user | Yes |
| GET | /verify-email |
Verify email via token | No |
| POST | /resend-verification |
Resend verification email | No |
| POST | /send-verification |
Send verification to current user | Yes |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | / |
List users (paginated) | No |
| POST | / |
Create user | No |
| GET | /:id |
Get user by ID | No |
| PATCH | /:id |
Update user | No |
| DELETE | /:id |
Delete user | No |
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /profile |
Get current user profile | Yes |
| PUT | /profile |
Update current user profile | Yes |
| POST | /change-password |
Change password | Yes |
| DELETE | /delete-account |
Delete own account | Yes |
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
List posts (paginated) |
| POST | / |
Create post |
| GET | /:id |
Get post by ID |
| PATCH | /:id |
Update post |
| DELETE | /:id |
Delete post |
page- Page number (default: 1)limit- Items per page (default: 10, max: 100)search- Search term (filters by relevant fields)
All responses follow a consistent structure:
{
"success": true,
"message": "Users retrieved successfully",
"data": [...],
"pagination": {
"page": 1,
"limit": 10,
"total": 50,
"totalPages": 5
}
}src/
├── config/ # Configuration & database setup
├── controllers/ # HTTP request handlers
├── middleware/ # Validation & error handling
├── routes/ # API route definitions
├── services/ # Business logic
├── types/ # TypeScript type definitions
├── utils/ # Helper functions
└── validators/ # Zod validation schemas
Request Flow: Routes → Middleware → Controllers → Services → Prisma → Database
# Development
npm run dev # Start with hot reload
npm run build # Compile TypeScript
npm start # Run production build
# Database
npm run db:generate # Generate Prisma client
npm run db:push # Push schema to database
npm run db:migrate # Run migrations
npm run db:studio # Open Prisma Studio
# Docker
npm run docker:dev # Start dev containers
npm run docker:dev:down # Stop dev containers
# Linting
npm run lint # Check for issues
npm run lint:fix # Fix issuesThis repo includes .github/workflows/node-api-cicd.yml.
- CI: installs dependencies and runs
npm run build - CD: builds Docker image, pushes to AWS ECR, then deploys on VPS over SSH
Deployment files are in deploy/:
deploy/docker-compose.vps.ymldeploy/.env.vps.exampledeploy/README.md(first-time setup and required GitHub secrets)
Runtime environment variables are injected from GitHub Secret APP_ENV_B64 during deployment.
- Define the model in
prisma/schema.prisma - Generate client:
npm run db:generate - Create validator:
src/validators/{resource}.validator.ts - Create service:
src/services/{resource}.service.ts - Create controller:
src/controllers/{resource}.controller.ts - Create routes:
src/routes/{resource}.routes.ts - Mount routes in
src/routes/index.ts
- Layered Architecture - Clear separation of concerns
- Validation Middleware - Zod schemas validate all inputs
- Centralized Error Handling - AppError class with global handler
- Type Safety - Full TypeScript with strict mode
- Graceful Shutdown - Proper cleanup on SIGTERM/SIGINT
MIT