Skip to main content

Course System Codemap

Architecture Overview

┌─────────────────────────────────────────────────────────────────┐
│ SERVER (NestJS) — single source of truth │
│ Route prefix: /course │
│ 4 controllers → 10 services → 12 entities → 26 DTOs │
├─────────────────────────────────────────────────────────────────┤
│ FRONTENDS — each defines own types, consumes HTTP API │
│ instructor/ editor + dashboard │
│ admin/ management + analytics │
│ student/ player + progress │
│ public/ marketplace + search │
│ landing-page/ marketing │
└─────────────────────────────────────────────────────────────────┘

Cross-package rule: No type imports between frontend packages. Each defines local interfaces.


1. Server: Course Module

Module: server/src/course/course.module.ts

1.1 Hierarchy

Course
├── CourseSection (course_sections)
│ └── CourseSubSection (course_subsections)
│ └── CourseItem (course_items) — VIDEO, FILE, TEXT, etc.
├── Level (levels)
├── CourseManager (course_managers) — junction: instructor → course
├── Requirement (course requirements with icon+text)
├── Inclusion (course inclusions/benefits with icon+text)
└── Audience (target audience with icon+text)

1.2 Controllers

File: server/src/course/course.controller.ts — Route prefix /course

MethodEndpointServiceDescription
POST/courseCourseWriteService.createCreate course
GET/courseCourseReadService.findAllPaginated list, view-based serialization
GET/course/:idCourseReadService.findOneBy ID, ?view=admin|dashboard|public
GET/course/slug/:slugCourseReadService.findOneBy slug, public access allowed
PUT/course/:idCourseWriteService.updateUpdate course
DELETE/course/:idCourseWriteService.removeHard delete
PUT/course/:id/visibilityCourseModerationService.updateCourseVisibilityAdmin only — isFeatured, isHidden
GET/course/:id/playerCoursePlayerService.getCourseForPlayerStudent player with section locking
GET/course/:id/curriculumCourseReadService.getNormalizedCurriculumSections → subsections → items
GET/course/:id/performanceCourseModerationService.getCoursePerformanceAnalytics metrics
GET/course/summaries/:idCourseModerationService.getCourseSummaryInstructor summaries
GET/course/:id/statisticsCourseModerationService.getInstructorStatisticsInstructor stats
GET/course/levelsCourseReadService.getAllLevelsAll levels
POST/course/levelsCourseReadService.createLevelAdmin only

Section endpoints (nested under /course):

MethodEndpointService
GET/course/section?courseId=CourseSectionService.findAll
GET/course/section/:sectionIdCourseSectionService.findOne
POST/course/sectionCourseSectionService.create
PUT/course/section/:sectionIdCourseSectionService.update
DELETE/course/section/:sectionIdCourseSectionService.remove

Subsection endpoints:

MethodEndpointService
GET/course/subsection?sectionId=CourseSubSectionService.findAll
GET/course/subsection/:subsectionIdCourseSubSectionService.findOne
POST/course/subsectionCourseSubSectionService.create
PUT/course/subsection/:subsectionIdCourseSubSectionService.update
DELETE/course/subsection/:subsectionIdCourseSubSectionService.remove
POST/course/subsection/batch-update-orderCourseSubSectionService.batchUpdateOrder

Item endpoints:

MethodEndpointService
GET/course/item?subsectionId=CourseItemService.findAll
GET/course/item/:courseItemIdCourseItemService.findOne
POST/course/itemCourseItemService.create
PUT/course/item/:courseItemIdCourseItemService.update
DELETE/course/item/:courseItemIdCourseItemService.remove
GET/course/download/:courseItemIdCourseItemService.downloadFile
POST/course/item/:courseItemId/video/uploadCourseItemService.initVideoUpload (Bunny TUS)
POST/course/item/:courseItemId/video/refreshCourseItemService.refreshVideoUpload
GET/course/item/:courseItemId/videoCourseItemService.getVideoPlayback

Property endpoints (Requirements, Inclusions, Audiences):

MethodEndpoint
GET/course/:id/:type
GET/course/:courseId/:type/:propId
POST/course/:courseId/:type
PUT/course/:courseId/:type/replace
PATCH/course/:courseId/properties/:type/:propId
DELETE/course/:courseId/:type/:propId

Batch controller (batch-update.controller.ts):

MethodEndpoint
PATCH/course/batch/:courseId/sections
PATCH/course/batch/:sectionId/subsections
PATCH/course/batch/:subsectionId/items

Course Manager controller (course-manager.controller.ts):

MethodEndpoint
POST/course-managers
GET/course-managers/:id
GET/course-managers/course/:courseId
GET/course-managers/instructor/:instructorId
PUT/course-managers/:id
DELETE/course-managers/:id

1.3 Services

ServiceFileKey Methods
CourseReadServiceservices/course-read.service.tsfindAll (paginated, nestjs-paginate), findOne (by id/slug with view), getAllLevels, createLevel, getNormalizedCurriculum
CourseWriteServiceservices/course-write.service.tscreate, update, remove — emits COURSE_UPDATED, COURSE_REMOVED events
CourseModerationServiceservices/course-moderation.service.tsgetCourseSummary, getInstructorStatistics, getCoursePerformance, updateCourseVisibility
CoursePlayerServiceservices/course-player.service.tsgetCourseForPlayer — assembles player data with section locking, progress, pre-signed video URLs, enrollment validation
CourseResponseServiceservices/course-response.service.tstoResponseDto — maps entities to response DTOs with serialization groups
CourseSectionServicecourse-section.service.tsCRUD for sections, batch order update
CourseSubSectionServicecourse-subsection.service.tsCRUD for subsections, batch order
CourseItemServicecourse-item.service.tsCRUD for items, Bunny Stream video upload init/refresh/playback, file downloads
CourseManagerServicecourse-manager.service.tsCRUD for course-instructor assignments
ProgressServiceprogress.service.tstrackProgress, getProgress, updateVideoProgress, markVideoCompleted, getCourseCompletionStatus
TimeCalculationService(in progress module)Video time calculations

1.4 Entities

Course (entities/course.entity.ts) — Table: courses

FieldTypeNotes
idUUID PK
titlestringUnique
slugstringUnique, nullable
subtitlestring
categoryRelation→Category
subcategoryRelation→Category
levelRelation→LevelEager
languagestring
subtitleLanguagestring
publishStatusenumDRAFT / PUBLISHED / ARCHIVED
descriptionstring
thumbnailRelation→FileOneToOne
introductoryVideoRelation→FileOneToOne
priceInCentsint
currencyenumUSD default
isFreeboolean
saleActiveboolean
salePercentageint
saleStart / saleEndDate
approvedboolean
isFeaturedboolean
isHiddenboolean
gigActivebooleanElasticsearch indexed flag
durationint
durationMeasureenumMINUTES/HOURS/DAYS/WEEKS/MONTHS/YEARS
instructorRelation→InstructorEager
managersRelation→CourseManager[]OneToMany
sectionsRelation→CourseSection[]OneToMany, cascade
requirementsRelation→Requirement[]OneToMany, cascade
inclusionsRelation→Inclusion[]OneToMany, cascade
audiencesRelation→Audience[]OneToMany, cascade
welcomeMessagestring
completionMessagestring
shareUrlstring
publishedAtDate
approvedAtDate
timingstring
lessonNotestring

CourseSection (entities/sections.entity.ts) — Table: course_sections

FieldType
idUUID PK
titlestring
descriptionstring
priceInCentsint (for à-la-carte)
saleActive / salePercentage
isActiveboolean
orderint
courseRelation→Course
subsectionsRelation→CourseSubSection[]

CourseSubSection (entities/subsections.entity.ts) — Table: course_subsections

FieldType
idUUID PK
titlestring
descriptionstring
isActiveboolean
orderint
sectionRelation→CourseSection
itemsRelation→CourseItem[]

CourseItem (entities/course_item.entity.ts) — Table: course_items

FieldType
idUUID PK
titlestring
typeenum: VIDEO / FILE / CAPTION / LECTURE_NOTE / TEXT / DESCRIPTION / ASSIGNMENT / QUIZ
sizeint (for files/video)
durationint (minutes for video)
contenttext (HTML for text-based types)
fileUrlstring
bunnyVideoIdstring
bunnyVideoStatusstring
isActiveboolean
orderint
subSectionRelation→CourseSubSection

Level (entities/level.entity.ts) — Table: levelsid, text

CourseManager (entities/manager.entity.ts) — Junction: course ↔ instructor

1.5 Enums

EnumFileValues
PublishStatusenums/publish-status.enum.tsDRAFT, PUBLISHED, ARCHIVED
CourseItemTypeenums/course-item.enum.tsVIDEO, FILE, CAPTION, LECTURE_NOTE, TEXT, DESCRIPTION, ASSIGNMENT, QUIZ
ItemCompletionStatusenums/item-status.enum.tsNOT_STARTED, IN_PROGRESS, NOT_AVAILABLE, COMPLETED
DurationMeasureenums/duration-measure.enum.tsMINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS

1.6 CASL Permissions

File: course.permissions.ts

RolePermission
everyoneRead published courses
adminManage all courses
supportRead/update courses
instructorOwn courses only (by instructor ID)

Hooks: CourseHook loads course entity for permission checks. CourseSectionHook loads section's parent course.

1.7 WebSocket Gateway

File: course-progress.gateway.ts — Namespace course-progress

Events: heartbeat, time_update, mark_completed, get_last_watched. 5s debounce on writes. Syncs video position to UserVideoProgress.

1.8 Background Jobs

File: jobs/certificate-generation.job.ts — BullMQ job for completion certificates.


2. Server: Enrollment Module

Module: server/src/enrollment/enrollment.module.ts — Route /enrollment

2.1 Endpoints

MethodEndpointDescription
GET/enrollment/meCurrent user's enrollments
GET/enrollment/check/:productType/:productIdCheck enrollment status
GET/enrollment/:idSingle enrollment
GET/enrollment/:id/completionCompletion check
GET/enrollmentAdmin: all enrollments

Enrollment Entity (entities/enrollment.entity.ts) — Table: enrollments

FieldType
idUUID PK
typeProductItemType (COURSE / CONSULTATION)
studentRelation→Student
courseRelation→Course
statusEnrollmentStatus
paymentRelation→Payment
orderRelation→Order
sectionEnrollmentsRelation→SectionEnrollment[]
enrolledAtDate
accessEndDateDate

EnrollmentStatus enum: PENDING, APPROVED, COMPLETED, REJECTED, REFUNDED

2.2 Enrollment Flow

Payment success event
→ EnrollmentListener listens for AppEvents.PAYMENT_SUCCESSFUL
→ enrollmentService.createEnrollment()
→ Creates Enrollment record
→ Creates SectionEnrollment records
→ Emits AppEvents.ENROLLMENT_CREATED
→ InstantListener creates chat room participant
→ NotificationListener sends product enrollment notification

3. Server: Cross-Cutting

3.1 Elasticsearch Integration

Files: server/src/elastic/

FileRole
course-elastic.service.tsIndex: upsert, delete, search, update gigActive
types/elastic-course.type.tsIndexed document shape
properties/course.property.tsES property mappings
listeners/course.listener.tsListens COURSE_UPDATED, COURSE_REMOVED, PRODUCT_ACTION_NEEDED → syncs to ES

Courses are indexed with gigActive flag. Search queries filter gigActive: true.

Route: /marketplace/course (separate controller)

Used by public/ for course discovery. Wraps Elasticsearch queries.

3.3 Analytics

File: server/src/analytics/entities/course-analytics-daily.entity.ts

Daily aggregations: enrollments, revenue, views, completions per course.

3.4 Video Infrastructure

  • Bunny Stream for video hosting
  • TUS resumable upload protocol via initVideoUpload → returns upload URL + signature
  • refreshVideoUpload for expiring signatures
  • getVideoPlayback returns playback URL, thumbnail, available resolutions

4. Student Frontend

4.1 Service Layer

File: student/src/services/course.service.ts

Static HTTP client class. Defines local Course, Section, Subsection, Item, Level, Category, Instructor, etc. interfaces.

MethodAPI Call
getCourseById(id, view)GET /course/:id?view=
getCourseBySlug(slug, view)GET /course/slug/:slug?view=
getAllSectionsForCourse(courseId, view)GET /course/section?courseId=&view=
getSectionById(id)GET /course/section/:id
getAllSubsectionsForSection(sectionId)GET /course/subsection?sectionId=
getSubsectionById(id)GET /course/subsection/:id
getAllItemsForSubsection(subsectionId)GET /course/item?subsectionId=
getItemById(id)GET /course/item/:id
getItemVideoPlayback(id)GET /course/item/:id/video
downloadCourseItemFile(courseItemId)GET /course/download/:courseItemId
getAllLevels()GET /course/levels

4.2 Player Service

File: student/src/services/course-player.service.ts

MethodAPI Call
getCourseForPlayer(courseId)GET /course/:id/player

Returns StudentCoursePlayerDto with section locking, progress, pre-signed video URLs.

4.3 Progress Service

File: student/src/services/course-progress.service.ts

MethodAPI Call
getCourseProgress(courseId)GET /course/progress/:courseId
updateCourseProgress(courseId, data)PATCH /course/progress/:courseId
getLastWatchedPosition(courseId)GET /course/progress/:courseId/last-watched

4.4 React Query Hooks

HookFileKey
useCourse(courseId)hooks/useCourse.ts["course", courseId]
useCoursePlayer(courseId)hooks/useCoursePlayer.ts["coursePlayer", courseId]
useCourseProgress(courseId)hooks/useCourseProgress.ts["courseProgress", courseId] — includes optimistic updates + utility methods
useEnrollments(type?)hooks/useEnrollments.ts["enrollments", type]

useCourseProgress returns:

  • progress, isLoading, error
  • updateProgress, updateSection, updateSubsection, updateItem
  • setCurrentPosition, getItemProgress, markItemCompleted, updateVideoTime
  • getSectionProgress, getSubsectionProgress

Optimistic update pattern: onMutate snapshots + onError rollback + onSettled invalidation.

4.5 Zustand Store

File: student/src/stores/my-course.ts

Persisted store (my-course-store key) for current player position: sectionId, subsectionId, itemId, videoCurrentTime.

4.6 Progress Types

File: student/src/types/course-progress.d.ts

CourseProgress {
currentSectionId, currentSubsectionId, currentItemId,
currentVideoSeekTime, completionPercentage,
sections: [{ id, progressPercentage, completed,
subsections: [{ id, completed,
items: [{ id, completed, seekTime, lastAccessed }]
}]
}]
}

4.7 Pages

RouteComponentPath
/my-coursesMyCourses.tsxpages/my-courses/MyCourses.tsx
/my-courses/ongoingOnGoingCourse.tsxpages/my-courses/OnGoingCourse.tsx
/my-courses/completedCompleted.tsxpages/my-courses/Completed.tsx
/my-courses/:idMyCourseDetails.tsxpages/my-courses/[id]/MyCourseDetails.tsx
—/descriptionDescription.tsxpages/my-courses/[id]/Description.tsx
—/attachedAttached.tsxpages/my-courses/[id]/Attached.tsx
—/lesson-noteLessonNote.tsxpages/my-courses/[id]/LessonNote.tsx
—/commentsComments.tsxpages/my-courses/[id]/Comments/

4.8 Player Components

ComponentPath
Sectioncomponents/Curriculum/Section/index.tsx
Lecturecomponents/Curriculum/Section/Lecture.tsx
SubSectioncomponents/Curriculum/Section/SubSection.tsx
CourseContentcomponents/course-slider/CourseContent.jsx

5. Instructor Frontend

5.1 Service Layer

File: instructor/src/services/course.service.ts

Full CRUD for course management. Defines local CourseResponseDto, CreateCourseDto, UpdateCourseDto, CourseSummaryDto, CourseManagerDto.

MethodAPI Call
createCourse(data)POST /course
getAllCourses(query)GET /course?view=dashboard&... — paginated with filters
getCourseById(id)GET /course/:id?view=dashboard
getCourseBySlug(slug)GET /course/slug/:slug?view=dashboard
getNormalizedCurriculum(id)GET /course/:id/curriculum?view=dashboard — Zod validated
updateCourse(id, data)PUT /course/:id
deleteCourse(id)DELETE /course/:id
batchUpdateSections(courseId, data)PATCH /course/batch/:courseId/sections
batchUpdateSubsections(sectionId, data)PATCH /course/batch/:sectionId/subsections
batchUpdateItems(subsectionId, data)PATCH /course/batch/:subsectionId/items
getAllLevels()GET /course/levels?view=dashboard
getCourseSummaries(instructorId)GET /course/summaries/:instructorId?view=dashboard
Property CRUDGET/POST/PUT/DELETE /course/:id/:type
replaceAllProperties(courseId, type, data)PUT /course/:courseId/:type/replace
Course Manager CRUDGET/POST/PUT/DELETE /course-managers

Additional services:

  • instructor/src/services/course-item.service.ts — Item CRUD
  • instructor/src/services/course-section.service.ts — Section CRUD
  • instructor/src/services/course-subsection.service.ts — Subsection CRUD

5.2 Course Editor

Multi-step form with Zustand store slices:

SliceFile
State definitionstores/course-editor/state.ts
Typesstores/course-editor/types.ts
Curriculumstores/course-editor/curriculum.slice.ts — sections/subsections/items
Formstores/course-editor/form.slice.ts
Step wizardstores/course-editor/step.slice.ts
Navigationstores/course-editor/navigation.slice.ts
Syncstores/course-editor/sync.slice.ts
Step handler registrystores/course-editor/step-handler-registry.ts

Editor pages:

StepComponentPath
Basic InfoBasicInformation.tsxpages/editor/BasicInformation.tsx
Advanced InfoAdvanceInformation.tsxpages/editor/AdvanceInformation.tsx
CurriculumCurriculum.tsxpages/editor/Curriculum.tsx
PricingPricing.tsxpages/editor/Pricing.tsx
PublishPublishCourse.tsxpages/editor/PublishCourse.tsx

Editor components:

ComponentPathRole
CurriculumSectioncomponents/course/CurriculumSection.tsxDrag-and-drop section
CurriculumSubsectioncomponents/course/CurriculumSubsection.tsxDrag-and-drop subsection
CourseItemcomponents/course/CourseItem.tsxItem type selector/editor
CourseImagecomponents/course/CourseImage.tsxThumbnail upload
SubsectionContentcomponents/course/SubsectionContent.tsxContent editor
SubmitButtoncomponents/course/SubmitButton.tsxPublish/submit
bunny-videocomponents/course/bunny-video.tsBunny Stream integration
sortablecomponents/course/sortable.tsxDnD wrapper

5.3 Dashboard Pages

PageFile
Course listpages/course/CoursesMain.tsx
Course detail/editpages/course/CourseDetailsPage.tsx
Activity dashboardcomponents/course/CourseActivityDashboard.tsx
Activity summarycomponents/course/CourseActivitySummary.tsx

5.4 Zod Validation

File: instructor/src/utils/schema/course.schema.tsnormalizedCurriculumSchema


6. Admin Frontend

6.1 Service Layer

File: admin/src/services/course.service.ts

MethodAPI Call
getAllCourses(params)GET /course — paginated
getAdminCourses(params)GET /course with data normalization
getAdminCourse(id)GET /course/:id?view=admin
deleteCourse(id)DELETE /course/:id
updateVisibility(id, update)PUT /course/:id/visibility
getCourseCurriculum(id)GET /course/:id/curriculum
deleteSection(sectionId)DELETE /course/section/:sectionId
deleteCourseItem(itemId)DELETE /course/item/:itemId
getCourseAnalytics(id)GET /analytics/course/:id
getCourseReviews(courseId)GET /review/all?id=&type=course
deleteReview(reviewId)DELETE /review/:reviewId

6.2 Admin Course Types

File: admin/src/types/course.types.ts

Defines AdminCourse (280+ lines), CourseListParams, CurriculumData, CourseFilters, CourseStatistics, CourseDetailAnalytics, CourseReview, PublishStatus enum, DurationMeasure enum, VisibilityUpdate.

6.3 Zod Schemas

File: admin/src/schemas/course.schema.ts

courseFiltersSchema, visibilityUpdateSchema, courseRejectionSchema, courseApprovalSchema.

6.4 Data Provider Handler

File: admin/src/providers/data-provider/handlers/courses.handler.ts

Integrates with Refine/React Admin for list, show, delete operations.

6.5 Pages & Components

Page/ComponentPath
Course listpages/courses/list.tsx
Course detailpages/courses/show.tsx with tabs
CourseCardpages/courses/CourseCard.tsx
FilterBarpages/courses/components/FilterBar.tsx
BulkActionsBarpages/courses/components/CourseBulkActionsBar.tsx
StatsGridpages/courses/components/CourseStatsGrid.tsx
OverviewTabpages/courses/components/OverviewTab/
CurriculumTabpages/courses/components/CurriculumTab/
AnalyticsTabpages/courses/components/AnalyticsTab/
ReviewsTabpages/courses/components/ReviewsTab/
AdminTabpages/courses/components/AdminTab/ — approve/reject
CourseHeaderpages/courses/components/CourseHeader/
SharedComponentspages/courses/components/SharedComponents.tsx
DeleteCourseDialogpages/courses/components/Modals/DeleteCourseDialog.tsx

7. Public/Marketplace Frontend

7.1 Service Layer

File: public/src/services/course.service.ts

MethodAPI CallView
getCourseById(id)GET /course/:idPUBLIC
getCourseBySlug(slug)GET /course/slug/:slugPUBLIC
getAllSectionsForCourse(courseId)GET /course/section?courseId=default
getSectionById(id)GET /course/section/:id
getAllSubsectionsForSection(sectionId)GET /course/subsection?sectionId=
getSubsectionById(id)GET /course/subsection/:id
getAllItemsForSubsection(subsectionId)GET /course/item?subsectionId=
getItemById(id)GET /course/item/:id
getAllLevels()GET /course/levels
getCoursesByInstructor(instructorId, limit)GET /course?instructorId=
searchMarketplaceCourses(params)GET /marketplace/course

7.2 Hooks

HookFile
useCoursePage()hooks/useCoursePage.ts — slug → course, enrollment check, section selection
useCoursesPage()hooks/useCoursesPage.ts — categories, best-selling, top-rated, most-popular, new-arrival
useCourseSearch()hooks/useCourseSearch.ts
useSimilarCourses()hooks/useSimilarCourses.ts
useInstructorAvailableCourses()hooks/useInstructorAvailableCourses.ts

7.3 Store

File: public/src/stores/course.ts

Zustand store: currentTab, selectedSections for à-la-carte purchasing with section selection/deselection and price calculation.


8. SDK (Auto-generated)

Files: sdk/src/

FileContent
axios/course/course.ts50+ API client functions (orval-generated)
axios/course-managers/course-managers.tsCourse manager API client
hooks/course/course.tsReact Query hooks (useQuery + useMutation)
hooks/course-managers/course-managers.tsCourse manager query hooks

9. Data Flow Diagrams

Course Creation (Instructor)

Instructor Editor
→ CourseEditor.tsx (multi-step wizard)
→ instructor/src/services/course.service.ts
→ POST /course (create)
→ POST /course/:id/section (add sections)
→ POST /course/section/:sectionId/subsection (add subsections)
→ POST /course/item (add items)
→ POST /course/item/:id/video/upload (upload video via Bunny TUS)
→ Server: CourseWriteService.create
→ Course entity saved
→ Event emitted: COURSE_CREATED
→ Elasticsearch listener indexes course

Course Player (Student)

Student opens /my-courses/:id
→ MyCourseDetails.tsx
→ useCoursePlayer(courseId)
→ GET /course/:id/player
→ CoursePlayerService.getCourseForPlayer()
→ Validates enrollment
→ Loads course + sections + subsections + items
→ Computes section locking (previous section must be completed)
→ Generates pre-signed video URLs
→ Returns StudentCoursePlayerDto with progress
→ useCourseProgress(courseId)
→ GET /course/progress/:courseId
→ Tracks: currentSection, currentItem, videoTime, completion
→ Optimistic updates via React Query mutation
→ WebSocket: course-progress gateway for real-time heartbeat
→ PATCH /course/progress/:courseId on debounce

Course Approval (Admin)

Admin opens course detail
→ GET /course/:id?view=admin
→ AdminTab: Approve / Reject
→ PUT /course/:id (sets approved=true + publishStatus=PUBLISHED)
→ AppEvents.COURSE_APPROVED emitted
→ NotificationListener → email to instructor
→ InstantListener → creates GROUP chat room
→ Course added to Elasticsearch (gigActive = true)
→ Marketplace now shows course

Enrollment (Student Purchase)

Student purchases course
→ Payment successful → AppEvents.PAYMENT_SUCCESSFUL
→ EnrollmentListener → enrollmentService.createEnrollment()
→ Creates Enrollment + SectionEnrollment records
→ Emits AppEvents.ENROLLMENT_CREATED
→ InstantListener: adds student as chat room participant
→ NotificationListener: sends enrollment confirmation
→ Student can now access /course/:id/player

Course Search (Marketplace)

User searches on landing/public
→ public/src/hooks/useCoursesPage.ts
→ GET /marketplace/course (Elasticsearch-backed)
→ Filters: category, level, price, rating, search term
→ Returns paginated results with totalHits
→ Course card → GET /course/slug/:slug
→ Checks enrollment (GET /enrollment/check/course/:id)
→ Shows enroll/buy CTA

10. File Index by Package

Server: Course Module (~58 files)

CategoryCountKey Paths
Module1course.module.ts
Controllers4course.controller.ts, course-manager.controller.ts, progress.controller.ts, batch-update.controller.ts
Services10services/course-read.service.ts, services/course-write.service.ts, services/course-moderation.service.ts, services/course-player.service.ts, services/course-response.service.ts, course-section.service.ts, course-subsection.service.ts, course-item.service.ts, course-manager.service.ts, progress.service.ts
Entities12entities/course.entity.ts, entities/sections.entity.ts, entities/subsections.entity.ts, entities/course_item.entity.ts, entities/level.entity.ts, entities/manager.entity.ts, entities/progress.entity.ts, entities/user-video-progress.entity.ts, entities/user-video-session.entity.ts, entities/requirement.entity.ts, entities/audience.entity.ts, entities/benefit.entity.ts
Enums4enums/publish-status.enum.ts, enums/course-item.enum.ts, enums/item-status.enum.ts, enums/duration-measure.enum.ts
DTOs26dto/ — create, update, response, player, video, batch, manager, progress, curriculum
Hooks/Perms4course.hook.ts, course-section.hook.ts, course.permissions.ts
Gateway1course-progress.gateway.ts
Jobs1jobs/certificate-generation.job.ts
Seeds1seeds/level.seeder.ts

Server: Enrollment Module (~16 files)

enrollment.module.ts, enrollment.controller.ts, enrollment.service.ts, entities/enrollment.entity.ts, entities/section-enrollments.entity.ts, enums/enrollment-status.entity.ts, dto/ (7 files), listeners/enrollment.listener.ts, enrollment.permissions.ts, enrollment.hook.ts

Server: Cross-Cutting

elastic/course-elastic.service.ts, elastic/types/elastic-course.type.ts, elastic/properties/course.property.ts, elastic/listeners/course.listener.ts, analytics/entities/course-analytics-daily.entity.ts, faker/flows/course.flow.ts, validation/schemas/course.schema.ts, templates/emails/course.tsx

Student Frontend (~18 files)

CategoryKey Paths
Servicesservices/course.service.ts, services/course-player.service.ts, services/course-progress.service.ts
Hookshooks/useCourse.ts, hooks/useCoursePlayer.ts, hooks/useCourseProgress.ts, hooks/useEnrollments.ts
Storestores/my-course.ts
Typestypes/course-progress.d.ts
Pagespages/my-courses/MyCourses.tsx, pages/my-courses/OnGoingCourse.tsx, pages/my-courses/Completed.tsx, pages/my-courses/[id]/MyCourseDetails.tsx, pages/my-courses/[id]/Description.tsx, pages/my-courses/[id]/Attached.tsx, pages/my-courses/[id]/LessonNote.tsx, pages/my-courses/[id]/Comments/
Componentscomponents/Curriculum/Section/, components/course-slider/CourseContent.jsx
Layoutlayout/CoursePageLayout.jsx

Instructor Frontend (~30 files)

CategoryKey Paths
Servicesservices/course.service.ts, services/course-item.service.ts, services/course-section.service.ts, services/course-subsection.service.ts
Storestores/course-editor/ (9 slices)
Pagespages/course/CoursesMain.tsx, pages/course/CourseDetailsPage.tsx, pages/editor/ (6 files)
Componentscomponents/course/ (10 files)

Admin Frontend (~18 files)

CategoryKey Paths
Serviceservices/course.service.ts
Typestypes/course.types.ts
Schemasschemas/course.schema.ts
Handlerproviders/data-provider/handlers/courses.handler.ts
Pagespages/courses/list.tsx, pages/courses/show.tsx
Tab Componentscomponents/ — OverviewTab, CurriculumTab, AnalyticsTab, ReviewsTab, AdminTab

Public Marketplace (~7 files)

CategoryKey Paths
Serviceservices/course.service.ts
Hookshooks/useCoursePage.ts, hooks/useCoursesPage.ts, hooks/useCourseSearch.ts, hooks/useSimilarCourses.ts, hooks/useInstructorAvailableCourses.ts
Storestores/course.ts

SDK (~4 files)

axios/course/course.ts, axios/course-managers/course-managers.ts, hooks/course/course.ts, hooks/course-managers/course-managers.ts

Landing Page (~3 files)

components/cards/courses_card/CoursesCard.jsx, pages/home/courseSearch/CourseSearch.jsx