How selleo/mentingo works
1. This is a monorepo for an LMS platform with three runnable apps: apps/api (NestJS backend), apps/web (Remix frontend), and apps/reverse-proxy (Caddy for local HTTPS/domain routing). The rest of the repo is shared libraries, generated artifacts, tests, and deployment/ops assets.
2. The backend is a modular NestJS monolith, not a microservice swarm. Each major domain lives in its own module under apps/api/src with a familiar controller/service/repository split. The largest domains are courses, lessons, users, auth, live training, learning paths, SCORM, file/video handling, announcements, analytics/statistics, AI, chat, settings, groups, and tenant administration.
3. Persistence is Postgres-backed and migration-driven. Database schema and migrations live in apps/api/src/storage, with Drizzle configs and a long migration history. The data model is strongly tenant-aware: tenant resolution, tenant state, and tenant row-level security are central architectural concerns rather than an afterthought.
4. Multi-tenancy is enforced in the backend data layer. storage/db contains tenant resolution, tenant DB runners, ALS-based request context, and an RLS interceptor. Many tables are tenant-scoped, and migrations explicitly enable RLS for core tables like permissions, outbox events, integration keys, learning paths, SCORM, and search documents.
5. The main backend write path is synchronous request handling plus asynchronous side effects. Controllers accept HTTP requests, services apply business rules, repositories persist state, and domain events/outbox records fan out to background work. This is visible in the events tree, outbox module, queues, workers, cron jobs, and per-domain handlers.
6. Background processing is a first-class subsystem. There are dedicated workers and queue services for activity logs, courses, master courses, learning paths, ingestion, audio transcription, Luma sync, SCORM import, and other long-running tasks. This keeps expensive jobs, external calls, and scheduled jobs off the request thread.
7. External integrations are woven into the backend boundaries. Auth supports local login plus Google, Microsoft, and Slack OAuth. Email is abstracted via adapters for SES, SMTP, and local/dev delivery. File and media flows integrate with S3, Bunny, Tus uploads, and video processing. Live training integrates with LiveKit, payments with Stripe, and observability with Sentry and Langfuse.
8. AI and knowledge ingestion are a distinct subsystem, not a feature flag. The ai module handles chat, threads, prompts, RAG, token accounting, summaries, and evaluation logic. The ingestion module chunks documents, generates embeddings, and populates vector/search-backed storage. Prompt definitions live in packages/prompts, and evaluation datasets/docs are checked in under docs/evaluation-datasets.
9. The frontend is a Remix application organized by product modules rather than technical layers. Routes and pages are composed from apps/web/app/modules, with feature-specific components, hooks, stores, schemas, and utilities living alongside the page entry points. It behaves like a client-heavy SPA, but Remix still provides routing, server entry, and SSR/hydration boundaries.
10. The web app talks to the API primarily through a generated TypeScript client and domain-specific hooks. app/api/generated-api.ts and the many query/mutation hooks show a deliberate API boundary: frontend features consume typed operations instead of calling REST endpoints ad hoc. WebSocket hooks are used where real-time updates matter, especially for live training, course chat, video upload state, and course-generation sync.
11. Authentication, authorization, and tenant/role access are enforced across both layers. The backend has JWT, refresh-token, feature, permission, tenant, staging, and support-mode guards; the frontend mirrors this with route/access guards and role-aware navigation. Support mode and super-admin tenant management are explicit product concepts with their own modules and UI surfaces.
12. Content and learning flows form the core business graph: courses contain chapters and lessons, lessons can be content, quiz, embed, SCORM, live training, or AI mentor experiences, and learning paths can aggregate courses and certificates. Surrounding modules like announcements, news, articles, Q&A, categories, groups, calendar, statistics, and learning time all feed the same tenant-scoped learning experience.
13. There are several specialized delivery pipelines. SCORM has both export/runtime packages (packages/scorm-export-generator, packages/scorm-export-runtime) and backend import/runtime support. Email templates are isolated in packages/email-templates. Shared constants, types, and utilities live in packages/shared, while packages/ui and packages/typescript-config provide cross-app design-system and config reuse.
14. Quality and deployment are built into the repo structure. Tests span Jest/Vitest unit tests, NestJS E2E tests, Playwright web E2E tests, and k6 performance scenarios. GitHub Actions, Dockerfiles, Compose files, and the Caddy reverse proxy indicate the app is intended to run as a containerized, multi-service system with separate frontend, API, database, and ancillary services like Mailhog.
Main entry points: api API · web Web · packages Shared libs · src Workers
Components 26
Monorepo
Top-level workspace with runnable apps, shared packages, and deployment assets.
- mentingo · LMS monorepo coordinating API, web, proxy, shared packages, and delivery assets.
Backend
NestJS API and server-side subsystems.
- API · Main backend application and domain monolith.
apps/api - Storage · Postgres schema, migrations, tenant-aware DB runner, and RLS enforcement.
apps/api/src/storage - Tenant DB · ALS-backed tenant resolution, request-scoped DB runner, tenant state, and RLS interceptor.
apps/api/src/storage/db - Courses · Course, chapter, lesson, enrollment, SCORM, and course-generation workflows.
apps/api/src/courses - Learning Paths · Learning-path composition, enrollment, export, certificate, and sync flows.
apps/api/src/learning-path - Content · Lessons, articles, news, QA, categories, groups, and announcements around tenant learning content.
apps/api/src - Auth · Local login, JWT/refresh tokens, OAuth strategies, MFA, and password flows.
apps/api/src/auth - Users · User lifecycle, import, notifications, roles, and admin-facing account management.
apps/api/src/user - Realtime · WebSocket gateways, presence, live updates, and real-time publishers.
apps/api/src/websocket - Workers · Queues, cron jobs, outbox dispatch, and background processors for expensive or delayed work.
apps/api/src - Files · Uploads, thumbnails, storage providers, video processing, and media delivery.
apps/api/src/file - Live Training · LiveKit-backed sessions, announcements, recordings, and attendance flows.
apps/api/src/live-training - AI · Chat, threads, prompts, RAG, token accounting, summaries, and judge/evaluation logic.
apps/api/src/ai - Ingestion · Document chunking, embeddings, indexing, and vector/search population.
apps/api/src/ingestion - Integrations · OAuth, email, S3/Bunny, Stripe, Sentry, Langfuse, Redis, and other boundary adapters.
apps/api/src/common
Frontend
Remix web app and browser-facing product modules.
- Web · Product UI with typed API client, route modules, and client-heavy flows.
apps/web - Typed client · Generated TypeScript client and domain hooks used by Remix features.
apps/web/app/api/generated-api.ts - Product modules · Route-centric feature areas for auth, dashboard, courses, admin, learning, live training, and settings.
apps/web/app/modules - Route guards · Frontend access, MFA, tenant, and role-aware route protection.
apps/web/app/Guards
Shared packages
Reusable libraries for prompts, SCORM, UI, types, and constants.
- Shared libs · Reusable packages for prompts, SCORM export/runtime, email templates, shared constants/types, and UI.
packages - Prompts · Generated prompt assets and templates for AI workflows.
packages/prompts - SCORM packages · SCORM export generator and runtime player assets.
packages/scorm-export-generator - Email templates · Shared transactional email content and translations.
packages/email-templates - Shared core · Cross-app constants, types, and small utilities for roles, features, content, and media.
packages/shared
Ops & delivery
Container, proxy, CI, test, and deployment assets.
- Proxy · Local HTTPS and domain routing layer.
apps/reverse-proxy
Connections 31
- mentingo → API: contains · Workspace includes the main backend app.
- mentingo → Web: contains · Workspace includes the Remix frontend.
- mentingo → Proxy: contains · Workspace includes the local reverse proxy.
- mentingo → Shared libs: contains · Workspace includes shared packages.
- API → Storage: persists via · Backend writes through migration-driven storage.
- Storage → Tenant DB: enforces · Tenant resolution and RLS are handled in the DB layer.
- API → Courses: serves · Course authoring, learning, enrollment, and SCORM flows.
- API → Learning Paths: serves · Learning-path composition and export flows.
- API → Content: serves · Content and communication domains share the monolith.
- API → Auth: guards with · Authentication and authorization are central request boundaries.
- API → Users: manages · User lifecycle and admin account operations.
- API → Realtime: publishes · WebSocket updates power live and collaborative features.
- API → Workers: offloads · Outbox, queues, workers, and cron jobs handle async work.
- API → Files: handles · Uploads, media processing, and delivery live in the backend.
- API → Live Training: integrates · Live training is a first-class backend domain.
- API → AI: implements · AI chat, RAG, summaries, and evaluation are backend features.
- API → Ingestion: feeds · Document ingestion supports AI/search pipelines.
- API → Integrations: adapts · External services are wired through boundary adapters.
- Web → Typed client: consumes · Frontend features use the generated typed API boundary.
- Web → Product modules: organizes as · Routes and UI are grouped by product module.
- Web → Route guards: protects with · Frontend mirrors backend access and tenant constraints.
- Web → Realtime: subscribes to · Course chat, live training, uploads, and sync use sockets.
- Web → Shared libs: reuses · Frontend shares types, UI primitives, and constants.
- Shared libs → Prompts: includes · Prompt templates for AI features.
- Shared libs → SCORM packages: includes · SCORM export generator/runtime package pair.
- Shared libs → Email templates: includes · Transactional email templates are isolated here.
- Shared libs → Shared core: includes · Common constants, types, and utilities live here.
- Workers → Storage: drains · Workers and dispatcher read/write persisted jobs and outbox records.
- Workers → Files: processes · Long-running media and import jobs run asynchronously.
- Workers → Learning Paths: syncs · Learning-path exports and course sync use workers.
- Workers → AI: supports · AI summaries, token accounting, and evaluation can run asynchronously.