NS Exam Portal
A production-grade multi-tenant online examination platform for educational institutions and corporate assessment providers. Built on a decoupled React + Express + Turso (libSQL) stack, deployed on Cloudflare Pages and GCP Cloud Run.
Developed and maintained by NS Software Solutions
Table of Contents
- Quick Start
- Tech Stack
- Features
- Project Structure
- Environment Variables
- Deployment
- Development Guidelines
- Known Limitations
- Support
Quick Start
Prerequisites
- Node.js 18+ and npm
- Firebase project with Firebase Admin service account credentials
- Turso database instance and auth token
- Git
Installation
1. Clone the repository:
git clone <YOUR_GIT_URL>
cd exam-portal-ns
2. Configure the backend:
cd backend
cp .env.example .env
# Edit backend/.env — add Turso URL/token and Firebase service account credentials
npm install
3. Configure the frontend:
cd ../frontend
cp .env.example .env
# Edit frontend/.env — add Firebase public config and VITE_API_URL
npm install
4. Start development servers:
Backend (port 8082 by default):
cd backend
npm run dev
Frontend (Vite dev server):
cd frontend
npm run dev
Tech Stack
| Layer | Technology | Notes |
|---|---|---|
| Frontend | React 18, TypeScript, Vite | Single Page Application with code splitting |
| UI | shadcn/ui (Radix UI + Tailwind CSS) | Dark/light theme support, accessible components |
| Routing | React Router v6 | Role-based layout structures with protected routes |
| Auth (client) | Firebase Authentication | Anonymous (guest) + email/password + token refresh |
| Backend | Node.js 22, Express, TypeScript | REST API + RPC endpoints, ESM modules |
| Database | Turso (libSQL / SQLite) | Serverless, edge-distributed with global replication |
| Auth (server) | Firebase Admin SDK | JWT verification, ADC on Cloud Run |
| File Storage | Firebase Storage (GCS) | Proctoring evidence with signed URLs |
| Hosting — Frontend | Cloudflare Pages | Edge CDN, custom domain: test.nssoftwaresolutions.in |
| Hosting — Backend | GCP Cloud Run (Asia South 2) | Containerized, auto-scaling, health monitoring |
| CI/CD | GCP Cloud Build | Automated build and deployment pipeline |
| Monitoring | GCP Cloud Monitoring | Performance metrics, logs, alerts |
Features
Multi-Role Platform
| Role | Access |
|---|---|
| Super Admin | Full platform control — tenant management, subscription and billing administration, global settings, audit logs, security. |
| Client Admin | Organizational control — question banks, test creation, student roster, analytics, subscription and Pay Per Test management. |
| Student | Test-taking, history, post-submission scorecard and XLSX performance report download. |
| Guest Student | Anonymous exam access via share code, no account required. |
Subscription & Billing System
- Four subscription tiers: Free, Starter (₹1,999/mo), Growth (₹3,999/mo), Enterprise (custom).
- Plan-driven limits: exams per month, candidates per exam, questions per exam — enforced server-side at every write operation.
- Plan-driven feature flags:
csv_import,xlsx_export,analytics,custom_branding,advanced_proctoring,camera_proctoring. - Subscription request workflow: Client Admins submit upgrade requests; Super Admins approve (auto-syncs limits, features, history) or reject.
- Automatic expiry: subscription status flips to
expiredon every/api/superadmin/subscriptionsfetch whenexpiry_dateis past. - Pay Per Test (PPT) System: Transactional assessment packages (Base ₹99, Basic ₹199, Standard ₹399, Professional ₹499, Placement Drive ₹1,499). Features include question limits (50-200), candidate capacity (50-500), proctoring controls, branding, and analytics. Client requests → Super Admin approves → Inventory available → Consumed on test creation with hard limits locked in
test_billing.
Test Management
- Folder-based test organization with uncategorized fallback.
- Draft / Published workflow with
statusandactivefield sync. - Scheduled activation and termination windows (
scheduled_start/scheduled_end). - Configurable attempts limit per student (0 = unlimited).
- Guest access toggle and public link with 8-character share code and QR code.
- Test cloning (
POST /api/rpc/clone-test) — copies questions, clears schedule, resets share code, forcesdraftstatus. read_onlylock: auto-applied when Pay Per Test candidate capacity is exhausted; blocks structural edits while allowing branding/visibility changes.
Assessment Builder
- Visual question palette with drag-and-drop-style reordering.
- Multi-section support with per-section configuration:
- Custom countdown timer (
duration_minutes) - Navigation lock (once candidate advances, prior section is locked)
- Shuffle questions and/or options independently
- Section-level negative marks override
- Custom countdown timer (
- Question types:
mcq,true_false,multi_select,fill_blank,subjective,coding. - Bulk CSV question import with two-stage validation, batch rollback by
import_batch_id, and question versioning.
Exam Engine (Student / Guest)
- Fullscreen enforcement with violation counter (3 strikes → auto-submit).
- Tab-switch / window-blur detection.
- Copy, paste, cut, right-click blocking.
- CSS text selection disabled on exam content.
- Section countdown timers with auto-advance or auto-submit on expiry.
- Section navigation lock: backend enforces via timer elapsed check and answer progression tracking — not just client-side.
- Auto-save answers with 2-second debounce (
POST /api/attempt-answers). - Auto-flush dirty answers before submission.
- Score masked until
show_results_after_submission = 1ANDresult_status = published.
Grading
- Server-side grading only (
POST /api/rpc/submit-attempt). - Supports single correct (
correct_answer) and multi-select (correct_answersJSON array). - Section-level negative marks override test-level negative marks.
- Score is floored at 0 (cannot go negative).
- Submission idempotent — duplicate submits return 400.
Proctoring
- Event types:
TAB_SWITCH,WINDOW_BLUR,FULLSCREEN_EXIT,NO_FACE,MULTIPLE_FACES,CAMERA_DISCONNECTED,CAMERA_PERMISSION_DENIED. - Severity scoring: LOW (1), MEDIUM (2–3), HIGH (5). Total risk score per attempt.
- Evidence snapshots (base64 → Firebase Storage GCS) for
NO_FACE,MULTIPLE_FACES,CAMERA_DISCONNECTED. - 30-second deduplication window: repeated events accumulate duration instead of inserting duplicates.
- Signed URLs (15-minute expiry) for evidence image retrieval.
- Feature-gated:
advanced_proctoring(basic events) andcamera_proctoring(camera events).
Analytics
- Super Admin dashboard: total clients, students, questions, tests, attempts; subscription plan distribution; expiring-soon alerts; today's exam activity and proctoring events; top orgs by student count; live load metrics (concurrent users, RPS, CPU, memory, API latency).
- Client Admin dashboard: student/question/test counts; average score and pass rate; top 5 performers; per-test performance breakdown.
- XLSX performance report: 3-sheet workbook (Summary, Detailed Questions, Analytics) with signed download for guests via
attempt_token.
Security
- Firebase ID token verification on every authenticated request.
- Tenant isolation: every query scoped to
client_idresolved from the authenticated user's profile. - BOLA/IDOR protection: all attempt/answer/proctoring reads verify
student_id === user.idor admin role. - Guest attempt token:
attempt_token(UUID) required for all guest read/write/submit/report/proctoring operations. - Rate limiting: 1,000 req/15 min global; 100 req/min on auth-sensitive endpoints.
- Maintenance mode: globally blocks new attempt creation when enabled; admin panels stay accessible.
Platform Controls (Super Admin)
- Maintenance mode toggle.
- Platform-wide announcement banner.
- User registration enable/disable.
- Platform branding logo (base64 or URL, reflected in all admin sidebars).
- Password reset for any user (Firebase Admin SDK).
- Paginated audit log with filters (user, action, entity type, date range).
- Client suspension (sets
active_status = 0, blocks all exam operations for that tenant).
Project Structure
exam-portal-ns/
├── backend/
│ ├── src/
│ │ ├── auth/
│ │ │ └── auth.ts # Firebase Admin SDK init + token verification
│ │ ├── db/
│ │ │ └── db.ts # Turso client init + all schema migrations
│ │ ├── middleware/
│ │ │ ├── auth.ts # Global auth context extractor
│ │ │ └── authz.ts # requireRole() middleware factory
│ │ ├── routes/
│ │ │ ├── rpc/
│ │ │ │ ├── clone-test.ts # Test duplication handler
│ │ │ │ └── submit-attempt.ts # Server-side grading engine
│ │ │ ├── attempt-answers.ts # Answer save/load with section lock enforcement
│ │ │ ├── attempts.ts # Attempt lifecycle management
│ │ │ ├── audit-logs.ts # Paginated audit log viewer (superadmin)
│ │ │ ├── clients.ts # Tenant CRUD + limits + features
│ │ │ ├── create-user.ts # Firebase + Turso user provisioning
│ │ │ ├── packages.ts # Pay Per Test package catalog + purchases
│ │ │ ├── proctoring.ts # Proctoring event logging + evidence upload
│ │ │ ├── profiles.ts # User profile management
│ │ │ ├── question-folders.ts # Question category folders
│ │ │ ├── questions.ts # Question bank CRUD + bulk import
│ │ │ ├── report.ts # XLSX performance report generation
│ │ │ ├── settings.ts # Global platform settings
│ │ │ ├── stats.ts # Dashboard analytics