Workouts — code map
API (NestJS)
Base path: /organizations/:orgId
| Route | File | Method |
|---|---|---|
POST /workouts | apps/api/src/workouts/workouts.controller.ts | WorkoutsService.create |
GET /workouts | same | findAll (filters: programId, q) |
GET /workouts/:id | same | findById |
PATCH /workouts/:id | same | update (accepts ?assignmentId for lazy-fork redirect) |
DELETE /workouts/:id | same | remove (soft delete; rejects snapshots) |
PUT /workouts/:id/sections | same | setSections (accepts ?assignmentId) |
PATCH /workouts/:id/movements/:movementId/prescription | same | updateMovementPrescription (accepts ?assignmentId) |
GET /workouts/:id/movements/:movementId/comments | same | listMovementComments |
POST /workouts/:id/movements/:movementId/comments | same | createMovementComment |
Module: apps/api/src/workouts/workouts.module.ts registers the BullMQ workouts-enrichment queue, plus dependencies on MembershipsModule, UsersModule, UploadsModule, R2Module, PushNotificationsModule, and WorkoutAssignmentsModule (for forkSnapshotIfNeeded).
DTOs
apps/api/src/workouts/dto/create-workout.dto.ts—CreateWorkoutDtoapps/api/src/workouts/dto/update-workout.dto.ts—UpdateWorkoutDtoapps/api/src/workouts/dto/set-sections.dto.ts—SetSectionsDto,SectionDto,MovementDtoapps/api/src/workouts/dto/update-movement-prescription.dto.ts—UpdateMovementPrescriptionDtoapps/api/src/workouts/dto/create-exercise-comment.dto.ts—CreateExerciseCommentDto
Key service methods (apps/api/src/workouts/workouts.service.ts)
resolveEditTarget(workoutId, assignmentId?)— delegates toWorkoutAssignmentsService.forkSnapshotIfNeeded; returns the snapshot id when assignmentId is supplied.requireWorkoutBuilder(orgId)— tier gate for structured-mode writes.mapMovementToSnapshot/resolveSnapshotMovement— locate the snapshot’s mirror of a library movement after fork.deepCopyWorkout— lives inWorkoutAssignmentsService.deepCopyWorkout(apps/api/src/workout-assignments/workout-assignments.service.ts:859). Copies sections, movements, and comments.WorkoutsService.computeDisplayName(static) — title or first line of description, ≤60 chars.
Web (Next.js)
| Route | File path |
|---|---|
| Library list | apps/web/src/app/[lang]/(protected)/dashboard/workouts/page.tsx |
| Create chooser | apps/web/src/app/[lang]/(protected)/dashboard/workouts/new/page.tsx |
| Structured builder (new) | apps/web/src/app/[lang]/(protected)/dashboard/workouts/new/builder/page.tsx |
| Freeform create | apps/web/src/app/[lang]/(protected)/dashboard/workouts/new/freeform/page.tsx |
| Workout detail | apps/web/src/app/[lang]/(protected)/dashboard/workouts/[id]/page.tsx |
| Edit | apps/web/src/app/[lang]/(protected)/dashboard/workouts/[id]/edit/page.tsx |
| Member whiteboard | apps/web/src/app/[lang]/(protected)/(member)/whiteboard/page.tsx |
Key components
apps/web/src/components/overview/workouts/workout-list-view.tsx— coach library listapps/web/src/components/overview/workouts/workout-card.tsx— list itemapps/web/src/components/overview/workouts/workout-builder.tsx— top-level builder shellapps/web/src/components/overview/workouts/workout-builder/— builder internals:use-builder-state.ts— central state machine (draft sections, movements, undo/redo)use-builder-save.ts— POST/PUT orchestrationprescription-codec.ts— serialize/parsePrescriptionJSONBshape.ts— section shape (linear/amrap/emom/…) registry helperssuperset.ts— superset grouping rulesvolume.ts— total-volume computation for the right-rail summarykeys.ts— stable React keys across reorderscomponents/section-editor.tsx,prescription-panel.tsx,builder-right-rail.tsx,builder-header.tsx,builder-action-bar.tsx,ribbon-action.tsx,shape-renderers.tsx,sortable-section.tsx,section-type-combobox.tsx,num-input.tsx,movement-demo-dialog.tsx
apps/web/src/components/overview/workouts/freeform-workout-form.tsx— freeform editorapps/web/src/components/overview/workouts/workout-execution-view.tsx— read-only display for non-edit contextsapps/web/src/components/overview/workouts/exercise-autocomplete.tsx,exercise-library-browser.tsx,exercise-video-dialog.tsx— exercise pickersapps/web/src/components/member/workouts/workout-detail-drawer.tsx— member’s read view of the snapshot
DB (Drizzle, PostgreSQL)
All schema in libs/db/src/lib/schema/workouts.ts:
| Table | Purpose |
|---|---|
workouts | Library and snapshot rows. is_snapshot discriminates. |
workout_sections | Ordered sections per workout; carries shape + config JSONB for AMRAP/EMOM/etc. |
workout_movements | Ordered movements per section; carries prescription JSONB + label + superset_group. |
Comments: exercise_comments in libs/db/src/lib/schema/comments.ts.
Attachments: attachments in libs/db/src/lib/schema/attachments.ts (polymorphic ownerType='exercise_comment').
Shared
| File | Exports |
|---|---|
libs/shared/src/lib/schemas/workout.schema.ts | workoutResponseSchema, workoutSummaryResponseSchema, workoutSectionSchema, workoutMovementSchema, setSectionsInputSchema, scoring/section-type/mode enum values |
libs/shared/src/lib/schemas/prescription.ts | PrescriptionSchema + sub-schemas (reps, load) |
libs/shared/src/lib/schemas/section-shape.ts | Section container shape registry (linear / amrap / emom / for_time / tabata / rep_scheme / rounds / intervals) — TODO: verify exact filename casing |
libs/shared/src/lib/constants/platform-tiers.ts | tierHasFeature, basic_workouts, workout_builder feature constants |
Tests
| Type | File |
|---|---|
| Builder state unit | apps/web/src/components/overview/workouts/workout-builder/use-builder-state.int.spec.tsx |
| Builder save unit | apps/web/src/components/overview/workouts/workout-builder/use-builder-save.unit.spec.ts |
| Prescription codec | apps/web/src/components/overview/workouts/workout-builder/prescription-codec.unit.spec.ts |
| Section shape | apps/web/src/components/overview/workouts/workout-builder/shape.unit.spec.ts |
| Superset | apps/web/src/components/overview/workouts/workout-builder/superset.unit.spec.ts |
| Volume | apps/web/src/components/overview/workouts/workout-builder/volume.unit.spec.ts |
| Builder keys | apps/web/src/components/overview/workouts/workout-builder/keys.unit.spec.ts |
| Builder derive | apps/web/src/components/overview/workouts/workout-builder-derive.unit.spec.ts |
| Member detail drawer | apps/web/src/components/member/workouts/workout-detail-drawer.int.spec.tsx |
| Comments panel | apps/web/src/components/messages/workout-comments-panel.int.spec.tsx |
| E2E builder | apps/web/e2e/specs/workout-builder.spec.ts |
| E2E member workout | apps/web/e2e/specs/member-workout.spec.ts |
| E2E comments | apps/web/e2e/specs/workout-comments.spec.ts |
| E2E lazy-fork | apps/web/e2e/specs/lazy-fork.spec.ts |