Skip to main content

System Architecture

Detailed technical architecture of the NS Internship Portal.

High-Level Architecture

Technology Stack

LayerTechnologyVersionPurpose
FrontendNext.js14.xApp Router, server-side rendering
UI FrameworkReact18.xComponent library
LanguageTypeScript5.xType safety
StylingTailwind CSS3.xUtility-first CSS
DatabaseSupabasePostgreSQLCore data storage
AuthJWTjose 6.2.1Token-based authentication
PaymentRazorpay2.9.2Payment processing
EmailResend SMTPNodemailerTransactional emails
File StorageCloudinary-Video, PDF, documents
PDFPDFKit0.14.0Certificate/invoice generation
VideoJitsi MeetJAASWebinar platform
TestingPlaywright1.xE2E testing
DeploymentVercel-Hosting + serverless

Authentication System

JWT Refresh Token Flow

Token Storage

  • auth-token cookie: HttpOnly, SameSite=Strict, 15min expiry
  • refresh-token cookie: HttpOnly, SameSite=Strict, 30 days expiry
  • Storage: Refresh token stored as SHA-256 hash in refresh_tokens table
  • Rotation: New refresh token issued on each use

Google OAuth Flow

Milestone System

Sequential Logic

Only reviewed (approved) unlocks the next milestone.

Status Enforcement (3 layers)

  1. Client-side: lib/milestoneHelpers.tscanSubmitMilestone()
  2. Server-side API: lib/enrollmentStatus.tscanSubmitMilestone()
  3. Database: lib/milestones.tssubmitMilestone()

Milestone Structure

DurationWeeklyMajorTotal
1 Month314
2 Months628
3 Months9312

Progress Calculation: progress = (reviewed_count / total_count) × 100

Email System

Architecture

Email Templates (14 total)

TemplateTypeTrigger
EnrollmentenrollmentPayment verified
CertificatecertificateAdmin approves submission
SubmissionsubmissionStudent submits final project
Password Resetpassword_resetForgot password
Milestone Reviewedmilestone_reviewedAdmin approves/rejects
AnnouncementannouncementAdmin creates with email=true
Deadline Reminderdeadline_reminder24h before milestone due
Offer Letteroffer_letterPayment verified
Job Alertjob_alertWeekly domain-matched jobs
WelcomewelcomeLead converted to user
Inactive Studentinactive_student7+ days inactive
Newsletter Welcomenewsletter_welcomeNewsletter signup
Webinar Confirmationwebinar_confirmationWebinar registration
Submission ConfirmationsubmissionFinal project submission

Email Queue System

  • Storage: email_queue table with status: pending → processing → sent/failed
  • Scheduling: /api/cron/process-emails runs daily at 6am UTC
  • Retry: Automatic retry on failure (max 3 attempts)
  • Tracking: 1×1 pixel at GET /api/email/track?id=<queueId>
  • Admin: View queue, cancel pending, retry failed

Analytics System

Event Tracking

Event Types

Event TypeTrigger
loginUser logs in (also updates last_login)
signupNew user registers
enrollmentStudent enrolls in a domain
milestone_submitStudent submits a milestone
certificate_issuedCertificate is issued
page_visitAnonymous page visit

In-Memory Cache

A singleton MemoryCache class with TTL support:

  • cache.get(key) — returns null if expired
  • cache.set(key, data, ttl) — TTL in milliseconds (default 60s)
  • withCache(key, fn, ttl) — async wrapper for cache-aside pattern
  • Auto-cleanup of expired entries every 5 minutes

Project Structure

ns-internship-portal/
├── app/
│ ├── admin/ # Admin dashboard + jobs page
│ ├── api/
│ │ ├── admin/ # 25+ admin endpoints
│ │ ├── auth/ # Auth: login, register, refresh, logout, google
│ │ ├── enrollments/ # Create, verify-payment, submit, cancel
│ │ ├── milestones/[id]/submit/ # Submit or resubmit
│ │ ├── cron/ # 4 scheduled cron jobs
│ │ └── ... # 57+ total endpoints
│ ├── dashboard/ # Student dashboard (SPA)
│ ├── certificate/[id]/ # Public shareable certificate page
│ └── ... # Public pages
├── components/
│ ├── admin/ # 19 admin tab/panel components
│ ├── chatbot/ # Lead capture chatbot components
│ ├── newsletter/ # NewsletterSignup component
│ └── dashboard/ # Student dashboard components
├── hooks/
│ ├── useAnnouncements.ts # Announcement state management
│ ├── usePermissions.ts # Client-side permission checks
│ └── useToast.ts # Toast notification state
├── lib/
│ ├── auth.ts # JWT token generation
│ ├── authClient.ts # Client-side auth helpers
│ ├── email.ts # 12 email templates
│ ├── emailQueue.ts # Email queue management
│ ├── milestones.ts # Milestone logic
│ ├── analytics.ts # Event tracking
│ └── ... # 25+ utility modules
├── middleware.ts # Edge auth + silent refresh + maintenance mode
├── supabase/migrations/ # 20+ SQL migration files
└── vercel.json # Cron: 4 jobs

Security Controls

ControlImplementation
Password hashingbcrypt, 10 rounds
Access tokensJWT via jose, 15min expiry
Refresh tokensSHA-256 hashed, DB-stored, rotated on use, revoked on logout
Cookie securityHttpOnly, SameSite=Strict, Secure in production
Rate limitingSupabase-backed (survives restarts)
Input validationAll endpoints, sanitization applied
File upload securityType + size validation via lib/fileValidation.ts
SQL injectionParameterized queries via Supabase
IDOR preventionOwnership checks on milestones/enrollments
Permission checks28 granular permissions, role hierarchy
Razorpay verificationHMAC-SHA256 signature
Cron protectionCRON_SECRET header required
Certificate expiry410 Gone at /api/certificates/verify/[id]
Admin audit trailIP + user agent, 28 action types
Disposable email block16+ domains blocked on register + Google OAuth
Google OAuthState parameter, code exchange, profile fetch

Deployment Architecture

Vercel Cron Jobs

CronSchedulePurpose
/api/cron/process-emailsDaily 6am UTCProcess email queue
/api/cron/inactive-studentsDaily 9am UTCRe-engagement emails
/api/cron/deadline-remindersDaily 8am UTC24h milestone reminders
/api/cron/job-alertsMonday 9am UTCWeekly job digest

Data Flow Diagrams

Enrollment Flow

API Request Flow

Scaling Considerations

Database Scaling

  • Supabase provides automatic scaling
  • Add read replicas for high traffic
  • Use connection pooling
  • Optimize queries with indexes

Caching Strategy

  • In-memory: Analytics queries (60s TTL)
  • CDN: Static assets (Next.js automatic)
  • Browser: SWR for data fetching

Horizontal Scaling

  • Next.js API routes scale automatically on Vercel
  • Database connections use connection pooling
  • Email queue handles bursts

Performance Optimization

  • Code splitting with Next.js
  • Image optimization with next/image
  • Lazy loading for routes
  • Debounced API calls
  • Pagination for large datasets

Monitoring and Observability

MetricToolPurpose
Error trackingSentry (optional)Exception monitoring
PerformanceVercel Speed InsightsCore Web Vitals
DatabaseSupabase DashboardQuery performance
EmailResend DashboardEmail delivery metrics
AnalyticsCustomEvent tracking