Capacity Connect · Technical atlas
How the platform is built
Capacity Connect is a learning management platform for the India Meteorological Department (SIH 2026, PS 26075). Trainees enroll and take assessments, trainers publish resources and quizzes, admins approve accounts and see competency data. This atlas is the technical approach the team builds from: components, data flow, function names, SQL and rules.
Every diagram opens full screen: tap or click it, or use Zoom / full screen. In the viewer, scroll or pinch to zoom, drag to pan, double-click to jump in.
System map
The whole platform on one sheet: clients, edge, the four-stage API chain, the control and data paths, Postgres with pgvector, local file storage, the AI provider switch, and the embedding worker pool. Read it top to bottom. The two thick arrows are the two main request paths.
System map
Components
One Express API holds all business logic as modules. Two things run outside it because they are slow or need other tooling: the Python ai-service and Gotenberg.
| Component | Tech | Responsibility | Path |
|---|---|---|---|
| Admin console | Vite multi-page build, React Router per section | Approvals, courses, competency widget, dropdown manager, notices | apps/admin-console |
| Portal | Vite multi-page build, React Router per section | One app for trainers and trainees; each page branches on role | apps/portal |
| Mobile | Flutter, go_router, dio | Trainee and trainer screens over the same REST API | apps/mobile |
| API | Node.js, Express, Better Auth, pg | Auth chain, REST handlers, rate limits, RLS context | services/api |
| ai-service | Python | Embedding workers, quiz drafting support, competency matching | services/ai-service |
| Gotenberg | Docker image behind the API | HTML to PDF for certificates, internal network only | services/pdf-service |
| Database | PostgreSQL 17, pgvector, Drizzle | All tables, vectors and row-level security policies | packages/db |
| Local AI | Ollama | nomic-embed-text embeddings always; Qwen3.5 for quizzes in local mode | runs on the deployment host |
Two request paths
The map draws two thick arrows out of the API. They behave differently and are worth keeping apart in your head.
JSON in, JSON out. Courses, enrollment, profiles, notices, dropdowns, approvals, questionnaires, attempts and feedback. Small, fast, transactional. Every handler runs inside the RLS transaction described on the Security page.
Bytes in, bytes out. Resource uploads go to the volume, certificate PDFs come back from Gotenberg and land in the volume, and downloads stream from it. These routes are the only way a file leaves storage.
Uploading a resource queues an embedding job. The ai-service worker turns the file into chunks and vectors without holding up the request.
Design rules
- The API is the only real gateHiding a sidebar item is decoration. Every protected route passes verifyJWT, attachRole, authorizeRoute and injectRLSContext, on web and mobile alike.
- Row-level security carries the identityEach request opens a transaction and sets the caller id and role for that transaction. Policies filter rows and vectors. No pooler sits between the API and Postgres, so the setting cannot leak across requests.
- Embeddings are always localEvery vector comes from Ollama nomic-embed-text at 768 dimensions. The model name is stored in an embedding_model column next to each vector so a future model swap is detectable.
- One switch for quiz AIAI_PROVIDER selects Vertex AI (Gemini) or local Ollama (Qwen3.5 9B/4B). Both must return the same JSON shape, so the rest of the system never branches on the provider.
- Files never have public URLsUploads, certificates and dumps sit on a Docker volume. The database stores a file_path. Downloads go through the API and inherit the same row-level checks.
- A human reviews AI outputGenerated questions land as drafts. Nothing reaches trainees until the trainer edits and publishes.
Roles
| Role | Kind | Can do |
|---|---|---|
super_admin | service role | Used by the embedding workers to write resource_chunks. Not a person-facing role. |
admin | person | Approve and reject accounts, manage dropdowns and notices, see dashboards, run competency suggestions. |
trainer | person | Create courses, upload resources, generate and publish questionnaires, monitor trainee results. |
trainee | person | Enroll, read resources, attempt questionnaires once, give feedback, download certificates. |