Zaptam - Product Requirements Document
Version: 1.0
Last Updated: March 2026
Status: Built & Documented
Table of Contents
- Executive Summary
- Vision & Mission
- Problem Statement
- Solution Overview
- Target Audience
- Core Features
- User Journeys
- Data Models
- API Reference
- Service Architecture
- Matching Algorithm
- Authentication System
- Billing & Premium Features
- Content Moderation & Trust System
- Technical Stack
- Gaps & Missing Features
1. Executive Summary
Zaptam is a private, verified dating and companionship network targeting the African market with a focus on exclusivity, discretion, and trust. Unlike traditional dating apps, Zaptam implements a rigorous verification system where:
- Men must verify their financial capacity ("worth verification")
- Women must verify their identity ("value verification")
The platform operates on a gender-asymmetric business model:
- Men pay for membership ($49-$499/month)
- Women join free after passing verification and acceptance review
The system consists of four interconnected applications:
- zaptam-api: Backend REST API + WebSocket server
- zaptam-app: User-facing mobile/web app (React)
- zaptam-admin: Administrative dashboard (React)
- zaptam-landing: Marketing website (React)
2. Vision & Mission
Vision
"Not Everyone Deserves Access" — Create the most trusted network for adults seeking genuine connections through rigorous verification and exclusive membership.
Mission
- Build a high-trust dating network where worth and value are verified, not claimed
- Protect user privacy with industry-leading security measures
- Maintain quality through selective approval and ongoing behavioral monitoring
- Create a value balance: men bring financial capacity, women bring authentic presence
Core Principles
- Verification First: Every member undergoes rigorous screening
- Privacy Protected: Screenshot protection, alias mode, encrypted messaging
- Quality Over Quantity: 8% acceptance rate (claimed target)
- Discretion First: No public profiles, no social sharing
- Zero Tolerance: Immediate action on misconduct
3. Problem Statement
Industry Problems
- Fake Profiles: Traditional dating apps are plagued with fake accounts and catfishing
- Low Commitment: Free apps attract users who aren't invested
- Privacy Concerns: Users fear exposure and lack control over their data
- Misaligned Incentives: Apps optimize for time spent swiping, not actual connections
- Safety Issues: Inadequate verification leads to harassment, scams, and blackmail
African Market Specific
- Cultural need for discretion in dating
- Growing affluent population seeking premium services
- Lack of high-quality, verified dating platforms in the region
- Trust deficit in online interactions
4. Solution Overview
Zaptam addresses these problems through:
| Problem | Solution |
|---|---|
| Fake profiles | Multi-tier verification system (ID, Worth, Value) |
| Low commitment | Paid membership for men ($49-499/month) |
| Privacy concerns | Alias mode, photo blur, screenshot detection, panic delete |
| Misaligned incentives | Match-based messaging (must both express interest) |
| Safety issues | Trust scoring, behavioral monitoring, blackmail hotline |
Key Differentiators
- Worth Verification (Men): Financial capacity demonstration
- Value Verification (Women): Identity verification + selective acceptance
- Trust Score: Dynamic 0-100 score based on behavior
- Panic Delete: Instant, permanent data wipe
- Screenshot Detection: Notify victims + trust penalty for offender
5. Target Audience
Male Users
- Demographics: 25-55, professional/business owners
- Income: Upper-middle to high income
- Needs: Quality connections, discretion, verified partners
- Pain Points: Fake profiles, time-wasters, privacy exposure
Female Users
- Demographics: 21-45, various backgrounds
- Needs: Safe environment, verified partners, earning potential
- Pain Points: Harassment, fake profiles, unwanted exposure
- Incentive: Free access + earnings from engagement
Admin Users
- Curators: Review verifications, handle basic reports
- Admins: User management, payouts, advanced moderation
- Super Admins: Full system access, analytics, configuration
6. Core Features
6.1 User Features
Authentication & Onboarding
- Phone number registration with OTP verification
- Gender-specific application process
- Multi-step profile completion
- Password-protected accounts
- Refresh token rotation
Profile Management
- Alias mode (hide real name)
- Bio and personal information
- Photo gallery with blur control
- Verification badges
- Trust score display
Discovery & Matching
- Browse opposite gender profiles (default)
- Filter by verification level
- Express interest (one-way)
- Mutual match detection
- Priority ordering (verified + high trust first)
Messaging
- Real-time WebSocket messaging
- Conversation list with unread counts
- Typing indicators
- Read receipts
- Disappearing messages (configurable)
- Media sharing
Privacy Controls
- Alias Mode: Use generated alias instead of real name
- Photo Blur: Set blur level 0-100% on photos
- Region Masking: Hide exact location
- Online Status: Toggle visibility
- Disappearing Messages: Auto-delete after set hours
- Panic Delete: Instant account wipe
Wallet & Transactions
- View balance (USD)
- Purchase credits (men)
- Request withdrawals (women)
- Transaction history
- Membership tier selection
6.2 Admin Features
Dashboard
- Total users (by gender, status)
- Pending verifications count
- Pending reports count
- Total matches
- User growth trends
- Revenue metrics
User Management
- List all users with filters/search
- View user details
- Update user status (suspend/ban)
- Adjust trust scores
- Change verification levels
Verification Queue
- List pending verifications
- Review documents
- Approve/reject with notes
- Auto-update user verification level
Report Handling
- List reports by type/status
- View report details
- Resolve or dismiss
- Apply trust penalties
- Ban offenders
Transaction Management
- View all transactions
- Process withdrawal requests
- Approve/reject payouts
- Revenue analytics
7. User Journeys
7.1 Male User Journey
1. DISCOVER → Landing page exposure
↓
2. APPLY → Submit application (phone, gender, email, occupation, net worth)
↓
3. VERIFY PHONE → Receive OTP via WhatsApp/SMS, enter code
↓
4. COMPLETE PROFILE → Set password, bio, date of birth
↓
5. PENDING APPROVAL → Wait for admin to approve worth verification
↓
6. ACTIVATED → Account becomes ACTIVE
↓
7. SUBSCRIBE → Choose membership tier ($49/$149/$499)
↓
8. PURCHASE CREDITS → Buy credits for messaging/unlocks
↓
9. DISCOVER → Browse verified female profiles
↓
10. EXPRESS INTEREST → Send interest to profiles
↓
11. MATCH → When interest is mutual
↓
12. MESSAGE → Start conversation with match
↓
13. MEET → Arrange real-world meeting7.2 Female User Journey
1. DISCOVER → Landing page exposure
↓
2. APPLY → Submit application (phone, gender, email, intro, photos)
↓
3. VERIFY PHONE → Receive OTP, enter code
↓
4. COMPLETE PROFILE → Set password, bio, date of birth
↓
5. IDENTITY VERIFICATION → Submit ID documents
↓
6. ACCEPTANCE REVIEW → Admin reviews (may reject even if verified)
↓
7. ACTIVATED → Account becomes ACTIVE (free membership)
↓
8. DISCOVER → Browse verified male profiles
↓
9. RECEIVE INTERESTS → Get notified of interests
↓
10. ACCEPT/DECLINE → Respond to interests
↓
11. MATCH → Interest accepted = match created
↓
12. MESSAGE → Chat with matches
↓
13. EARN → Receive earnings from engagement (to wallet)
↓
14. WITHDRAW → Request payout (min $10)7.3 Admin Journey
1. LOGIN → Authenticate with admin credentials
↓
2. DASHBOARD → View system overview
↓
3. VERIFICATIONS → Review pending verifications
├── APPROVE → User level upgraded
└── REJECT → User notified, can resubmit
↓
4. REPORTS → Handle user reports
├── INVESTIGATE → Escalate blackmail
├── RESOLVE → Apply penalties, ban if needed
└── DISMISS → Close without action
↓
5. USERS → Manage user accounts
├── SUSPEND → Temporary restriction
├── BAN → Permanent block
└── RECALCULATE TRUST → Update trust score
↓
6. PAYOUTS → Process withdrawal requests
├── APPROVE → Release funds
└── REJECT → Notify user
↓
7. ANALYTICS → Review growth and revenue metrics8. Data Models
8.1 User Model
model User {
id String @id @default(uuid()) @db.Uuid
phoneNumber String @unique
email String? @unique
password String? // Hashed, nullable during application
role UserRole @default(USER)
gender Gender? // MALE | FEMALE
status UserStatus @default(PENDING)
// Profile
alias String? @unique // System-generated or custom
name String? // Real name (hidden in alias mode)
bio String? // User description
occupation String? // For male users
intro String? // For female users
netWorth String? // For male users
dateOfBirth DateTime?
// Trust & Verification
trustScore Int @default(50) // 0-100
verificationLevel VerificationLevel @default(NONE)
// Timestamps
lastActiveAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime? // Soft delete
// Relations
settings UserSettings?
photos Photo[]
sentMessages Message[] @relation("sender")
receivedMessages Message[] @relation("recipient")
sentInterests Interest[] @relation("sender")
receivedInterests Interest[] @relation("recipient")
verifications Verification[]
walletTransactions WalletTransaction[]
reports Report[] @relation("reporter")
reportedBy Report[] @relation("reported")
conversations1 Conversation[] @relation("participant1")
conversations2 Conversation[] @relation("participant2")
refreshTokens RefreshToken[]
otpCodes OtpCode[]
}8.2 UserSettings Model
model UserSettings {
id String @id @default(uuid()) @db.Uuid
userId String @unique @db.Uuid
aliasMode Boolean @default(true) // Hide real name
showOnlineStatus Boolean @default(false) // Show when online
regionMasking Boolean @default(true) // Hide exact location
photoBlurLevel Int @default(100) // 0-100, default fully blurred
disappearingMsgs Int? // Hours until auto-delete
}8.3 Photo Model
model Photo {
id String @id @default(uuid()) @db.Uuid
userId String @db.Uuid
url String // R2/S3 URL
blurLevel Int @default(100) // 0-100
isPrimary Boolean @default(false) // Main profile photo
order Int @default(0) // Display order
createdAt DateTime @default(now())
}8.4 Interest Model
model Interest {
id String @id @default(uuid()) @db.Uuid
senderId String @db.Uuid
recipientId String @db.Uuid
status InterestStatus @default(PENDING) // PENDING | ACCEPTED | DECLINED
createdAt DateTime @default(now())
@@unique([senderId, recipientId]) // Prevent duplicate interests
}8.5 Conversation Model
model Conversation {
id String @id @default(uuid()) @db.Uuid
participant1Id String @db.Uuid
participant2Id String @db.Uuid
messages Message[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([participant1Id, participant2Id])
}8.6 Message Model
model Message {
id String @id @default(uuid()) @db.Uuid
conversationId String @db.Uuid
senderId String @db.Uuid
recipientId String @db.Uuid
content String? // Text content
mediaUrl String? // Media attachment URL
isRead Boolean @default(false)
expiresAt DateTime? // Disappearing message
deletedAt DateTime? // Soft delete
createdAt DateTime @default(now())
}8.7 Verification Model
model Verification {
id String @id @default(uuid()) @db.Uuid
userId String @db.Uuid
type VerificationType // IDENTITY | WORTH | VALUE
status VerificationStatus @default(PENDING)
documents Json? // Array of document URLs
notes String? // Admin notes
reviewedBy String? @db.Uuid
reviewedAt DateTime?
createdAt DateTime @default(now())
}8.8 WalletTransaction Model
model WalletTransaction {
id String @id @default(uuid()) @db.Uuid
userId String @db.Uuid
type TransactionType // MEMBERSHIP | CREDIT_PURCHASE | EARNING | WITHDRAWAL | BOOST
amount Decimal @db.Decimal(10, 2)
currency String @default("USD")
status TransactionStatus @default(PENDING) // PENDING | COMPLETED | FAILED | REFUNDED
reference String? // Payment gateway reference
createdAt DateTime @default(now())
}8.9 Report Model
model Report {
id String @id @default(uuid()) @db.Uuid
reporterId String @db.Uuid // Who filed the report
reportedId String @db.Uuid // Who is being reported
type ReportType // BLACKMAIL | HARASSMENT | FAKE_PROFILE | INAPPROPRIATE_CONTENT | OTHER
description String // Detailed description
evidence Json? // Screenshots, links, etc.
status ReportStatus @default(PENDING) // PENDING | INVESTIGATING | RESOLVED | DISMISSED
resolution String? // Admin's resolution notes
resolvedBy String? @db.Uuid
resolvedAt DateTime?
createdAt DateTime @default(now())
}8.10 MembershipTier Model
model MembershipTier {
id String @id @default(uuid()) @db.Uuid
name String // Standard, Premium, Elite
price Decimal @db.Decimal(10, 2) // Monthly price in USD
currency String @default("USD")
duration Int // Days
features Json // Array of feature strings
isActive Boolean @default(true)
createdAt DateTime @default(now())
}8.11 RefreshToken Model
model RefreshToken {
id String @id @default(uuid()) @db.Uuid
userId String @db.Uuid
token String @unique
expiresAt DateTime
createdAt DateTime @default(now())
}8.12 OtpCode Model
model OtpCode {
id String @id @default(uuid()) @db.Uuid
userId String? @db.Uuid
phone String
code String // 6-digit code
purpose OtpPurpose // REGISTRATION | LOGIN | PASSWORD_RESET
expiresAt DateTime
usedAt DateTime?
createdAt DateTime @default(now())
}8.13 Enums
enum UserRole {
USER
CURATOR
ADMIN
SUPER_ADMIN
}
enum Gender {
MALE
FEMALE
}
enum UserStatus {
PENDING // Application submitted
ACTIVE // Approved and verified
SUSPENDED // Temporarily restricted
BANNED // Permanently blocked
DELETED // Soft deleted
}
enum VerificationLevel {
NONE // No verification
IDENTITY // ID verified
FULL // ID + Worth/Value verified
}
enum VerificationType {
IDENTITY // Government ID
WORTH // Financial capacity (men)
VALUE // Additional verification (women)
}
enum VerificationStatus {
PENDING
APPROVED
REJECTED
}
enum InterestStatus {
PENDING
ACCEPTED
DECLINED
}
enum TransactionType {
MEMBERSHIP
CREDIT_PURCHASE
EARNING
WITHDRAWAL
BOOST
}
enum TransactionStatus {
PENDING
COMPLETED
FAILED
REFUNDED
}
enum ReportType {
BLACKMAIL
HARASSMENT
FAKE_PROFILE
INAPPROPRIATE_CONTENT
OTHER
}
enum ReportStatus {
PENDING
INVESTIGATING
RESOLVED
DISMISSED
}
enum OtpPurpose {
REGISTRATION
LOGIN
PASSWORD_RESET
}9. API Reference
9.1 Base URL & Headers
Production: https://api.zaptam.com
Local: http://localhost:3000
Headers:
Content-Type: application/json
Authorization: Bearer <access_token> (for protected routes)9.2 Authentication Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/auth/apply | Submit application | No |
| POST | /api/auth/verify-phone | Send OTP to phone | No |
| POST | /api/auth/confirm-phone | Verify OTP code | No |
| POST | /api/auth/complete-profile | Complete registration | No |
| POST | /api/auth/login | Login with credentials | No |
| POST | /api/auth/refresh | Refresh access token | No |
| POST | /api/auth/logout | Invalidate tokens | Yes |
| POST | /api/auth/forgot-password | Request password reset | No |
| POST | /api/auth/reset-password | Reset password with code | No |
9.3 User Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/users/me | Get current user | Yes |
| PATCH | /api/users/me | Update profile | Yes |
| GET | /api/users/me/settings | Get settings | Yes |
| PATCH | /api/users/me/settings | Update settings | Yes |
| POST | /api/users/me/photos | Upload photo | Yes |
| DELETE | /api/users/me/photos/:id | Delete photo | Yes |
| DELETE | /api/users/me | Delete account | Yes |
| POST | /api/users/me/panic-delete | Panic delete (hard) | Yes |
9.4 Discovery & Profile Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/discover | Browse profiles | Yes |
| GET | /api/profiles/:id | View profile detail | Yes |
| POST | /api/profiles/:id/interest | Express interest | Yes |
9.5 Match Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/matches | Get all matches | Yes |
| DELETE | /api/matches/:id | Remove/decline match | Yes |
9.6 Message Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/messages/conversations | List conversations | Yes |
| GET | /api/messages/conversations/:id | Get messages | Yes |
| POST | /api/messages/conversations/:id | Send message | Yes |
| DELETE | /api/messages/conversations/:id | Delete conversation | Yes |
| POST | /api/messages/messages/:id/report | Report a message | Yes |
9.7 Wallet Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/wallet | Get balance | Yes |
| GET | /api/wallet/transactions | Transaction history | Yes |
| POST | /api/wallet/purchase | Purchase credits | Yes |
| POST | /api/wallet/withdraw | Request withdrawal | Yes |
| GET | /api/wallet/membership-tiers | Get membership options | Yes |
9.8 Verification Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/verification/status | Get verification status | Yes |
| POST | /api/verification/identity | Submit ID verification | Yes |
| POST | /api/verification/worth | Submit worth (men) | Yes |
| POST | /api/verification/value | Submit value (women) | Yes |
9.9 Report Endpoints
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/reports | Submit report | Yes |
| POST | /api/reports/blackmail | Emergency blackmail report | Yes |
| GET | /api/reports/my-reports | View submitted reports | Yes |
9.10 Admin Endpoints
| Method | Endpoint | Description | Required Role |
|---|---|---|---|
| GET | /api/admin/dashboard | Dashboard stats | CURATOR+ |
| GET | /api/admin/users | List users | CURATOR+ |
| GET | /api/admin/users/:id | User detail | CURATOR+ |
| PATCH | /api/admin/users/:id | Update user | ADMIN+ |
| POST | /api/admin/users/:id/suspend | Suspend user | ADMIN+ |
| POST | /api/admin/users/:id/ban | Ban user | ADMIN+ |
| POST | /api/admin/users/:id/recalculate-trust | Recalc trust | CURATOR+ |
| GET | /api/admin/verifications | Verification queue | CURATOR+ |
| PATCH | /api/admin/verifications/:id | Review verification | CURATOR+ |
| GET | /api/admin/reports | List reports | CURATOR+ |
| GET | /api/admin/reports/:id | Report detail | CURATOR+ |
| PATCH | /api/admin/reports/:id | Handle report | CURATOR+ |
| GET | /api/admin/transactions | All transactions | CURATOR+ |
| GET | /api/admin/payouts | Payout requests | CURATOR+ |
| PATCH | /api/admin/payouts/:id | Process payout | ADMIN+ |
| GET | /api/admin/analytics | Analytics data | CURATOR+ |
9.11 WebSocket Events
Connection: ws://api.zaptam.com with auth.token in handshake
Client → Server:
| Event | Payload | Description |
|---|---|---|
join:conversation | conversationId: string | Join conversation room |
leave:conversation | conversationId: string | Leave conversation room |
message:send | { conversationId, content, mediaUrl?, expiresIn? } | Send message |
message:read | conversationId: string | Mark messages as read |
typing:start | conversationId: string | Start typing indicator |
typing:stop | conversationId: string | Stop typing indicator |
presence:check | targetUserId: string | Check if user is online |
presence:bulk-check | userIds: string[] | Check multiple users |
screenshot:detected | { conversationId? } | Report screenshot taken |
Server → Client:
| Event | Payload | Description |
|---|---|---|
message:new | { conversationId, message } | New message received |
message:read | { conversationId, readBy } | Messages were read |
typing:start | { conversationId, userId } | User started typing |
typing:stop | { conversationId, userId } | User stopped typing |
user:online | { userId } | User came online |
user:offline | { userId } | User went offline |
notification:message | { conversationId, senderId, preview } | New message notification |
screenshot:alert | { conversationId, userId } | Screenshot detected |
10. Service Architecture
10.1 System Overview
┌─────────────────────────────────────────────────────────────────┐
│ CLIENTS │
├─────────────────┬─────────────────┬─────────────────────────────┤
│ zaptam-app │ zaptam-admin │ zaptam-landing │
│ (React SPA) │ (React SPA) │ (React SPA) │
│ Port: 5173 │ Port: 5174 │ Port: 5175 │
└────────┬────────┴────────┬────────┴─────────────────────────────┘
│ │
├─────────────────┼──────────────────────────────────────┐
│ │ │
▼ ▼ │
┌─────────────────────────────────────────────────────────────────┤
│ zaptam-api │
│ (Express + Socket.IO) │
│ Port: 3000 │
├─────────────────────────────────────────────────────────────────┤
│ Routes │ Services │ Sockets │
│ ├─ auth │ ├─ auth │ ├─ message.socket │
│ ├─ users │ ├─ user │ └─ presence.socket │
│ ├─ profiles │ ├─ match │ │
│ ├─ matches │ ├─ message │ Middleware │
│ ├─ messages │ ├─ wallet │ ├─ auth.middleware │
│ ├─ wallet │ ├─ verification│ ├─ role.middleware │
│ ├─ verification │ ├─ report │ ├─ validation.middleware │
│ ├─ reports │ ├─ trust │ ├─ rateLimit.middleware │
│ └─ admin/* │ └─ notification│ └─ error.middleware │
└────────┬────────────────┬────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────────┐
│ PostgreSQL │ │ Cloudflare R2 │ │ Notification Service │
│ (via Prisma) │ │ (Photo Storage) │ │ (External API) │
└─────────────────┘ └──────────────────┘ └─────────────────────────┘10.2 Service Modules
AuthService (auth.service.ts)
applyForAccount()- Handle new applicationssendPhoneOtp()- Send verification codesverifyOtp()- Validate OTP codescompleteRegistration()- Finalize account setuplogin()- Authenticate usersrefreshAccessToken()- Token rotationlogout()- Invalidate tokensresetPassword()- Password recovery
UserService (user.service.ts)
getUserById()- Fetch user profilegetUserSettings()- Fetch settingsupdateProfile()- Update user infoupdateSettings()- Update privacy settingschangePassword()- Password changedeleteAccount()- Soft deletepanicDelete()- Hard delete (all data)updateLastActive()- Track activity
MatchService (match.service.ts)
discoverProfiles()- Browse with filtersgetProfileById()- View detailed profileexpressInterest()- Send interestgetMatches()- List mutual matchesdeclineMatch()- Remove match
MessageService (message.service.ts)
getConversations()- List conversationsgetMessages()- Fetch messagessendMessage()- Send new messagedeleteConversation()- Remove conversationgetOrCreateConversation()- Ensure conversation exists
WalletService (wallet.service.ts)
getWalletBalance()- Calculate balancegetTransactionHistory()- List transactionspurchaseCredits()- Buy credits (men)purchaseMembership()- Subscribe to tierrequestWithdrawal()- Request payout (women)processWithdrawal()- Admin payout approvalgetMembershipTiers()- Get pricing
VerificationService (verification.service.ts)
getVerificationStatus()- Check current levelsubmitVerification()- Submit documentsreviewVerification()- Admin reviewgetPendingVerifications()- Admin queue
ReportService (report.service.ts)
createReport()- Submit reportcreateBlackmailReport()- High-priority reportgetReports()- Admin listgetReportById()- Report detailgetUserReports()- User's reports
TrustService (trust.service.ts)
calculateTrustScore()- Compute scoreupdateTrustScore()- Refresh scoreapplyTrustPenalty()- Deduct pointsreportScreenshotDetected()- Screenshot penalty
NotificationService (notification.service.ts)
sendOtpNotification()- Send OTP via WhatsApp/SMS
10.3 Middleware Pipeline
Request → RateLimit → Auth → Role → Validation → Controller → Response
↓ ↓ ↓ ↓
429 err 401 err 403 err 400 err11. Matching Algorithm
11.1 Discovery Ordering
Profiles are ranked by:
- Verification Level (descending): FULL > IDENTITY > NONE
- Trust Score (descending): Higher scores first
- Last Active (descending): Recently active first
11.2 Interest & Match Flow
User A ──[Express Interest]──→ User B
│
├── If B has NOT expressed interest in A:
│ └── Create Interest (A→B, status: PENDING)
│
└── If B has already expressed interest in A:
└── MUTUAL MATCH!
├── Update B→A Interest to ACCEPTED
├── Create A→B Interest as ACCEPTED
└── Create Conversation for A & B11.3 Photo Blur Logic
For non-matched users:
blurLevel = Math.max(photo.blurLevel, 80) // At least 80% blurFor matched users:
blurLevel = photo.blurLevel // User's preferred blur level12. Authentication System
12.1 Token Architecture
| Token Type | Expiry | Storage | Use |
|---|---|---|---|
| Access Token | 15 minutes | Memory | API requests |
| Refresh Token | 7 days | Database + Client | Get new access token |
| OTP Code | 10 minutes | Database | Phone verification |
12.2 JWT Payload
{
userId: string,
role: UserRole,
iat: number,
exp: number
}12.3 Token Flow
1. User logs in
2. Server generates access + refresh tokens
3. Access token sent in Authorization header
4. On 401, client sends refresh token
5. Server validates refresh token, issues new pair
6. Old refresh token invalidated (rotation)12.4 OTP Flow
- Request OTP →
sendPhoneOtp() - External notification service sends code via WhatsApp/SMS
- User enters code
verifyOtp()validates and marks code as used- OTP expires after 10 minutes or single use
13. Billing & Premium Features
13.1 Membership Tiers (Men)
| Tier | Price | Features |
|---|---|---|
| Standard | $49/month | Worth verification, browse profiles, unlimited interest, messaging, basic privacy |
| Premium | $149/month | + Worth badge, priority discovery, see who viewed, advanced privacy, read receipts |
| Elite | $499/month | + Top placement, personal curator, exclusive events, monthly boost, 24/7 concierge |
13.2 Women's Access
- Price: Free
- Requirement: Identity verification + acceptance review
- Benefits: Full platform access, earnings from engagement, priority support
13.3 Transaction Types
| Type | Direction | User Type |
|---|---|---|
MEMBERSHIP | Out | Men |
CREDIT_PURCHASE | In (wallet credit) | Men |
EARNING | In | Women |
WITHDRAWAL | Out | Women |
BOOST | Out | All |
13.4 Withdrawal Process
- Women request withdrawal (min $10)
- Transaction created with status PENDING
- Admin reviews in payout queue
- Admin approves → status COMPLETED, funds released
- Admin rejects → status FAILED, balance restored
14. Content Moderation & Trust System
14.1 Trust Score Algorithm
Base Score: 50 (starting value) Range: 0-100
Positive Factors:
| Factor | Points | Max |
|---|---|---|
| Verification Level (IDENTITY) | +10 | 10 |
| Verification Level (FULL) | +20 | 20 |
| Account Age | +1/month | 10 |
| Matches (Interactions) | +1 per 2 matches | 10 |
Negative Factors:
| Factor | Points |
|---|---|
| Valid Report Against User | -5 each |
| Screenshot Detected | -10 each |
14.2 Report Types & Handling
| Type | Priority | Auto-Action |
|---|---|---|
BLACKMAIL | CRITICAL | Immediate -20 trust, auto-investigate |
HARASSMENT | HIGH | Review within 24h |
FAKE_PROFILE | MEDIUM | Review within 48h |
INAPPROPRIATE_CONTENT | MEDIUM | Review within 48h |
OTHER | LOW | Review within 72h |
14.3 Report Status Flow
PENDING → INVESTIGATING → RESOLVED
→ DISMISSED14.4 Screenshot Detection
- Client detects screenshot attempt
- Sends
screenshot:detectedsocket event - Server applies -10 trust penalty
- Server sends
screenshot:alertto conversation partner - Logged for review
14.5 Panic Delete
Permanently removes ALL user data:
- Messages (sent and received)
- Conversations
- Interests (sent and received)
- Photos
- Verifications
- Wallet transactions
- Reports (filed and against)
- Tokens
- Settings
- User record
15. Technical Stack
15.1 Backend (zaptam-api)
| Category | Technology |
|---|---|
| Runtime | Node.js |
| Framework | Express.js 4.18 |
| Language | TypeScript 5.3 |
| ORM | Prisma 5.9 |
| Database | PostgreSQL |
| Real-time | Socket.IO 4.7 |
| Auth | JWT (jsonwebtoken 9.0) |
| Validation | Joi 17.12 |
| File Storage | Cloudflare R2 (S3-compatible) |
| Password Hashing | bcryptjs |
| Rate Limiting | express-rate-limit |
| Security | Helmet |
15.2 Frontend Apps (zaptam-app, zaptam-admin)
| Category | Technology |
|---|---|
| Framework | React 18 |
| Language | TypeScript 5.3 |
| Build Tool | Vite 5.0 |
| Router | React Router 6.22 |
| State Management | Zustand 4.5 |
| Data Fetching | TanStack Query 5.17 |
| HTTP Client | Axios 1.6 |
| Real-time | Socket.IO Client 4.7 |
| UI Components | Radix UI |
| Styling | Tailwind CSS 3.4 |
| Animation | Framer Motion 11 |
| Forms | React Hook Form 7.50 |
| Charts (Admin) | Recharts 2.15 |
15.3 Landing Page (zaptam-landing)
| Category | Technology |
|---|---|
| Framework | React 18 |
| Language | TypeScript 5.3 |
| Build Tool | Vite 5.0 |
| Router | React Router 6.22 |
| Styling | Tailwind CSS 3.4 |
| Animation | Framer Motion 11 |
15.4 External Services
| Service | Purpose |
|---|---|
| Cloudflare R2 | Photo storage |
| Notification Service (Eneza) | WhatsApp/SMS OTP delivery |
| PostgreSQL | Primary database |
16. Gaps & Missing Features
16.1 Not Yet Implemented
| Feature | Priority | Description |
|---|---|---|
| Payment Gateway Integration | HIGH | Stripe/PayPal for actual payments (currently mock) |
| Push Notifications | HIGH | FCM/APNs for mobile notifications |
| Email Notifications | MEDIUM | Transactional emails (welcome, matches, etc.) |
| Photo Moderation | HIGH | AI-based nudity/inappropriate content detection |
| ID Verification Integration | HIGH | Jumio/Onfido for automated ID verification |
| Worth Verification | HIGH | Plaid/bank verification for financial capacity |
| Video Calls | MEDIUM | In-app video calling for matches |
| Voice Messages | LOW | Audio message support |
| Profile Boost | MEDIUM | Paid boost functionality |
| Exclusive Events | LOW | Elite tier event management |
| Personal Curator | LOW | Human matching assistance for Elite |
| Crypto Payments | LOW | Bitcoin/crypto payment option |
| 2FA | MEDIUM | Two-factor authentication option |
| App Store Deployment | HIGH | iOS/Android native apps (currently web only) |
16.2 Technical Debt
| Issue | Impact | Suggested Fix |
|---|---|---|
| No automated tests | HIGH | Add Jest/Vitest test suites |
| No CI/CD pipeline | MEDIUM | Setup GitHub Actions |
| No logging infrastructure | MEDIUM | Add structured logging (Pino/Winston) |
| No monitoring | MEDIUM | Add APM (DataDog/NewRelic) |
| Hardcoded notification URL | LOW | Move to environment config |
| No database migrations | MEDIUM | Use Prisma migrate instead of db push |
| No API versioning | LOW | Add /api/v1/ prefix |
| No request tracing | LOW | Add correlation IDs |
| Socket.IO not scalable | MEDIUM | Add Redis adapter for multi-instance |
16.3 Security Improvements Needed
| Issue | Priority | Recommendation |
|---|---|---|
| Rate limit bypass | HIGH | Add Redis-backed rate limiting |
| No brute-force protection | HIGH | Add account lockout after failed attempts |
| JWT in memory only | MEDIUM | Consider HttpOnly cookies |
| No audit logging | MEDIUM | Log all admin actions |
| Screenshot detection is client-side | LOW | Inform users this is deterrent only |
| Panic delete is irreversible | INFO | Add confirmation flow |
16.4 UX Improvements
| Feature | Priority | Description |
|---|---|---|
| Profile completion progress | MEDIUM | Show % complete |
| Onboarding tutorial | MEDIUM | Guide new users |
| Dark/Light mode toggle | LOW | Theme switching |
| Language localization | MEDIUM | Multi-language support |
| Accessibility (a11y) | MEDIUM | WCAG compliance |
| Offline support | LOW | PWA with service worker |
| Image compression | MEDIUM | Client-side compression before upload |
Appendix A: Directory Structure
zaptam-api/
├── prisma/
│ ├── schema.prisma # Database schema
│ └── seed.ts # Database seeding
├── src/
│ ├── config/ # Configuration
│ │ ├── database.ts # Prisma client
│ │ ├── jwt.ts # JWT config
│ │ ├── multer.ts # File upload config
│ │ ├── r2.ts # Cloudflare R2 config
│ │ └── socket.ts # Socket.IO config
│ ├── controllers/ # Route handlers
│ │ ├── admin/ # Admin controllers
│ │ ├── auth.controller.ts
│ │ ├── match.controller.ts
│ │ ├── message.controller.ts
│ │ ├── profile.controller.ts
│ │ ├── report.controller.ts
│ │ ├── user.controller.ts
│ │ ├── verification.controller.ts
│ │ └── wallet.controller.ts
│ ├── middleware/ # Express middleware
│ │ ├── auth.middleware.ts
│ │ ├── error.middleware.ts
│ │ ├── rateLimit.middleware.ts
│ │ ├── role.middleware.ts
│ │ └── validation.middleware.ts
│ ├── routes/ # Route definitions
│ │ ├── admin/
│ │ ├── auth.routes.ts
│ │ ├── match.routes.ts
│ │ ├── message.routes.ts
│ │ ├── profile.routes.ts
│ │ ├── report.routes.ts
│ │ ├── user.routes.ts
│ │ ├── verification.routes.ts
│ │ ├── wallet.routes.ts
│ │ └── index.ts
│ ├── services/ # Business logic
│ │ ├── auth.service.ts
│ │ ├── match.service.ts
│ │ ├── message.service.ts
│ │ ├── notification.service.ts
│ │ ├── report.service.ts
│ │ ├── trust.service.ts
│ │ ├── user.service.ts
│ │ ├── verification.service.ts
│ │ └── wallet.service.ts
│ ├── sockets/ # WebSocket handlers
│ │ ├── index.ts
│ │ ├── message.socket.ts
│ │ └── presence.socket.ts
│ ├── types/ # TypeScript types
│ │ └── index.ts
│ ├── utils/ # Utility functions
│ │ ├── crypto.utils.ts
│ │ ├── helpers.ts
│ │ ├── jwt.utils.ts
│ │ └── r2.utils.ts
│ ├── validators/ # Joi schemas
│ │ ├── auth.validator.ts
│ │ ├── message.validator.ts
│ │ └── profile.validator.ts
│ ├── app.ts # Express app setup
│ └── server.ts # Entry point
└── package.json
zaptam-app/
├── src/
│ ├── api/ # API client modules
│ │ ├── auth.ts
│ │ ├── client.ts
│ │ ├── matches.ts
│ │ ├── messages.ts
│ │ ├── users.ts
│ │ ├── verification.ts
│ │ └── wallet.ts
│ ├── components/ # React components
│ │ ├── auth/
│ │ ├── layout/
│ │ ├── match/
│ │ ├── message/
│ │ ├── profile/
│ │ ├── ui/
│ │ ├── wallet/
│ │ └── AppLayout.tsx
│ ├── hooks/ # Custom hooks
│ │ └── useAuth.ts
│ ├── lib/ # Utilities
│ │ ├── constants.ts
│ │ ├── socket.ts
│ │ └── utils.ts
│ ├── pages/ # Page components
│ │ ├── auth/
│ │ ├── Conversation.tsx
│ │ ├── Discover.tsx
│ │ ├── Matches.tsx
│ │ ├── Messages.tsx
│ │ ├── Profile.tsx
│ │ ├── Settings.tsx
│ │ └── Wallet.tsx
│ ├── services/ # Service layer
│ │ └── api.ts
│ ├── store/ # Zustand stores
│ │ ├── auth.ts
│ │ └── socketStore.ts
│ ├── types/ # TypeScript types
│ │ └── index.ts
│ ├── App.tsx # Root component
│ └── main.tsx # Entry point
└── package.json
zaptam-admin/
├── src/
│ ├── components/
│ │ ├── dashboard/
│ │ ├── reports/
│ │ ├── ui/
│ │ ├── users/
│ │ ├── verification/
│ │ └── AdminLayout.tsx
│ ├── hooks/
│ ├── pages/
│ │ ├── Dashboard.tsx
│ │ ├── Login.tsx
│ │ ├── Reports.tsx
│ │ ├── Transactions.tsx
│ │ ├── Users.tsx
│ │ └── Verifications.tsx
│ ├── services/
│ │ └── api.ts
│ ├── store/
│ │ └── auth.ts
│ ├── types/
│ │ └── index.ts
│ ├── App.tsx
│ └── main.tsx
└── package.json
zaptam-landing/
├── src/
│ ├── components/
│ │ ├── layout/
│ │ ├── sections/
│ │ └── ui/
│ ├── hooks/
│ ├── pages/
│ │ ├── About.tsx
│ │ ├── Apply.tsx
│ │ ├── Contact.tsx
│ │ ├── Home.tsx
│ │ ├── HowItWorks.tsx
│ │ ├── Membership.tsx
│ │ ├── Privacy.tsx
│ │ └── Terms.tsx
│ ├── App.tsx
│ └── main.tsx
└── package.jsonAppendix B: Environment Variables
zaptam-api
# Database
DATABASE_URL=postgresql://user:pass@host:5432/zaptam
# JWT
JWT_SECRET=your-secret-key
JWT_ACCESS_EXPIRY=15m
JWT_REFRESH_EXPIRY=7d
# Cloudflare R2
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_BUCKET_NAME=zaptam-photos
R2_PUBLIC_URL=https://r2.zaptam.com
# Notification Service
NOTIFICATION_SERVICE_URL=https://notifications.eneza.app
NOTIFICATION_SERVICE_API_KEY=your-api-key
DEFAULT_NOTIFICATION_CHANNEL=whatsapp
# Server
PORT=3000
NODE_ENV=production
CORS_ORIGIN=https://app.zaptam.comzaptam-app / zaptam-admin
VITE_API_URL=https://api.zaptam.com
VITE_WS_URL=wss://api.zaptam.comDocument generated from codebase analysis. Last updated: March 2026.