An online course platform for corporate training. Admins build video/PDF courses with multiple-choice quizzes; employees enrol, learn at their own pace, pass the quiz, and earn an auto-generated PDF certificate. Progress, completions and certificates roll up into role-aware dashboards.
The UI is Atrium — an editorial-academic console with a royal-violet "scholar" accent, gold certificates and green completion, a Newsreader serif display, progress rings, a course player and a bookmark-ribbon that collapses the rail. Light and dark themes are both first-class.
- Course catalog filtered by category, with per-course progress.
- Course player — video and PDF lessons with a completion checklist.
- Quizzes — multiple-choice, auto-graded against a per-course pass threshold.
- Progress tracking — lessons + quiz roll up into a completion percentage.
- Certificates — a polished PDF certificate is generated automatically on completion.
- A personal dashboard with progress rings and "continue learning".
- Course management — create courses, upload video/PDF lessons and build quiz questions with the correct-answer marked.
- User management — create learners/admins, assign courses, remove users.
- Training dashboard — learners, courses, completions, completion rate, a per-course completed-vs-in-progress chart, a completions-over-time trend and a top-learners board.
- Activity log — a live feed of enrolments, quiz results, certificates and admin actions.
- Settings — default pass threshold and an AES-256-GCM-encrypted SMTP password.
- Two roles (admin / learner) with a role-aware sidebar.
- Light + dark themes (persisted), bookmark-ribbon collapse, resizable tables, password show/hide toggles, toasts, and a confirm modal on every destructive action and on sign-out.
| Layer | Choice |
|---|---|
| Backend | Node.js · TypeScript · Fastify |
| Storage | SQLite (better-sqlite3, WAL) under data/ |
| Uploads | @fastify/multipart → data/uploads (session-gated) |
| Certificates | pdfkit (A4-landscape PDF generated on the fly) |
| Crypto | bcryptjs passwords · HMAC-signed cookie · AES-256-GCM vault |
| Frontend | React + Vite + TypeScript SPA, Chart.js, react-router |
| Serving | Fastify serves the API, the built SPA and uploaded media |
- Node.js 18+ (developed on Node 24).
# backend deps
npm install
# build the SPA that the server serves
npm run build:web
# start the server (API + SPA on one port)
npm start # http://localhost:6500Open http://localhost:6500 and sign in.
| Role | Password | |
|---|---|---|
| Admin | admin@coursecorp.test |
Learn1234! |
| Learner | aysel@coursecorp.test |
Learn1234! |
On first boot a demo academy is seeded (6 courses with lessons + quizzes, 6 learners with realistic progress, completions and certificates).
# terminal 1 — API (auto-restart)
npm run dev
# terminal 2 — Vite dev server (proxies /api + /uploads → :6500)
cd web && npm run dev # http://localhost:5173Copy .env.example to .env:
PORT=6500
SESSION_SECRET=change-me-to-a-long-random-string
ADMIN_EMAIL=admin@coursecorp.test
ADMIN_PASSWORD=Learn1234!
MAX_UPLOAD_MB=200
# VAULT_KEY=base64-32-byte-key # else generated to data/.vault-key.env, data/ (database + uploads + vault key) and build artifacts are git-ignored.
- Auth — bcrypt password hashing; HMAC-signed, HTTP-only, 12-hour session cookie.
- Roles — every admin endpoint is role-checked server-side; learners never receive quiz answer keys.
- Secrets — the SMTP password is sealed with AES-256-GCM (key from
VAULT_KEYor generated todata/.vault-key, mode 0600) and shown masked. - Uploads — raw media under
/uploadsrequires a valid session.
.
├── src/ # Fastify backend (TypeScript, run via tsx)
│ ├── server.ts # app, plugins, static SPA + uploads, seed, listen
│ ├── routes.ts # all /api endpoints (auth, courses, quiz, certs, users…)
│ ├── data.ts # courses, enrolments, progress, certificates, dashboards
│ ├── certificate.ts # pdfkit certificate generator
│ ├── db.ts auth.ts vault.ts logbus.ts config.ts seed.ts types.ts
├── web/ # React + Vite SPA
│ └── src/
│ ├── App.tsx AppShell.tsx api.ts types.ts styles.css charts.tsx ui.tsx components.tsx
│ └── pages/ # Login, Dashboard, Catalog, Course, Certificates,
│ # AdminCourses, CourseManage, AdminUsers, Logs, Settings
└── requirements: package.json (backend) + web/package.json (frontend)
Apache License 2.0 — see LICENSE.