A comprehensive backend API for a custom tailoring service platform built with Node.js, Express, TypeScript, Prisma, and PostgreSQL. TailorCraft enables clients to book custom tailoring services, manage bookings, make payments, and interact with tailors efficiently.
- ** Interactive API Documentation** - Swagger UI
- *** Swagger Guide** - How to use the API documentation
- Health Check - API status
- Features
- Tech Stack
- Project Structure
- Prerequisites
- Installation
- Environment Variables
- Database Setup
- Running the Application
- API Documentation
- Core Services
- Deployment
- Scripts
- Documentation
- Contributing
- License
- User registration with OTP email verification
- JWT-based authentication (access & refresh tokens)
- Role-based access control (Admin & Client)
- Forgot password with OTP reset
- Token revocation and automatic cleanup
- Automatic expired OTP cleanup (every 5 minutes)
- Profile management with image upload (Cloudinary)
- Address and preferred pickup address management
- User statistics and analytics (Admin)
- Create bookings with custom or pre-designed styles
- Measurement submission (JSON format)
- Booking status tracking (Pending, Approved, In Progress, Completed, Cancelled)
- Automatic delivery reminders (3 days, 1 day before)
- Admin booking management
- Paystack payment gateway integration
- Full and installment payment options
- Payment verification
- Webhook handling for payment updates
- Automatic fund transfers to admin account
- Payment history and statistics
- Test payment simulation
- Pre-designed clothing catalog (Native, Casual, Formal)
- Design with multiple images
- Price range management
- Minimum delivery time
- Required materials tracking
- Measurement guides and tutorials
- Client reviews on completed bookings
- Rating system (1-5 stars)
- Admin review moderation
- Rate limiting with Redis
- Automated background jobs (cron)
- Email notifications (Resend/Gmail)
- File upload with Cloudinary
- CORS configuration
- Helmet security
- Health check endpoint
- Keep-alive service for hosting platforms
- Runtime: Node.js 18+
- Language: TypeScript 5.8
- Framework: Express 5.1
- Database: PostgreSQL (Neon)
- ORM: Prisma 6.8
- Authentication: JWT (jsonwebtoken), Argon2
- Validation: Zod
- Payment: Paystack API
- Cloud Storage: Cloudinary
- Email: Resend / Nodemailer
- Caching: Redis, IORedis
- Cron Jobs: node-cron
- File Upload: Multer
- Security: Helmet, express-rate-limit
tailor_craft_backend/
├── src/
│ ├── admin/ # Admin creation scripts
│ │ └── createAdmin.ts
│ ├── config/ # Configuration files
│ │ ├── cloudinary.config.ts
│ │ ├── config.ts
│ │ ├── cors.config.ts
│ │ └── database.ts
│ ├── controllers/ # Route controllers
│ │ ├── auth.controller.ts
│ │ ├── booking.controller.ts
│ │ ├── payment.controller.ts
│ │ ├── profile.controller.ts
│ │ ├── review.controller.ts
│ │ └── admin/
│ │ ├── admin.controller.ts
│ │ ├── design.controller.ts
│ │ └── guide.controller.ts
│ ├── middleware/ # Express middleware
│ │ ├── auth.middleware.ts
│ │ ├── rateLimitter.middleware.ts
│ │ ├── redis.middleware.ts
│ │ ├── upload.middleware.ts
│ │ └── validate.middleware.ts
│ ├── routes/ # API routes
│ │ ├── auth.routes.ts
│ │ ├── booking.routes.ts
│ │ ├── payment.routes.ts
│ │ ├── profile.routes.ts
│ │ ├── review.routes.ts
│ │ └── admin/
│ │ ├── admin.routes.ts
│ │ ├── design.routes.ts
│ │ └── guide.routes.ts
│ ├── services/ # Business logic
│ │ ├── auth.ts
│ │ ├── booking.service.ts
│ │ ├── cleanup.service.ts
│ │ ├── keep-alive.service.ts
│ │ ├── payment.service.ts
│ │ ├── profile.services.ts
│ │ ├── reminder.service.ts
│ │ ├── review.ts
│ │ └── admin/
│ │ ├── admin.service.ts
│ │ ├── design.service.ts
│ │ └── guide.service.ts
│ ├── types/ # TypeScript types
│ │ ├── index.d.ts
│ │ ├── paystack.d.ts
│ │ └── types.ts
│ ├── utils/ # Utility functions
│ │ ├── cloudinary.utils.ts
│ │ ├── email.service.ts
│ │ ├── email.ts
│ │ ├── error.utils.ts
│ │ ├── helpers.utils.ts
│ │ └── paystack.utils.ts
│ ├── validation/ # Zod schemas
│ │ ├── auth.ts
│ │ ├── booking.validation.ts
│ │ ├── design.ts
│ │ ├── guide.ts
│ │ ├── profile.validation.ts
│ │ └── review.ts
│ ├── health/ # Health check
│ │ └── health.ts
│ ├── app.ts # Express app setup
│ └── index.ts # Server entry point
├── migrations/ # Prisma migrations
├── schema.prisma # Prisma schema
├── tsconfig.json # TypeScript config
├── package.json # Dependencies
└── .env # Environment variables
- Node.js (v18 or higher)
- PostgreSQL database
- Redis (optional, for rate limiting)
- Cloudinary account (for image uploads)
- Paystack account (for payments)
- Email service (Resend or Gmail)
- Clone the repository
git clone https://github.com/Chinweike99/tailor_craft_backend.git
cd tailor_craft_backend- Install dependencies
npm install
# or
pnpm install
# or
yarn install- Set up environment variables
cp .env.example .env
# Edit .env with your configuration- Generate Prisma Client
npm run postinstall- Run database migrations
npm run db:migrate- Create admin user
npm run adminCreate a .env file in the root directory with the following variables:
# Server Configuration
PORT=4000
NODE_ENV=development
FRONTEND_PORT1=https://your-frontend-url.com
FRONTEND_PORT2=https://your-frontend-url-2.com
# Database Configuration
DATABASE_URL=postgresql://user:password@host:port/database?sslmode=require
EXTERNAL_DB_URL=postgresql://user:password@host:port/database?sslmode=require
DATABASE_HOST_NAME=your-db-host
# JWT Configuration
JWT_SECRET=your-super-secret-jwt-key
JWT_ACCESS_EXPIRATION=2h
JWT_REFRESH_EXPIRATION=7d
# Redis Configuration (Optional)
REDIS_URL=redis://localhost:6379
# Paystack Configuration
PAYSTACK_SECRET_KEY=sk_test_your_secret_key
PAYSTACK_PUBLIC_KEY=pk_test_your_public_key
PAYSTACK_IS_LIVE=false
# Cloudinary Configuration
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret
# Email Configuration (Resend)
RESEND_API_KEY=re_your_resend_api_key
EMAIL_SERVICE=resend
EMAIL_FROM=noreply@yourdomain.com
# Or use Gmail
# EMAIL_SERVICE=gmail
# EMAIL_USER=your-email@gmail.com
# EMAIL_PASS=your-app-password
# EMAIL_FROM=your-email@gmail.com
# Admin Account Configuration
ADMIN_EMAIL=admin@tailorcraft.com
ADMIN_PASS=SecurePassword123!
ADMIN_PHONE=09123456789
ADMIN_NAME=TailorCraft Admin
ACCOUNT_NAME=TailorCraft Fashion
ADMIN_ACCOUNT_NUMBER=1234567890
ADMIN_BANK_CODE=058
# Render Configuration (for deployment)
RENDER_EXTERNAL_URL=https://your-app-name.onrender.com
RENDER_SERVICE_ID=your-service-id
RENDER_API_KEY=your-api-key- Create a free account at Neon
- Create a new project and database
- Copy the connection string to
DATABASE_URLin.env
- Install PostgreSQL on your machine
- Create a database:
CREATE DATABASE tailorcraft_db;- Update
DATABASE_URLin.env
# Apply all migrations
npm run db:migrate
# Create a new migration (development)
npm run db:migrate:dev
# Check migration status
npm run db:migrate:status
# Reset database ( DANGER: Deletes all data)
npm run db:migrate:reset
# Open Prisma Studio (GUI for database)
npm run db:studionpm run devServer runs on http://localhost:4000
Access Points:
- Home:
http://localhost:4000/ - API Docs:
http://localhost:4000/api-docs - Health:
http://localhost:4000/api/v1/health
# Build the project
npm run build
# Start production server
npm startnpm run adminnpm run paymentThe API includes comprehensive Swagger/OpenAPI 3.0 documentation with an interactive interface.
Access the Swagger UI:
- Development: http://localhost:4000/api-docs
- Production: https://your-app-name.onrender.com/api-docs
Features:
- Interactive Testing - Try all endpoints directly in your browser
- Complete Documentation - All 40+ endpoints with detailed descriptions
- Authentication Support - Test protected endpoints with JWT tokens
- Request/Response Examples - See exactly what data to send and expect
- Schema Definitions - Explore all data models and types
- No Setup Required - Works out of the box
Read the detailed guide: SWAGGER_GUIDE.md
Base URL: http://localhost:4000/api/v1
Endpoint Summary:
- Authentication: 7 endpoints (register, login, verify-otp, etc.)
- Profile: 3 endpoints (get, update, upload image)
- Bookings: 5 endpoints (create, list, update status, etc.)
- Payments: 7 endpoints (initialize, verify, history, etc.)
- Designs: 5 endpoints (CRUD operations)
- Guides: 5 endpoints (CRUD operations)
- Reviews: 3 endpoints (create, list)
- Admin: 4 endpoints (stats, client management)
- Health: 1 endpoint (health check)
For detailed endpoint documentation with request/response examples, see the Swagger UI.
POST /api/v1/auth/register
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"phone": "08012345678",
"password": "SecurePass123!"
}
Response: 200 OK
{
"message": "OTP Sent to email",
"data": {...}
}POST /api/v1/auth/verify-otp
Content-Type: application/json
{
"email": "john@example.com",
"otp": "123456"
}
Response: 200 OK
{
"user": {...},
"tokens": {
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc..."
}
}POST /api/v1/auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "SecurePass123!"
}
Response: 200 OK
{
"user": {...},
"tokens": {
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc..."
}
}POST /api/v1/auth/refresh-token
Content-Type: application/json
{
"refreshToken": "eyJhbGc..."
}
Response: 200 OK
{
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc..."
}POST /api/v1/auth/forgot-password
Content-Type: application/json
{
"email": "john@example.com"
}
Response: 200 OK
{
"message": "OTP sent to email"
}POST /api/v1/auth/reset-password
Content-Type: application/json
{
"email": "john@example.com",
"otp": "123456",
"newPassword": "NewSecurePass123!"
}
Response: 200 OK
{
"message": "Password reset successfully"
}POST /api/v1/auth/logout
Authorization: Bearer {accessToken}
Response: 200 OK
{
"message": "Logged out successfully"
}All profile endpoints require authentication.
GET /api/v1/profile
Authorization: Bearer {accessToken}
Response: 200 OK
{
"id": "uuid",
"name": "John Doe",
"email": "john@example.com",
"phone": "08012345678",
"profileImage": "https://cloudinary.com/...",
"bio": "Fashion enthusiast",
"address": {...},
"preferredPickupAddress": {...}
}PATCH /api/v1/profile
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"name": "John Updated",
"bio": "Updated bio",
"address": {
"street": "123 Main St",
"city": "Lagos",
"state": "Lagos",
"country": "Nigeria"
}
}
Response: 200 OKPOST /api/v1/profile/upload
Authorization: Bearer {accessToken}
Content-Type: multipart/form-data
image: [file]
Response: 200 OK
{
"message": "Profile image uploaded successfully",
"imageUrl": "https://cloudinary.com/..."
}POST /api/v1/booking
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"designId": "uuid", // Optional if customDesign provided
"customDesign": { // Optional if designId provided
"description": "Custom design details",
"images": ["url1", "url2"]
},
"measurements": {
"chest": "42",
"waist": "34",
"shoulder": "18",
"sleeve": "24"
},
"deliveryDate": "2026-02-15T00:00:00Z",
"notes": "Please use silk material"
}
Response: 201 Created
{
"id": "uuid",
"status": "PENDING",
"paymentStatus": "UNPAID",
...
}GET /api/v1/booking
Authorization: Bearer {accessToken}
Response: 200 OK
[
{
"id": "uuid",
"status": "PENDING",
"deliveryDate": "2026-02-15",
...
}
]GET /api/v1/booking/:id
Authorization: Bearer {accessToken}
Response: 200 OK
{
"id": "uuid",
"userId": "uuid",
"measurements": {...},
"status": "APPROVED",
...
}PATCH /api/v1/booking/:id/status
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"status": "APPROVED", // or "DECLINED", "IN_PROGRESS", "COMPLETED"
"declineReason": "Optional reason for decline"
}
Response: 200 OKGET /api/v1/booking/admin/all
Authorization: Bearer {accessToken}
Response: 200 OK
[...]POST /api/v1/payment/:bookingId
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"isInstallment": false, // true for partial payment
"amount": 50000 // Optional, for installment
}
Response: 200 OK
{
"paymentUrl": "https://checkout.paystack.com/...",
"reference": "REF_...",
"amount": 50000
}GET /api/v1/payment/verify?reference=REF_xxx
Authorization: Bearer {accessToken}
Response: 200 OK
{
"message": "Payment verified successfully",
"payment": {...}
}GET /api/v1/payment/history
Authorization: Bearer {accessToken}
Response: 200 OK
[
{
"id": "uuid",
"amount": 50000,
"status": "SUCCESS",
"createdAt": "2026-01-05",
...
}
]GET /api/v1/payment/all-payment
Authorization: Bearer {accessToken}
Response: 200 OKGET /api/v1/payment/stats
Authorization: Bearer {accessToken}
Response: 200 OK
{
"totalRevenue": 500000,
"totalPayments": 10,
"successfulPayments": 8,
...
}POST /api/v1/payment/webhook
X-Paystack-Signature: {signature}
{
"event": "charge.success",
"data": {...}
}GET /api/v1/design
Authorization: Bearer {accessToken}
Response: 200 OK
[
{
"id": "uuid",
"title": "Agbada",
"description": "Traditional Nigerian attire",
"images": ["url1", "url2"],
"category": "NATIVE",
"priceRange": {
"min": 30000,
"max": 80000
},
"minimumDeliveryTime": 7
}
]GET /api/v1/design/:id
Authorization: Bearer {accessToken}
Response: 200 OKPOST /api/v1/design
Authorization: Bearer {accessToken}
Content-Type: multipart/form-data
title: "Senator Wear"
description: "Modern senator style"
category: "FORMAL"
priceRange: {"min": 25000, "max": 50000}
minimumDeliveryTime: 5
requiredMaterials: ["Fabric", "Thread"]
images: [file1, file2]
Response: 201 CreatedPATCH /api/v1/design/:id
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"title": "Updated title",
"isActive": false
}
Response: 200 OKDELETE /api/v1/design/:id
Authorization: Bearer {accessToken}
Response: 200 OKGET /api/v1/guide
Authorization: Bearer {accessToken}
Response: 200 OKGET /api/v1/guide/:id
Authorization: Bearer {accessToken}
Response: 200 OKPOST /api/v1/guide
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"title": "How to Measure Chest",
"description": "Step by step guide",
"type": "VIDEO", // or "PDF", "IMAGE"
"resourceUrl": "https://youtube.com/..."
}
Response: 201 CreatedPATCH /api/v1/guide/:id
Authorization: Bearer {accessToken}
Response: 200 OKDELETE /api/v1/guide/:id
Authorization: Bearer {accessToken}
Response: 200 OKPOST /api/v1/review/:bookingId
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"rating": 5,
"comment": "Excellent work!"
}
Response: 201 CreatedGET /api/v1/review
Authorization: Bearer {accessToken}
Response: 200 OKGET /api/v1/review/admin
Authorization: Bearer {accessToken}
Response: 200 OKGET /api/v1/client
Authorization: Bearer {accessToken}
Response: 200 OKGET /api/v1/client/stats
Authorization: Bearer {accessToken}
Response: 200 OK
{
"totalClients": 50,
"totalBookings": 120,
"totalRevenue": 5000000,
...
}GET /api/v1/client/:id
Authorization: Bearer {accessToken}
Response: 200 OKDELETE /api/v1/client/:id
Authorization: Bearer {accessToken}
Response: 200 OKGET /api/v1/health
Response: 200 OK
{
"status": "OK",
"timestamp": "2026-01-06T...",
"uptime": 3600
}Automatically removes expired OTP records and revoked tokens every 5 minutes to maintain database hygiene.
// Located in: src/services/cleanup.service.ts
- Runs on startup
- Cron schedule: */5 * * * * (every 5 minutes)
- Cleans expired PendingVerification records
- Cleans expired RevokedToken recordsSends automated email reminders to clients about upcoming delivery dates.
// Located in: src/services/reminder.service.ts
- Sends reminder 3 days before delivery
- Sends reminder 1 day before delivery
- Checks daily at 9:00 AMPrevents free-tier hosting platforms from sleeping by pinging the server every 14 minutes.
// Located in: src/services/keep-alive.service.ts
- Pings health endpoint every 14 minutes
- Only runs in productionHandles all email communications using Resend or Gmail.
// Located in: src/utils/email.service.ts
- OTP emails
- Password reset emails
- Booking confirmations
- Delivery remindersManages Paystack integration for payment processing.
// Located in: src/services/payment.service.ts
- Initialize payments
- Verify transactions
- Handle webhooks
- Process refunds
- Automatic fund transfers-
Create a new Web Service on Render
-
Connect your GitHub repository
-
Configure build settings:
- Build Command:
npm run build:render - Start Command:
npm start
- Build Command:
-
Add environment variables (from
.envfile) -
Deploy!
The app automatically detects the environment:
NODE_ENV=development- Local developmentNODE_ENV=production- Production deployment
| Script | Description |
|---|---|
npm run dev |
Start development server with hot reload |
npm run build |
Build TypeScript to JavaScript |
npm start |
Start production server |
npm run admin |
Create admin user |
npm run payment |
Test payment flow |
npm run lint |
Run ESLint |
npm run db:migrate |
Deploy database migrations |
npm run db:migrate:dev |
Create new migration |
npm run db:migrate:status |
Check migration status |
npm run db:migrate:reset |
Reset database ( |
npm run db:studio |
Open Prisma Studio |
- Password hashing with Argon2
- JWT-based authentication with token rotation
- Token revocation system
- Rate limiting (100 requests per 15 minutes)
- CORS protection
- Helmet security headers
- Input validation with Zod
- SQL injection protection (Prisma)
- XSS protection
npm testStores client and admin information with authentication details.
Temporary storage for unverified registrations with OTP.
Customer orders with measurements and delivery information.
Pre-made clothing designs catalog.
Payment transactions and history.
Customer feedback and ratings.
Measurement guides and tutorials.
Scheduled delivery reminders.
Invalidated JWT tokens for logout.
This project includes comprehensive documentation for developers:
- Swagger UI - Interactive API documentation
- Test all endpoints in your browser
- View request/response schemas
- Built-in JWT authentication
- 40+ endpoints fully documented
- SWAGGER_GUIDE.md - Complete guide to using the Swagger documentation
- QUICK_START.md - Quick start guide for testing the API
- IMPLEMENTATION_SUMMARY.md - Swagger implementation details
- TESTING_CHECKLIST.md - Checklist to verify everything works
- OpenAPI 3.0 specification
- Interactive endpoint testing
- Complete schema definitions
- Authentication examples
- Error response documentation
- Production-ready
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
For support, email tailorcraft.fashion@gmail.com
This project is licensed under the ISC License.
- Prisma - Next-generation ORM
- Paystack - Payment processing
- Cloudinary - Image management
- Resend - Email delivery
- Neon - Serverless PostgreSQL
Built by Chinweike Akwolu
Repository: https://github.com/Chinweike99/tailor_craft_backend