Perfxcel Architecture
System Overview
Perfxcel consists of three services: a public React SPA, an internal admin React SPA, and a shared Express REST API backed by Supabase PostgreSQL.
graph TB
subgraph Public
PX[perfxcel.com\nReact 19 / Cloudflare Pages]
end
subgraph Admin
PA[admin.perfxcel.com\nReact 19 / Cloudflare Pages]
end
subgraph API
PXAPI[api.perfxcel.com\nNode.js / Express 5]
SB[(Supabase PostgreSQL\nperfxcel schema)]
AUTH[Supabase Auth\nJWT validation]
end
PX -->|GET /courses, POST /interests| PXAPI
PA -->|Bearer JWT — all admin routes| PXAPI
PXAPI -->|requireAuth + requirePerfxcelTenant| AUTH
PXAPI -->|supabase client (service role)| SB
Request Flow — Public Learner
Public routes on perfxcel-api require no authentication. The public site calls the API directly.
sequenceDiagram
participant L as Learner (perfxcel.com)
participant API as api.perfxcel.com
participant CF as Cloudflare Turnstile
participant SB as Supabase PostgreSQL
L->>API: GET /api/v1/courses
API->>SB: SELECT * FROM courses WHERE is_published=true AND status='active'
SB-->>API: Course list
API-->>L: 200 OK
L->>CF: Turnstile widget challenge
CF-->>L: token
L->>API: POST /api/v1/courses/:id/interest { turnstileToken, ... }
API->>CF: POST /siteverify (token verification)
CF-->>API: { success: true }
API->>SB: INSERT INTO interests (...)
SB-->>API: Interest created
API-->>L: 201 Created
Request Flow — Admin Operation
Admin routes require a valid Supabase JWT from the perfxcel tenant.
sequenceDiagram
participant A as admin.perfxcel.com
participant API as api.perfxcel.com
participant SB_AUTH as Supabase Auth
participant SB_DB as Supabase PostgreSQL
A->>API: POST /api/v1/courses (Bearer JWT)
API->>SB_AUTH: supabase.auth.getUser(token)
SB_AUTH-->>API: { user }
API->>API: requirePerfxcelTenant — verify user is perfxcel tenant member
API->>SB_DB: INSERT INTO courses (...)
SB_DB-->>API: Course created
API-->>A: 201 Created
Service Responsibilities
perfxcel-app (Public SPA)
- Course catalog with taxonomy-based filtering (category, city, association, delivery mode)
- Course detail pages with interest registration form (Cloudflare Turnstile)
- Certificate verification (
/verify) - Training plan request form
- Contact form with Turnstile
perfxcel-admin (Internal Admin SPA)
- Course management — create, edit, publish, bulk-manage
- Taxonomy management — categories, cities, associations, delivery modes
- Interest management — view and convert to enrollments
- Enrollment management — status tracking
- Training plan requests — review and act on bulk requests
- Enquiry management — update status
- Audit logs — paginated, filterable action log
- Dashboard — real-time platform metrics (courses, interests, enrollments)
perfxcel-api (REST API)
- Single Express 5 app, all routes under
/api/v1/ - Two authentication tiers:
- Public — no auth, rate-limited by
globalLimiter - Admin —
requireAuth+requirePerfxcelTenantmiddleware chain - Cloudflare Turnstile server-side verification on interest/contact submissions
- Sentry error tracking via
@dotevolve/error-utils
API Route Map
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/v1/courses |
Public | List published active courses |
POST |
/api/v1/courses |
Admin | Create a course |
PATCH |
/api/v1/courses/bulk |
Admin | Bulk update course status/visibility |
GET |
/api/v1/courses/:id |
Public | Get a single course |
PUT |
/api/v1/courses/:id |
Admin | Update a course |
DELETE |
/api/v1/courses/:id |
Admin | Soft-delete a course |
POST |
/api/v1/courses/:id/interest |
Public | Register learner interest |
GET |
/api/v1/taxonomies |
Public | List all taxonomy items |
POST |
/api/v1/taxonomies |
Admin | Create a taxonomy item |
PUT |
/api/v1/taxonomies/:id |
Admin | Update a taxonomy item |
DELETE |
/api/v1/taxonomies/:id |
Admin | Delete a taxonomy item |
GET |
/api/v1/interests |
Admin | List interest submissions |
PATCH |
/api/v1/interests/:id |
Admin | Update interest status |
GET |
/api/v1/enrollments |
Admin | List enrollments |
POST |
/api/v1/enrollments |
Admin | Create enrollment |
PATCH |
/api/v1/enrollments/:id |
Admin | Update enrollment status |
GET |
/api/v1/enquiries |
Admin | List enquiries |
PATCH |
/api/v1/enquiries/:id |
Admin | Update enquiry status |
POST |
/api/v1/contact |
Public | Submit contact form (Turnstile) |
GET |
/api/v1/verify |
Public | Verify a certificate number |
GET |
/api/v1/metrics |
Admin | Platform metrics (dashboard) |
GET |
/api/v1/audit-logs |
Admin | Paginated audit log |
GET |
/api/v1/training-plan |
Admin | List training plan requests |
POST |
/api/v1/training-plan |
Public | Submit training plan request |
Technology Stack
| Concern | Choice |
|---|---|
| API runtime | Node.js 24 / Express 5 / TypeScript 5.9 |
| Database | Supabase PostgreSQL (perfxcel schema) |
| Auth | Supabase Auth (service role key on API) |
| Bot protection | Cloudflare Turnstile |
| Error tracking | @dotevolve/error-utils (Sentry) |
| Frontend build | Vite 8 / React 19 / Tailwind CSS 4 |
| Deployment | Cloudflare Pages (frontends), OCI (API) |
| Testing | Vitest 4 (frontends), Jest 30 (API) |