System Architecture
Millenium Potters is built as a modern, scalable microfinance management platform using a client-server architecture with separate frontend and backend services.
High-Level Architecture
┌─────────────────────────────────────────────────────────────┐
│ Client Layer │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Next.js 14 Frontend Application │ │
│ │ (React 19, Tailwind CSS, Aceternity UI) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↕ HTTP/REST API
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Node.js/Express Backend Server │ │
│ │ (Prisma ORM, JWT Auth, Express Middleware) │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────────────────┐
│ Data Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ CockroachDB │ │ Supabase │ │ Cloudinary │ │
│ │ (Production)│ │ (Auth) │ │ (Storage) │ │
│ │ PostgreSQL │ │ │ │ │ │
│ │ (Local) │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
Technology Stack
Frontend
Backend
Database
External Services
Frontend Technologies The client application is built with Next.js 14 and modern React patterns: Technology Version Purpose Next.js 16.0.10 React framework with App Router React 19.1.0 UI library TypeScript 5.x Type safety Tailwind CSS 4.x Utility-first styling Radix UI Various Accessible component primitives Framer Motion 12.25.0 Animation library Axios 1.11.0 HTTP client Shepherd.js 14.5.1 Interactive user tours Recharts 3.1.2 Data visualization date-fns 4.1.0 Date manipulation Sonner 2.0.7 Toast notifications
See: ~/workspace/source/frontend/package.json:11-66 UI Component Libraries
Aceternity UI Beautiful animated components for modern interfaces
Radix UI Unstyled, accessible primitives for alerts, dialogs, dropdowns, etc.
Lucide Icons Consistent icon library with 500+ icons
Key Features
Server-Side Rendering (SSR) : Fast initial page loads with Next.js App Router
TypeScript : Full type safety across the application
Responsive Design : Mobile-first design with Tailwind breakpoints
Real-time Updates : Automatic data refresh on mutations
Error Monitoring : Sentry integration for production error tracking
Interactive Tours : Shepherd.js guides for onboarding
See: ~/workspace/source/frontend/package.json:27 (Sentry) Backend Technologies The API server is built with Node.js and Express: Technology Version Purpose Node.js 18+ Runtime environment Express 4.18.2 Web framework Prisma 5.22.0 ORM and database toolkit TypeScript 5.3.3 Type safety bcryptjs 3.0.2 Password hashing jsonwebtoken 9.0.2 JWT authentication Supabase JS 2.94.0 Auth integration Cloudinary 2.8.0 File storage Nodemailer 7.0.6 Email sending Zod 3.22.4 Schema validation Helmet 8.1.0 Security headers
See: ~/workspace/source/backend/package.json:28-52 API Architecture RESTful API with structured endpoints: /api/
├── auth/ # Authentication endpoints
│ ├── login
│ ├── logout
│ ├── refresh
│ └── password-reset
├── users/ # User management
├── unions/ # Union CRUD
├── union-members/ # Member management
├── loans/ # Loan operations
├── repayments/ # Payment recording
├── schedules/ # Repayment schedules
├── reports/ # Analytics and reports
└── documents/ # File uploads
Security Features
Authentication & Authorization
JWT Tokens : Secure token-based authentication
Role-Based Access Control (RBAC) : Three-tier permission system
Session Management : Track and revoke active sessions
Password Hashing : bcrypt with salt rounds
Supabase Integration : OAuth providers and magic links
Helmet.js : HTTP security headers (XSS, CSP, etc.)
CORS : Configured cross-origin resource sharing
Rate Limiting : Prevent brute force attacks
Input Validation : Zod schema validation on all inputs
SQL Injection Prevention : Prisma parameterized queries
Audit Logs : Track all critical actions with before/after snapshots
Login History : Monitor authentication attempts
User Activity : Track last login and activity timestamps
Session Tracking : JWT ID and IP address logging
See: ~/workspace/source/backend/prisma/schema.prisma:506-545 Database Schema Millenium Potters uses a relational database with a comprehensive schema: Core Entities
Users
User accounts with role-based permissions: model User {
id String @id @default ( cuid ())
email String @unique
passwordHash String
role Role // ADMIN, SUPERVISOR, CREDIT_OFFICER
isActive Boolean @default ( true )
firstName String ?
lastName String ?
phone String ?
supervisorId String ? // Links officers to supervisors
supervisor User ? @relation ( "SupervisorToOfficers" )
unions Union [] // Credit Officer manages unions
// ... relationships
}
See: ~/workspace/source/backend/prisma/schema.prisma:85-153
Unions
Organizational units for grouping members: model Union {
id String @id @default ( cuid ())
name String
location String ?
address String ?
creditOfficerId String
creditOfficer User @relation ( fields : [ creditOfficerId ] )
unionMembers UnionMember []
loans Loan []
}
Each union is managed by one Credit Officer and contains multiple members. See: ~/workspace/source/backend/prisma/schema.prisma:61-83
Union Members
Individual members who receive loans: model UnionMember {
id String @id @default ( cuid ())
code String ? @unique
firstName String
lastName String
phone String ?
email String ?
address String ?
dateOfBirth DateTime ?
isVerified Boolean @default ( true )
unionId String
union Union @relation ( fields : [ unionId ] )
documents UnionMemberDocument []
loans Loan []
}
See: ~/workspace/source/backend/prisma/schema.prisma:156-197
Loans
Loan applications and tracking: model Loan {
id String @id @default ( cuid ())
loanNumber String @unique
unionMemberId String
unionId String
loanTypeId String ?
principalAmount Decimal @db.Decimal ( 14 , 2 )
termCount Int
termUnit TermUnit // DAY, WEEK, MONTH
status LoanStatus @default ( DRAFT )
// DRAFT, PENDING_APPROVAL, APPROVED, ACTIVE, COMPLETED, etc.
createdByUserId String
assignedOfficerId String ?
scheduleItems RepaymentScheduleItem []
repayments Repayment []
}
See: ~/workspace/source/backend/prisma/schema.prisma:225-280
Repayments
Payment tracking and allocation: model Repayment {
id String @id @default ( cuid ())
loanId String
receivedByUserId String
amount Decimal @db.Decimal ( 14 , 2 )
paidAt DateTime
method RepaymentMethod // CASH, TRANSFER, POS, etc.
reference String ?
allocations RepaymentAllocation []
}
model RepaymentScheduleItem {
id String @id @default ( cuid ())
loanId String
sequence Int
dueDate DateTime
principalDue Decimal @db.Decimal ( 14 , 2 )
interestDue Decimal @db.Decimal ( 14 , 2 )
totalDue Decimal @db.Decimal ( 14 , 2 )
paidAmount Decimal @db.Decimal ( 14 , 2 )
status ScheduleStatus // PENDING, PAID, PARTIAL, OVERDUE
}
See: ~/workspace/source/backend/prisma/schema.prisma:282-350 Database Providers
PostgreSQL 18 Local Development
Fast local setup
Full SQL compatibility
Prisma migrations support
CockroachDB Production
Distributed SQL database
Automatic hourly backups (30-day retention)
Point-in-Time Recovery (PITR)
Serverless scaling
Online schema migrations
datasource db {
provider = "cockroachdb"
url = env ( "DATABASE_URL" )
directUrl = env ( "DIRECT_URL" )
// Connection pooling: ~20-30 connections for 50-100 users
}
See: ~/workspace/source/backend/prisma/schema.prisma:8-15 Strategic indexes for query optimization: // User indexes
@@index ( [ email ] )
@@index ( [ role ] )
@@index ( [ isActive ] )
// Loan indexes
@@index ( [ status ] )
@@index ( [ loanNumber ] )
@@index ( [ unionMemberId ] )
@@index ( [ unionId ] )
// Repayment indexes
@@index ( [ loanId , paidAt ] )
@@index ( [ receivedByUserId ] )
Third-Party Integrations
Purpose : User authentication and OAuthFeatures:
Email/password authentication
OAuth providers (Google, GitHub, etc.)
Magic link authentication
JWT token generation
Password reset flows
Integration: import { createClient } from '@supabase/supabase-js'
const supabase = createClient (
process . env . SUPABASE_URL ,
process . env . SUPABASE_ANON_KEY
)
See: ~/workspace/source/backend/package.json:30 and ~/workspace/source/frontend/package.json:28
Purpose : Document and image storageFeatures:
Secure file uploads
Image optimization and transformation
CDN delivery
Backup storage for database exports
File Types:
Member identity documents
Loan documents
Profile images
Database backup files
Integration: import cloudinary from 'cloudinary'
cloudinary . v2 . config ({
cloud_name: process . env . CLOUDINARY_CLOUD_NAME ,
api_key: process . env . CLOUDINARY_API_KEY ,
api_secret: process . env . CLOUDINARY_API_SECRET
})
See: ~/workspace/source/backend/package.json:38
Purpose : Transactional emailsUse Cases:
Password reset emails
Loan status notifications
Welcome emails
Payment confirmations
Configuration:
Configurable SMTP settings in admin panel
Email templates with variable substitution
Template management in database
Integration: import nodemailer from 'nodemailer'
const transporter = nodemailer . createTransport ({
host: process . env . SMTP_HOST ,
port: process . env . SMTP_PORT ,
auth: {
user: process . env . SMTP_USER ,
pass: process . env . SMTP_PASS
}
})
See: ~/workspace/source/backend/package.json:46 and ~/workspace/source/backend/prisma/schema.prisma:371-384
Purpose : Production error monitoringFeatures:
Real-time error tracking
Stack trace analysis
Performance monitoring
Release tracking
Integration:
Frontend: Next.js integration
Backend: Express middleware
Source maps for debugging
See: ~/workspace/source/frontend/package.json:27
Authentication Flow
Session Management
Login : User credentials verified via Supabase, JWT generated with user ID and role
Token Storage : JWT stored in HTTP-only cookie (production) or localStorage (development)
Request Authorization : Frontend includes JWT in Authorization header for API requests
Token Validation : Backend middleware verifies JWT signature and expiry
Role Check : Endpoint permissions checked against user role
Session Tracking : Active sessions tracked in database with JWT ID
Logout : Session revoked in database, token blacklisted
See: ~/workspace/source/backend/prisma/schema.prisma:506-522
Data Flow Examples
Creating a Loan
Credit Officer creates draft
POST / api / loans
{
unionMemberId : "..." ,
principalAmount : 50000 ,
termCount : 12 ,
termUnit : "MONTH"
}
Backend:
Validates user has CREDIT_OFFICER role
Checks member belongs to officer’s union
Creates loan with status DRAFT
Generates unique loan number
Officer submits for approval
PATCH / api / loans / : id / submit
Backend:
Updates status to PENDING_APPROVAL
Notifies supervisor via email
Creates audit log entry
Supervisor reviews and approves
PATCH / api / loans / : id / approve
{
notes : "Approved after document review"
}
Backend:
Validates user has SUPERVISOR or ADMIN role
Updates status to APPROVED
Creates audit log entry
Notifies credit officer
Loan disbursement
POST / api / loans / : id / disburse
{
disbursedAt : "2026-03-11" ,
method : "TRANSFER" ,
reference : "TXN123456"
}
Backend:
Updates status to ACTIVE
Generates repayment schedule
Creates schedule items in database
Calculates due dates based on term unit
Recording a Repayment
Credit officer records payment
POST / api / repayments
{
loanId : "..." ,
amount : 5000 ,
paidAt : "2026-03-11" ,
method : "CASH"
}
Backend allocates payment
Find oldest unpaid/partial schedule item
Apply to interest first, then principal
Update schedule item status (PAID, PARTIAL, or PENDING)
Create RepaymentAllocation records
Update loan status if fully paid
Frontend updates UI
Refresh repayment schedule
Update payment history
Recalculate outstanding balance
Show success notification
Backup & Recovery
Automated Backups
CockroachDB Managed
Hourly automatic backups
30-day retention period
Point-in-time recovery
Managed by CockroachDB service
Application-Level
Manual or scheduled exports
JSON/CSV format exports
Cloudinary storage
Configurable frequency and retention
Backup Schedule Settings
model BackupScheduleSettings {
id String @id @default ( "default" )
frequency String @default ( "disabled" ) // daily, weekly, monthly
location String @default ( "cloud" ) // local, cloud, both
retentionDays Int @default ( 30 )
includeAuditLogs Boolean @default ( false )
lastBackupAt DateTime ?
nextBackupAt DateTime ?
}
See: ~/workspace/source/backend/prisma/schema.prisma:661-673
Deployment Architecture
Production Deployment
┌─────────────────────────────────────────────┐
│ Vercel Edge Network │
│ ┌────────────────────────────────────┐ │
│ │ Next.js Frontend (SSR/SSG) │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────┐
│ Backend API Server │
│ (Render/Railway/AWS/DigitalOcean) │
└─────────────────────────────────────────────┘
↕ ↕ ↕
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ CockroachDB │ │ Supabase │ │ Cloudinary │
│ Serverless │ │ (Auth) │ │ (Storage) │
└──────────────┘ └──────────────┘ └──────────────┘
Environment Configuration
NODE_ENV=development
DATABASE_URL=postgresql://localhost:5432/millenium_local
NEXT_PUBLIC_API_URL=http://localhost:5000/api
NODE_ENV=production
DATABASE_URL=cockroachdb://...
NEXT_PUBLIC_API_URL=https://api.millenium.com/api
Maintenance Mode
Safe deployment with user lockout:
model CompanySetting {
maintenanceMode Boolean @default ( false )
// ... other settings
}
When enabled:
All API requests return 503 Service Unavailable
Frontend shows maintenance page
Admin users can still access the system
Scheduled for deployments and database migrations
See: ~/workspace/source/backend/prisma/schema.prisma:352-369
Database Optimization
Connection Pooling : 20-30 connections for 50-100 concurrent users
Strategic Indexes : All foreign keys and frequently queried fields
Pagination : Limit query results to prevent memory issues
Soft Deletes : Use deletedAt field instead of hard deletes
Frontend Optimization
Server-Side Rendering : Fast initial page loads
Code Splitting : Automatic with Next.js
Image Optimization : Next.js Image component
Static Generation : Pre-render pages when possible
API Response Caching : React Query for client-side caching
API Optimization
Rate Limiting : Prevent abuse with express-rate-limit
Response Compression : Gzip/Brotli compression
Query Optimization : Prisma select for specific fields only
Batch Operations : Reduce database round trips
See: ~/workspace/source/backend/package.json:42 (rate limiting)
Scalability
Horizontal Scaling
Stateless Backend : Multiple API server instances
Load Balancing : Distribute requests across servers
Database : CockroachDB scales horizontally
CDN : Cloudinary for global file delivery
Vertical Scaling
Database : Increase CockroachDB resources as needed
Server : Scale up API server memory/CPU
Connection Pool : Adjust based on concurrent users
The current architecture supports 50-100 concurrent users. For larger deployments, consider implementing Redis caching, message queues, and horizontal API scaling.
Security Best Practices
Authentication
JWT tokens with expiration
HTTP-only cookies in production
Session tracking and revocation
Password reset with time-limited tokens
Authorization
Role-based access control (RBAC)
Endpoint-level permission checks
Resource ownership validation
Supervisor-officer hierarchy enforcement
Data Protection
Password hashing with bcrypt
Sensitive data encryption at rest
HTTPS enforced in production
Regular automated backups
Monitoring
Audit logs for all critical actions
Login history tracking
Error monitoring with Sentry
Session activity monitoring
What’s Next?
API Reference Explore detailed API endpoint documentation
User Guide Learn how to use all platform features
Deployment Guide Deploy to production with best practices
Development Contribute to the codebase