n8n SaaS Platform - Complete Documentation
Version : 1.0.0
Last Updated : January 2, 2026
Status : Development - Phase 1 Complete, Phase 2 Planned
A complete SaaS platform for hosting n8n automation instances with subscription-based billing, designed for the Egyptian market.
Project Overview
Completed Features
Technology Stack
Project Structure
Database Schema
API Endpoints
Business Logic
Admin Panel Features
Next Phase: n8n Instance Provisioning
Infrastructure Architecture
Setup Instructions
Environment Variables
Security Features
This platform enables customers to subscribe to hosted n8n automation instances. The system handles:
User Registration & Authentication
Subscription Management (Monthly/Annual plans)
Payment Processing (Paymob integration for Egyptian payments)
Support Ticketing System
Admin Dashboard for platform management
Automated n8n Instance Provisioning (Next Phase)
Egyptian businesses needing automation
Pricing in EGP (Egyptian Pounds)
Arabic-friendly UI
Phase 1 - Core Platform (DONE)
Technology
Purpose
Node.js 20+
Runtime environment
Express.js
Web framework
TypeScript
Type safety
Prisma ORM
Database abstraction
SQLite (dev) / PostgreSQL (prod)
Database
JWT
Authentication tokens
bcrypt
Password hashing
SendGrid
Email delivery
Paymob
Payment gateway
Technology
Purpose
Next.js 14+
React framework (App Router)
TypeScript
Type safety
TailwindCSS
Styling
Shadcn/ui
UI component library
Lucide Icons
Icon library
React Hook Form
Form management
Zod
Validation
Technology
Purpose
Docker
Containerization
Docker Swarm
Orchestration
Hetzner Cloud
VPS hosting
Traefik
Reverse proxy & SSL
PostgreSQL
Shared database
Redis
Queue for n8n
n8n-intag-store/
βββ backend/
β βββ prisma/
β β βββ schema.prisma # Database models
β β βββ seed.ts # Seed data script
β β βββ migrations/ # Database migrations
β βββ src/
β β βββ config/
β β β βββ database.ts # Prisma client
β β β βββ env.ts # Environment config
β β β βββ swagger.ts # API docs config
β β βββ controllers/
β β β βββ auth.controller.ts
β β β βββ user.controller.ts
β β β βββ subscription.controller.ts
β β β βββ payment.controller.ts
β β β βββ support.controller.ts
β β β βββ coupon.controller.ts
β β β βββ admin.controller.ts
β β β βββ webhook.controller.ts
β β βββ middleware/
β β β βββ auth.middleware.ts # JWT verification
β β β βββ admin.middleware.ts # Admin role check
β β β βββ validate.middleware.ts # Request validation
β β β βββ error.middleware.ts # Error handling
β β β βββ rateLimiter.middleware.ts
β β βββ routes/
β β β βββ auth.routes.ts
β β β βββ user.routes.ts
β β β βββ subscription.routes.ts
β β β βββ payment.routes.ts
β β β βββ support.routes.ts
β β β βββ coupon.routes.ts
β β β βββ admin.routes.ts
β β β βββ webhook.routes.ts
β β β βββ pricing.routes.ts
β β β βββ index.ts
β β βββ services/
β β β βββ auth.service.ts # Authentication logic
β β β βββ user.service.ts # User management
β β β βββ subscription.service.ts # Subscription logic
β β β βββ paymob.service.ts # Payment gateway
β β β βββ support.service.ts # Ticketing system
β β β βββ coupon.service.ts # Coupon management
β β β βββ pricing.service.ts # Dynamic pricing
β β β βββ admin.service.ts # Admin operations
β β β βββ email.service.ts # Email templates & sending
β β β βββ activityLog.service.ts # Audit logging
β β β βββ docker.service.ts # Container management (stub)
β β βββ utils/
β β β βββ jwt.ts # Token helpers
β β β βββ password.ts # Hashing utilities
β β β βββ validators.ts # Input validation
β β β βββ pagination.ts # Pagination helper
β β β βββ date.ts # Date formatting
β β βββ server.ts # Express app entry
β βββ .env.example
β βββ Dockerfile
β βββ package.json
β βββ tsconfig.json
β
βββ frontend/
β βββ app/
β β βββ (auth)/
β β β βββ login/page.tsx
β β β βββ signup/page.tsx
β β βββ (dashboard)/
β β β βββ dashboard/
β β β βββ page.tsx # User dashboard
β β β βββ billing/page.tsx
β β β βββ settings/page.tsx
β β β βββ support/page.tsx
β β β βββ layout.tsx
β β βββ admin/
β β β βββ page.tsx # Admin dashboard
β β β βββ layout.tsx # Admin layout with sidebar
β β β βββ users/page.tsx # User management
β β β βββ subscriptions/page.tsx
β β β βββ payments/page.tsx
β β β βββ coupons/page.tsx
β β β βββ pricing/page.tsx
β β β βββ tickets/page.tsx
β β β βββ activity/page.tsx
β β β βββ settings/page.tsx
β β βββ checkout/page.tsx
β β βββ pricing/page.tsx
β β βββ forgot-password/page.tsx
β β βββ reset-password/page.tsx
β β βββ verify-email/page.tsx
β β βββ layout.tsx # Root layout
β β βββ page.tsx # Landing page
β β βββ globals.css
β βββ components/
β β βββ ui/ # Shadcn components
β β β βββ button.tsx
β β β βββ card.tsx
β β β βββ input.tsx
β β β βββ table.tsx
β β β βββ dialog.tsx
β β β βββ ...
β β βββ Pagination.tsx # Reusable pagination
β β βββ Navbar.tsx
β β βββ Footer.tsx
β β βββ ...
β βββ lib/
β β βββ api.ts # API client
β β βββ auth.ts # Auth context
β β βββ utils.ts # Utility functions
β βββ .env.example
β βββ Dockerfile
β βββ package.json
β βββ tailwind.config.js
β βββ tsconfig.json
β
βββ docker/
β βββ docker-compose.dev.yml
β
βββ scripts/
β βββ setup-dev.ps1 # Windows dev setup
β βββ setup-dev.sh # Linux/Mac dev setup
β
βββ .gitignore
βββ README.md
model User {
id String @id @default (uuid () )
email String @unique
password String // bcrypt hashed
fullName String
phone String ?
role String @default (" user " ) // user, admin, super_admin, support_agent
status String @default (" active " ) // active, suspended, deleted
emailVerified Boolean @default (false )
instanceUrl String ? // n8n instance URL
containerId String ? // Docker container ID
// ... timestamps and relations
}
model Subscription {
id String @id @default (uuid () )
userId String
planType String // monthly, yearly
status String // active, paused, cancelled, expired, payment_failed, suspended
amount Float
currency String @default (" EGP " )
currentPeriodStart DateTime
currentPeriodEnd DateTime
nextBillingDate DateTime ?
pausedAt DateTime ?
cancelledAt DateTime ?
creditBalance Float @default (0 ) // For proration
// ... relations
}
model Payment {
id String @id @default (uuid () )
subscriptionId String
userId String
gatewayTransactionId String ?
paymentGateway String // paymob
amount Float
currency String @default (" EGP " )
status String // success, failed, pending, refunded
// ... relations
}
model Coupon {
id String @id @default (uuid () )
code String @unique
discountType String // percentage, fixed
discountValue Float
maxUses Int ? // null = unlimited
usedCount Int @default (0 )
validFrom DateTime
validUntil DateTime ?
isActive Boolean @default (true )
applicablePlans String ? // JSON: ["monthly", "yearly"]
minOrderAmount Float ?
}
model PricingConfig {
id String @id @default (uuid () )
planType String @unique // monthly, yearly
price Float
currency String @default (" EGP " )
displayName String
description String ?
features String @default (" []" ) // JSON array
isActive Boolean @default (true )
}
SupportTicket & SupportMessage
Full ticketing system with message threading
Category: billing, technical, refund, other
Priority: low, normal, high, urgent
Status workflow with SLA tracking
RefundRequest - Refund workflow
ActivityLog - Audit trail
EmailQueue - Reliable email delivery
WebhookLog - Payment webhook debugging
SystemSetting - Admin configuration
CouponUsage - Track coupon redemptions
Method
Endpoint
Description
POST
/api/auth/signup
Register new user
POST
/api/auth/login
User login
POST
/api/auth/logout
Logout (invalidate token)
POST
/api/auth/refresh
Refresh JWT token
POST
/api/auth/forgot-password
Request password reset
POST
/api/auth/reset-password
Reset password with token
GET
/api/auth/verify-email/:token
Verify email address
Method
Endpoint
Description
GET
/api/user/profile
Get current user profile
PUT
/api/user/profile
Update profile
PUT
/api/user/password
Change password
PUT
/api/user/email-preferences
Update email settings
Method
Endpoint
Description
GET
/api/subscription
Get user's subscription
POST
/api/subscription/create
Create new subscription
POST
/api/subscription/pause
Pause subscription
POST
/api/subscription/resume
Resume subscription
POST
/api/subscription/cancel
Cancel subscription
POST
/api/subscription/upgrade
Upgrade to annual
Method
Endpoint
Description
GET
/api/payments
List user's payments
GET
/api/payments/:id
Get payment details
GET
/api/payments/:id/invoice
Download invoice
POST
/api/payments/checkout
Initiate payment
Method
Endpoint
Description
POST
/api/coupons/validate
Validate a coupon code
POST
/api/coupons/apply
Apply coupon to order
Method
Endpoint
Description
GET
/api/support/tickets
List user's tickets
POST
/api/support/tickets
Create new ticket
GET
/api/support/tickets/:id
Get ticket details
POST
/api/support/tickets/:id/messages
Add message
PUT
/api/support/tickets/:id/close
Close ticket
Method
Endpoint
Description
GET
/api/pricing
Get all pricing plans
GET
/api/pricing/:planType
Get specific plan
Method
Endpoint
Description
POST
/api/webhooks/paymob
Payment success/failure
POST
/api/webhooks/paymob/refund
Refund completed
Admin Routes (require admin role)
Method
Endpoint
Description
GET
/api/admin/dashboard
Dashboard metrics
GET
/api/admin/users
List all users (paginated)
GET
/api/admin/users/:id
Get user details
PUT
/api/admin/users/:id
Update user
PUT
/api/admin/users/:id/suspend
Suspend user
GET
/api/admin/subscriptions
List all subscriptions
GET
/api/admin/payments
List all payments
GET
/api/admin/coupons
List all coupons
POST
/api/admin/coupons
Create coupon
PUT
/api/admin/coupons/:id
Update coupon
DELETE
/api/admin/coupons/:id
Delete coupon
GET
/api/admin/pricing
Get pricing config
PUT
/api/admin/pricing/:planType
Update pricing
GET
/api/admin/tickets
List all tickets
PUT
/api/admin/tickets/:id/assign
Assign ticket
GET
/api/admin/activity
Activity logs
GET
/api/admin/refunds
Refund requests
PUT
/api/admin/refunds/:id
Process refund
Plan
Price
Billing
Savings
Monthly
400 EGP
Recurring
-
Annual
3,800 EGP
Upfront
~20%
New User β Signup β Select Plan β Payment
β
Subscription Active β n8n Instance Created
β
[Payment Due] β Payment Success β Renewal
β β
β Payment Failed β Grace Period (7 days)
β β
β Retry Days 3, 5, 7
β β
β Still Failed β Suspended
β
[User Action] β Pause (max 30 days) β Resume
β
[User Action] β Cancel β Access until period end β Expired
7-day money-back guarantee on first payment
Full refund only (no partial refunds)
One refund per customer lifetime
Refund processed back to original payment method
7 days for failed payments
Automatic retry on days 3, 5, 7
Email notifications at each retry
Suspension after 7 days if still failed
π§ Admin Panel Features
Active subscriptions count
Monthly revenue (MRR)
New signups (today/week/month)
Active users
Open support tickets
Recent activity feed
Revenue chart
User Management (/admin/users)
List all users with pagination
Search by email/name
Filter by status/role
View user details
Edit user information
Suspend/reactivate users
Subscription Management (/admin/subscriptions)
List all subscriptions with pagination
Filter by status/plan type
View subscription details
Manual status changes
Payment History (/admin/payments)
List all payments with pagination
Filter by status/gateway
View payment details
Download invoices
Coupon Management (/admin/coupons)
Create new coupons
Edit existing coupons
Set discount type (percentage/fixed)
Set validity period
Set usage limits
Enable/disable coupons
View usage statistics
Pricing Configuration (/admin/pricing)
Edit plan prices
Update plan features (JSON array)
Toggle plan availability
Support Tickets (/admin/tickets)
List all tickets with pagination
Filter by status/priority/category
Assign to admin
Reply to tickets
Close/resolve tickets
Activity Logs (/admin/activity)
Audit trail of all actions
Filter by user/action type
IP address tracking
π Next Phase: n8n Instance Provisioning
Architecture Decision: Cluster Model (Cost-Optimized)
After analysis, we decided on a Docker Swarm cluster architecture using Hetzner Cloud ARM64 servers for maximum cost efficiency.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INTERNET β
ββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LOAD BALANCER NODE (CAX11 - β¬3.79/mo) β
β Traefik + SSL Termination β
β Routes: customer1.n8n.yoursite.com β
ββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββββββββββββββ
β WORKER NODE #1 β β WORKER NODE #2 β β SERVICES NODE β
β CAX31 ARM64 β β CAX31 ARM64 β β CAX21 ARM64 β
β 8 vCPU, 16GB RAM β β 8 vCPU, 16GB RAM β β 4 vCPU, 8GB RAM β
β β¬12.49/mo β β β¬12.49/mo β β β¬6.49/mo β
β [8 n8n instances]β β [8 n8n instances]β β PostgreSQL + Redis β
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββββββββββββββ
n8n Resource Requirements (per instance)
RAM : 2GB minimum per instance
CPU : 1 core minimum
Storage : Each instance gets its own PostgreSQL database
Customers
Worker Nodes
Monthly Cost
Cost/Customer
1-8
1Γ CAX31
β¬22.77
β¬2.85
9-16
2Γ CAX31
β¬35.26
β¬2.20
17-24
3Γ CAX31
β¬53.75
β¬2.24
25-40
5Γ CAX31
β¬81.43
β¬2.04
Customer Subscribes β Payment Confirmed
β
βΌ
βββββββββββββββββββββββββββββββββββββββ
β PROVISIONING SERVICE β
β β
β 1. Check cluster capacity β
β 2. If full: Add worker via Hetzner β
β 3. Create PostgreSQL database β
β 4. Deploy n8n container to swarm β
β 5. Configure DNS (Cloudflare) β
β 6. Wait for health check β
β 7. Email customer with credentials β
βββββββββββββββββββββββββββββββββββββββ
Required New Database Models
model N8nInstance {
id String @id @default (uuid () )
userId String @unique
subdomain String @unique // customer.n8n.yoursite.com
status InstanceStatus @default (PENDING )
allocatedRam Int @default (2048 ) // MB
allocatedCpu Int @default (1 )
workerId String ?
createdAt DateTime @default (now () )
suspendedAt DateTime ?
deletedAt DateTime ?
}
model ClusterNode {
id String @id @default (uuid () )
ip String
type String // manager, worker, services
hetznerId String
capacity Int @default (8 ) // max n8n instances
currentLoad Int @default (0 )
status String @default (" active " )
}
enum InstanceStatus {
PENDING
PROVISIONING
ACTIVE
SUSPENDED
DELETING
DELETED
ERROR
}
// New services to implement:
βββ services /
β βββ cluster . service . ts // Manage cluster nodes
β βββ hetzner . service . ts // Hetzner Cloud API
β βββ provisioning . service . ts // n8n instance lifecycle
β βββ dns . service . ts // Cloudflare DNS management
When subscription events occur:
Event
Action
subscription.created + payment.success
Provision n8n instance
payment.failed (after grace period)
Suspend instance (scale to 0)
payment.success (after failed)
Resume instance (scale to 1)
subscription.cancelled
Suspend immediately, schedule deletion in 30 days
Node.js 20+
PostgreSQL 15+ (or SQLite for dev)
npm or yarn
Git
# Clone repository
git clone < repository-url>
cd n8n-intag-store/backend
# Install dependencies
npm install
# Create environment file
cp .env.example .env
# Edit .env with your configuration
# Required: DATABASE_URL, JWT_SECRET
# Run database migrations
npx prisma migrate dev
# Seed initial data (optional)
npx prisma db seed
# Start development server
npm run dev
# Server runs on http://localhost:3001
cd n8n-intag-store/frontend
# Install dependencies
npm install
# Create environment file
cp .env.example .env.local
# Edit .env.local
# Required: NEXT_PUBLIC_API_URL=http://localhost:3001
# Start development server
npm run dev
# App runs on http://localhost:3000
Using Docker (Development)
cd n8n-intag-store
# Start all services
docker-compose -f docker/docker-compose.dev.yml up -d
# View logs
docker-compose -f docker/docker-compose.dev.yml logs -f
π Environment Variables
# Database
DATABASE_URL = " postgresql://user:password@localhost:5432/n8n_saas?schema=public"
# For SQLite (dev): DATABASE_URL="file:./dev.db"
# JWT Authentication
JWT_SECRET = " your-secure-random-string-min-32-chars"
JWT_EXPIRES_IN = " 1d"
# Server
PORT = 3001
NODE_ENV = development
# Payment Gateway (Paymob)
PAYMOB_API_KEY = " your-paymob-api-key"
PAYMOB_INTEGRATION_ID = " your-integration-id"
PAYMOB_HMAC_SECRET = " your-hmac-secret"
PAYMOB_IFRAME_ID = " your-iframe-id"
# Email (SendGrid)
SENDGRID_API_KEY = " SG.xxxxxxx"
SENDGRID_FROM_EMAIL = " noreply@yoursite.com"
SENDGRID_FROM_NAME = " n8n SaaS"
# Frontend URL (for emails/redirects)
FRONTEND_URL = " http://localhost:3000"
# Admin Credentials (for seeding)
ADMIN_EMAIL = " admin@yoursite.com"
ADMIN_PASSWORD = " secure-admin-password"
# Future: Hetzner Cloud
HETZNER_API_TOKEN = " "
# Future: Cloudflare
CLOUDFLARE_API_TOKEN = " "
CLOUDFLARE_ZONE_ID = " "
NEXT_PUBLIC_API_URL = " http://localhost:3001"
NEXT_PUBLIC_APP_NAME = " n8n SaaS"
NEXT_PUBLIC_APP_URL = " http://localhost:3000"
HTTPS enforced in production
Passwords hashed with bcrypt (12 rounds)
JWT tokens with 24-hour expiration
Input validation on all endpoints (Zod)
SQL injection prevention via Prisma ORM
XSS prevention with input sanitization
CSRF protection on state-changing endpoints
Rate limiting on auth endpoints
Helmet.js for secure HTTP headers
CORS configured for allowed origins
cd backend
npm run test
cd frontend
npm run test
# Create new migration
npx prisma migrate dev --name migration_name
# Apply migrations
npx prisma migrate deploy
# Reset database
npx prisma migrate reset
ESLint + Prettier configured
Run npm run lint to check
Run npm run format to auto-fix
This is a private project. Contact the owner for access.
Private - All Rights Reserved
Built with β€οΈ for Egyptian businesses