A production-oriented student registration, payment, and admin operations system for CCA special-offer bootcamp onboarding.
CCA Offer Student Onboarding is a full-stack Next.js application built to handle the complete registration lifecycle for special-offer bootcamp intakes:
- ๐งญ guided public onboarding flow
- ๐งพ structured student detail capture and validation
- ๐ณ secure online payment initiation through PayHere
- ๐ฆ manual bank-transfer slip upload and verification workflows
- ๐๏ธ admin dashboard for records, exports, editing, and payment review
- ๐๏ธ Neon Postgres-backed student persistence
- โ๏ธ Vercel Blob-backed private payment-slip storage and downloadable receipt generation
- ๐ฒ optional SMS confirmation hooks for operational follow-up
This repository is maintained by Codezela Technologies and the source repository lives at:
- โจ Overview
- ๐ Key Highlights
- ๐ง Product Flow
- ๐ ๏ธ Tech Stack
- ๐บ๏ธ Application Routes
- ๐ API Surface
- ๐๏ธ Project Structure
- โ๏ธ Environment Configuration
- ๐พ Database And Storage
โถ๏ธ Getting Started- ๐งช Testing
- ๐ฆ Build And Deployment Notes
- ๐ Security And Operational Notes
- ๐ข Ownership And Branding
- ๐ License
- Select one or two bootcamp programs in a single onboarding journey.
- Pass through a multi-step guided registration process.
- Validate core student details including:
- Sri Lankan NIC
- email address
- district
- phone formats
- registration ID pattern
- Continue through multiple payment paths:
- PayHere online card payment
- bank transfer with payment-slip upload
- View success states and registration confirmations after completion.
- Generate and access downloadable receipt views through signed receipt links or the admin area.
- Secure admin login backed by encrypted session cookies.
- Paginated student dashboard with search, filters, and manual record creation.
- Individual student record view and edit flows.
- Manual admin-side grouped registration creation for one or two bootcamps.
- Optional bank-slip attachment during manual admin record creation.
- Student deletion support through admin API routes.
- Export student data to XLSX.
- Access uploaded payment slips through secured file-serving routes.
- Prisma-backed student persistence.
- Neon/Postgres runtime by default, with MySQL schema assets still present as alternate schema assets.
- Private Vercel Blob storage for payment slips.
- Optional SMS notifications when payment or registration workflows complete.
- Deadline-driven registration control using environment-configurable timing.
The platform is built around a staged registration journey. Registration data is first validated and staged in an encrypted cookie session, then committed into the database once a payment completion path is chosen.
flowchart LR
A["Landing Page"] --> B["Select 1-2 Bootcamps"]
B --> C["Eligibility Check"]
C --> D["Registration Form"]
D --> E["Validate + Stage In Session"]
E --> F["Payment Options"]
F --> G["PayHere Online Payment"]
F --> H["Bank Transfer Slip Upload"]
F --> I["Study Now / Pay Later Completion Route"]
G --> J["Payment Notify + Success View"]
H --> K["Slip Saved + Student Persisted"]
I --> L["Registration Success"]
J --> M["Admin Dashboard / Export / Receipt / Slip Access"]
K --> M
L --> M
- Student lands on the public home page.
- Student selects one or two bootcamps.
- Eligibility step determines whether the user can continue.
- Registration details are submitted to
/api/register. - Valid data is stored in the encrypted session cookie.
- Student chooses a payment path.
- Final records are written to the database when payment flow completes.
- Admins can review, export, edit, or inspect uploaded artifacts afterward.
- A single student journey can create multiple database rows when two bootcamps are selected.
- Registration IDs may be suffixed internally with
-1,-2, and so on for multi-bootcamp persistence. - Duplicate checks are scoped per bootcamp using normalized:
- NIC
- WhatsApp number
| Layer | Technology |
|---|---|
| Frontend | Next.js 16 App Router, React 19 |
| Language | TypeScript |
| Styling | Tailwind CSS v4 |
| Database ORM | Prisma 7 |
| Default Runtime Database | Neon Postgres |
| Additional Database Schema Assets | MySQL Prisma schema and generated client output |
| Testing | Vitest |
| Validation | Zod |
| Auth/session storage | Encrypted JWT cookie via jose |
| File generation | pdf-lib, custom XLSX generation, yazl |
| File persistence | Vercel Blob private storage |
| Payments | PayHere |
| Messaging | External SMS gateway integration |
| Route | Purpose |
|---|---|
/ |
Landing page and primary campaign entry point |
/select-bootcamp |
Bootcamp selection flow |
/check-eligibility |
Eligibility gate before registration |
/register |
Student registration form |
/payment/options |
Payment method selection |
/payment/payhere |
PayHere launch screen |
/payment/payhere-success |
Payment completion / processing state |
/payment/upload-slip |
Bank-transfer slip upload |
/payment/slip-success |
Slip submission success view |
/registration-success |
Success page for non-card completion flow |
/payment/receipt/[id] |
Receipt display page with signed-link or admin access |
/offer-ended |
Deadline-closed state |
| Route | Purpose |
|---|---|
/cca-admin-login |
Admin login |
/cca-admin-area/dashboard |
Student dashboard |
/cca-admin-area/student/new |
Manual admin record creation |
/cca-admin-area/student/[id] |
Student detail view |
/cca-admin-area/student/[id]/edit |
Student edit screen |
| Route | Purpose |
|---|---|
/files/slips/[studentId] |
Download or view uploaded slip file for a student |
/payment/receipt/[id]/download |
Receipt download route |
| Endpoint | Method | Purpose |
|---|---|---|
/api/register |
POST |
Validate and stage registration data in session |
/api/payment/blob/upload |
POST |
Authorize direct private slip uploads to Vercel Blob |
/api/payment/payhere/start |
POST |
Build PayHere payment payload and redirect to payment launcher |
/api/payment/notify |
POST |
Verify PayHere callback signature and mark payment complete |
/api/payment/store-slip |
POST |
Validate and store uploaded payment slip |
/api/payment/agree |
POST |
Complete the non-card registration path |
/api/payment/session/clear |
POST |
Clear staged payment session data |
| Endpoint | Method | Purpose |
|---|---|---|
/api/admin/login |
POST |
Authenticate admin session |
/api/admin/logout |
POST |
Clear admin session |
/api/admin/export |
GET |
Export filtered student records to XLSX |
/api/admin/student |
POST |
Create a manual admin student registration |
/api/admin/student/slip-upload |
POST |
Authorize optional admin-side slip upload during manual record creation |
/api/admin/student/[id] |
GET |
Retrieve student details |
/api/admin/student/[id] |
PUT |
Update student data |
/api/admin/student/[id] |
PATCH |
Approve a pending bank-slip registration group |
/api/admin/student/[id] |
DELETE |
Delete a student record |
.
โโโ AGENTS.md
โโโ README.md
โโโ app/
โ โโโ api/
โ โโโ cca-admin-area/
โ โโโ cca-admin-login/
โ โโโ check-eligibility/
โ โโโ files/
โ โโโ payment/
โ โโโ register/
โ โโโ registration-success/
โ โโโ select-bootcamp/
โโโ components/
โ โโโ admin/
โ โโโ forms/
โ โโโ ui/
โโโ generated/
โ โโโ mysql/
โ โโโ postgres/
โโโ lib/
โ โโโ content/
โ โโโ auth.ts
โ โโโ config.ts
โ โโโ db.ts
โ โโโ env.ts
โ โโโ flow.ts
โ โโโ ids.ts
โ โโโ payhere.ts
โ โโโ session.ts
โ โโโ sms.ts
โ โโโ storage.ts
โ โโโ student-service.ts
โ โโโ types.ts
โ โโโ validation.ts
โ โโโ xlsx.ts
โโโ prisma/
โ โโโ mysql/
โ โโโ postgres/
โโโ public/
โ โโโ images/
โโโ tests/
lib/config.tscontains business constants, fee values, bootcamp names, support details, and deadline accessors.lib/env.tsdefines environment-variable handling and required runtime configuration.lib/validation.tsis the core validation source of truth for registration input.lib/session.tscontrols encrypted cookie session behavior.lib/student-service.tscontains persistence, payment-completion, duplication, and dashboard logic.lib/storage.tshandles Blob-backed payment-slip validation, reads, and deletes.prisma/postgres/schema.prismadefines the default runtime data model..env.exampleshows the required local and deployed configuration variables.
The app no longer uses code-level fallback credentials or fallback session secrets. Operational settings should be set explicitly in local development and in each deployed environment.
| Variable | Purpose | Local behavior / default |
|---|---|---|
APP_URL |
Base URL used for generated absolute links and callbacks | Defaults to http://localhost:3000 |
ADMIN_USERNAME |
Admin login username | Required |
ADMIN_PASSWORD |
Admin login password | Required |
COUNTDOWN_DEADLINE |
Offer expiry and countdown cutoff | Required |
SESSION_SECRET |
Secret used for encrypted JWT session cookies | Required |
DATABASE_URL |
Runtime Neon/Postgres connection string used by the Prisma Neon adapter | No production-safe default |
DIRECT_URL |
Direct Postgres connection string used by Prisma CLI commands | Falls back to DATABASE_URL in prisma.config.ts |
BLOB_READ_WRITE_TOKEN |
Vercel Blob token for private uploads and reads | Required for slip uploads and admin slip access |
PAYHERE_MERCHANT_ID |
PayHere merchant ID | Required for real online payments |
PAYHERE_MERCHANT_SECRET |
PayHere merchant secret | Required for hash generation and callback verification |
PAYHERE_SANDBOX |
Toggle PayHere sandbox behavior | Defaults to true |
SMS_USERNAME |
SMS gateway username | Optional |
SMS_PASSWORD |
SMS gateway password | Optional |
SMS_SOURCE |
Sender/source identifier for SMS | Optional |
SMS_API_URL |
SMS provider endpoint | Optional |
These values must be supplied explicitly:
ADMIN_USERNAMEADMIN_PASSWORDSESSION_SECRETCOUNTDOWN_DEADLINE
If any of them are missing, the app should fail fast instead of silently booting with insecure defaults.
The live application code uses the Postgres Prisma client generated under:
generated/postgres/client
The runtime connection is handled by the Prisma Neon adapter in lib/db.ts and expects a Neon/Postgres DATABASE_URL.
The Prisma CLI uses:
DIRECT_URLwhen present- otherwise
DATABASE_URL
The primary persisted entity is Student, which includes:
- registration identifiers
- student identity fields
- selected bootcamp
- normalized duplicate-detection fields
- payment method and status
- payment slip blob pathname
- PayHere order ID
- amounts and timestamps
Uploaded payment slips are stored in:
- private Vercel Blob storage
Operationally, this means:
- uploads do not rely on the local filesystem
- admin slip access is mediated through the application route at
/files/slips/[studentId] BLOB_READ_WRITE_TOKENmust be configured in both local development and Vercel
- Neon/Postgres is the active runtime path in the current codebase.
- MySQL Prisma schema assets exist under
prisma/mysql, but the main application imports the Postgres-generated client. - The Prisma CLI path is configured in
prisma.config.ts.
- Node.js 20 or newer
- npm
npm installnpm run prisma:generateCopy the example environment file and fill in your real values:
cp .env.example .envAt minimum for local app flows you need:
DATABASE_URLDIRECT_URLBLOB_READ_WRITE_TOKEN
The app is designed for Neon Postgres in both local development and Vercel deployment.
Once your database credentials are set, sync the schema:
npm run prisma:pushIf you are using a migration-based local workflow:
npm run prisma:migratenpm run devOpen:
Use:
Use the ADMIN_USERNAME and ADMIN_PASSWORD values from your local .env.
Run the full test suite:
npm testRun tests in watch mode:
npm run test:watch- copy parity checks
- registration validation
- Sri Lankan NIC validation
- registration ID generation
- PayHere hash generation
- XLSX workbook generation
tests/copy-parity.test.tstests/validation.test.tstests/nic.test.tstests/ids.test.tstests/payhere.test.tstests/xlsx.test.ts
Create a production build:
npm run buildRun the production server locally:
npm run start- Set
APP_URLto the actual public base URL. - Set a strong
SESSION_SECRET. - Set explicit admin credentials.
- Configure
DATABASE_URLandDIRECT_URLfor Neon Postgres. - Configure
BLOB_READ_WRITE_TOKENfor Vercel Blob. - Configure real PayHere merchant credentials for card payments.
- Keep the upload flow on private Blob storage; it is already designed to avoid Vercelโs server body-size bottleneck by using direct client uploads.
The admin export endpoint returns an .xlsx workbook containing registration and payment fields, including hyperlinks to uploaded slip files when present.
- Admin and staged-registration state are stored in encrypted JWT cookies.
- Cookies are marked
httpOnly. - Secure cookies are enabled automatically in production.
- Card details are handled by PayHere, not stored directly by this application.
- PayHere notifications are verified with MD5-based signature logic in
lib/payhere.ts. - Payment-completion code paths should be treated as security-sensitive.
The payment-slip upload flow accepts these file extensions:
jpgjpegpngpdfdocxdoc
Maximum allowed file size:
10 MB
Storage backend:
- Private Vercel Blob
SMS delivery is optional. If SMS credentials are not configured, the app safely skips outbound delivery rather than failing the registration flow.
Registration availability is controlled by COUNTDOWN_DEADLINE. Once the deadline passes, the onboarding flow redirects to the offer-ended state.
This project is built and maintained by Codezela Technologies.
- Company website: https://codezela.com
- Repository: https://github.com/codezelat/cca-offer-student-onboarding
For branding, ownership, usage authorization, licensing, or implementation inquiries, use the official company website as the primary contact point.
This repository is proprietary software owned by Codezela Technologies.
- License file: LICENSE
- Public reuse, redistribution, sublicensing, or commercial exploitation is not permitted without prior written authorization from Codezela Technologies.
Copyright ยฉ 2026 Codezela Technologies. All rights reserved.

