CASE STUDY 07 · SaaS

NexusLMS

A production-grade LMS with an AI tutor wired into the content model.

NexusLMS landing page: learning that adapts to every mind

Learning Management System with a RAG-backed AI tutor, smart assessments with 8 question types, a block-based course builder, and enterprise multi-tenancy — 110+ tables, 38 API modules.

110+

database tables

38

API modules

8

assessment question types

RLS

database-enforced multi-tenancy

THE PROBLEM

LMS products split into two camps: legacy enterprise systems (deep but hostile to use) and modern course-sellers (pleasant but shallow — no real assessment engine, no tenancy, no compliance surface).

Bolting a chatbot onto either camp produces a toy. An AI tutor is only useful if it's grounded in the actual course content and aware of where the learner is.

WHAT I BUILT

A full LMS: block-based course builder (text, video, embeds, assessments composed like documents), an assessment engine with 8 question types and configurable grading, learner progress tracking, and enterprise multi-tenancy with row-level security.

The AI tutor is RAG over the tenant's own course corpus: it answers with citations into the material, scoped to what the learner is enrolled in — a tutor that has actually read the course, not a general chatbot in a sidebar.

ARCHITECTURE

Next.js 15 (learner + admin apps)
      │
      ▼
NestJS API ── 38 modules
  ├─ course builder (block model)
  ├─ assessment engine (8 question types)
  ├─ AI tutor ── RAG over tenant course corpus
  │               (embeddings + citation-grounded answers)
  ├─ custom JWT auth (multi-tenant claims)
  └─ Drizzle ORM ──► PostgreSQL
                      110+ tables · RLS per tenant
  • Multi-tenancy runs on Postgres row-level security — the database enforces isolation even if application code slips, which is the only tenancy story worth telling enterprises.
  • The tutor's RAG index is per-tenant and per-course: embeddings are scoped so answers can cite the learner's actual material and never leak across tenants.
  • 38 NestJS modules keep a 110-table domain navigable — each module owns its slice of schema, DTOs, and permissions.

STACK — AND WHY

Next.js 15

Learner and admin frontends with server components for content-heavy pages.

NestJS

Module system that keeps a very large API surface organized and testable.

PostgreSQL + RLS

Database-enforced tenant isolation; 110+ tables of relational course/assessment/progress structure.

Drizzle ORM

Typed schema shared across 38 modules — refactoring a 110-table domain without types would be suicide.

THE HARD PARTS

RAG that cites, scoped to tenancy

The tutor must answer from the tenant's courses only, with citations a learner can click. That means per-tenant embedding namespaces, retrieval filtered by enrollment, and answer generation constrained to retrieved chunks — hallucinated confidence is worse than 'I don't know' in an education product.

An assessment engine that survives real teachers

Eight question types × partial credit × retakes × time limits × question banks with randomization — the combinatorics of assessment configuration is where LMS complexity actually lives. The engine models attempts as immutable event streams so regrades and disputes are replayable.

110+ tables without drowning

The schema is the product. Keeping it navigable required strict module ownership (no cross-module table writes), typed queries end-to-end, and migrations as first-class reviewed artifacts.

WHAT IT TAUGHT ME

  • Row-level security moves tenancy from 'trust my code' to 'trust Postgres' — worth the query-planning care it costs.
  • In education, the AI feature's ceiling is your content model: RAG is only as good as the block structure it retrieves over.
  • Immutable attempt events made every 'my grade is wrong' conversation answerable with a replay instead of an apology.
Visit nexus.hire.rest← Back to the descent