Courses — Code Map
API — apps/api/src/courses/
courses.module.tscourses.controller.ts— split routing:- Trainer-side:
@Controller()with explicitorganizations/:orgId/courses[/…]paths. - Buyer-side:
me/courses[/…]paths (no org param). - Public:
@Public()onpublic/courses/:idandpublic/courses/:id/checkout.
- Trainer-side:
courses.service.ts—create | findAll | findById | update | publish | archive | setDay | setPrice | listMyEntitlements | getMyEntitlement | startCourse | restartCourse | markWorkoutComplete | unmarkWorkoutComplete | getCourseWorkout | listEnrollments | findPublicById | ensureEntitlementForCheckout | attachLeadForBuyer.course-checkout.service.ts— orchestrates the buy flow (categories A/B), gates by published status + active plan, callsPaymentService.createCourseHostedPayment.course-sessions.service.ts— trainer CRUD +listPublishedfor course meetings; trainer list carriesbookedCount.course-rsvps.service.ts— buyer book/cancel (transactional capacity,COURSE_MEETING_FULL), buyer session decoration (bookedCount,myRsvpStatus), trainer attendees + attendance.course-materials.service.ts— trainer materials CRUD + R2 presign (viaUploadsService, ownerTypecourse_material), buyer list + presigned download.courses.service.unit.spec.ts,course-rsvps.service.unit.spec.ts,course-materials.service.unit.spec.ts— unit tests.dto/courses.dto.ts—CreateCourseDto,UpdateCourseDto,SetCourseDayDto,SetCoursePriceDto,StartCourseDto,CourseCheckoutDto,CreateCourseSessionDto,UpdateCourseSessionDto,SetRsvpAttendanceDto,CreateCourseMaterialDto,UpdateCourseMaterialDto,PresignCourseMaterialDto.
API — adjacent
apps/api/src/payments/services/payment.service.ts:213—createCourseHostedPayment(setsmetadata.courseEntitlementId).apps/api/src/payments/services/webhook-processing.service.ts:199 / :332— handlesmetadata.courseEntitlementIdon payment-completed / payment-failed. Owns the cross-org guard.apps/api/src/leads/— lead lifecycle (source='course_purchase').apps/api/src/organization-leads/— junction table for category-B linking.
Shared
libs/shared/src/lib/schemas/course.schema.ts— Zod schemas forCourseResponse,PublicCourseResponse,CourseEntitlementResponse.libs/shared/src/lib/constants/course-errors.ts(or similar) —COURSE_ALREADY_OWNEDconstant exported.
DB
libs/db/src/lib/schema/courses.ts—course_configs,course_workouts,course_entitlements,course_workout_completions,course_sessions,course_session_rsvps,course_materials.libs/db/src/lib/schema/enums.ts—courseEntitlementStatus,coursePreviewType,publishStatus,courseRsvpStatus,courseMaterialKind,planType(coursevalue),deliveryMode(coursevalue),leadSource(course_purchasevalue).libs/db/src/lib/schema/scheduling.ts—programstable (the parent row).libs/db/src/lib/schema/payments.ts—planstable (course plans live here withtype='course'andprogram_idset).
Web — apps/web/src/
app/[lang]/buy/courses/[id]/page.tsx— public checkout entry point. Clerk email-code sign-in/sign-up flow; POSTs/public/courses/:id/checkoutonce authed.app/[lang]/(protected)/library/[id]/page.tsx— buyer’s player.app/[lang]/(protected)/dashboard/courses/— trainer-side CRUD + curriculum editor + enrollments view.[id]/course-meetings.tsx(meetings manager + attendees sheet),[id]/course-materials.tsx(materials manager) with co-located drivers + int specs.components/courses/course-dialog.tsx— trainer dialog for creating / editing the high-level course.components/courses/course-dialog.driver.tsx,course-dialog.int.spec.tsx— driver + tests.components/course-player/:player-header.tsxday-nav.tsx,day-tile.tsxworkout-view.tsxfull-program-sheet.tsxmeetings-section.tsx(+ driver/int spec) — buyer meetings with book/cancel, spots-left, add-to-calendarmaterials-section.tsx— buyer materials (downloads, links, YouTube/Vimeo embeds)ics.ts— client-side .ics generation for booked meetings
Cross-references
apps/api/src/minisites/— the public storefront link points at/buy/courses/:idon the gym’s minisite host.apps/api/src/notifications/templates/payment-receipt.ts— email used bysendPaymentReceiptafter a paid course purchase (only fires for category-A buyers today; see Gaps in README).apps/api/src/tasks/—cancellation_reviewandmanual_refundtask types are not specific to courses but apply when refunding a course purchase.
i18n keys
courses.buy.*— public checkout (email step, code step, signed-in confirm, redirect copy, error messages includingerrorAlreadyOwned).courses.*— trainer dialog + player labels.