Exercise Library Feature
Video library of exercises with taxonomy, instructions, and equipment requirements.
What this enables
Video exercise catalog: Browse hundreds of PT exercises by body region (shoulder, knee, lumbar spine) with video demos and step-by-step instructions.
Shared vs. custom: Use platform exercises ("Bird Dog", "Wall Slide") or clone and customize them for your clinic protocols.
Assign to treatment plans: Build telerehab programs from library exercises—"Day 1: 3x Shoulder External Rotation, 2x Wall Slide".
Track patient adherence: See which exercises patients complete, how many reps, if they're struggling.
Clinical taxonomy: Organize by category (stretching, strengthening, balance), body region, equipment needed, and clinical contraindications.
How it works
- Browse library: Admin searches for "shoulder" → sees 50+ shoulder exercises
- Create treatment plan: Builds 8-week program by adding library exercises
- Assign to patient: Patient gets treatment plan → telerehab app shows video demos
- Patient does exercises: Logs sets/reps → system tracks adherence
- Custom exercises (optional): Clone "Wall Slide" → customize instructions for your clinic's technique
- Analytics: See which exercises patients struggle with, which get best results
Technical Reference
Overview
The exercise library is a global + organization-scoped video exercise database for telerehabilitation. Organizations browse, search, and assign exercises to treatment plans. Exercises contain a video demonstration, text/image instructions, and full clinical taxonomy metadata.
Core Concept
Exercise Library = What exercises exist (content domain)
Treatment Plans = How exercises are prescribed (clinical domain) → See treatment-plans/
Telemetry = How exercises are tracked (analytics domain) → See integrations/An exercise defines:
- What it is (name, description, difficulty, taxonomy)
- How to perform it (video + ordered instruction steps)
- What's needed (equipment, contraindications)
An exercise does NOT define:
- Sets, reps, or duration (that's configured per-exercise in treatment plan sessions)
- Who should do it (that's on treatment plans → patient enrollment)
- Tracking data (that's in patient_exercise_logs and Telemetry)
Dual-Scope Model: Global + Organization
┌─────────────────────────────────────────┐
│ GLOBAL LIBRARY │
│ (organization_id IS NULL) │
│ Platform-curated by superadmins │
├─────────────────────────────────────────┤
│ exercises │
│ ├── Shoulder External Rotation │
│ ├── Wall Slide │
│ ├── Bird Dog │
│ └── Clamshell │
└─────────────────────────────────────────┘
↓ visible to all orgs
┌─────────────────────────────────────────┐
│ ORG LIBRARY │
│ (organization_id = org.id) │
│ Created by org admins │
├─────────────────────────────────────────┤
│ exercises │
│ ├── Custom Knee Protocol Step 1 │
│ ├── Post-ACL Warm-up (cloned) │
│ └── Balance Board Series │
└─────────────────────────────────────────┘Visibility rules:
- All authenticated users see global exercises (published)
- Org staff see global + their org's exercises
- Patients see published exercises only (through their treatment plans)
- Only superadmins can create/modify global exercises
- Org admins can create/modify their org's exercises
- Org admins can clone global exercises into their org library for customization
Key Tables
| Table | Purpose |
|---|---|
exercises | Main entity — video, metadata, taxonomy. Global (org_id NULL) or org-scoped. |
exercise_categories | Taxonomy categories (stretching, strengthening, balance). Hierarchical via parent_id. |
exercise_body_regions | Body part tags (shoulder, knee, lumbar spine). Grouped by body_area. |
exercise_equipment | Equipment catalog (resistance band, yoga mat, dumbbell). |
exercise_tags | Polymorphic M:M junction — links exercises to categories, body regions, and equipment. |
exercise_instructions | Ordered text/image instruction steps per exercise. |
exercise_contraindications | Clinical warnings/restrictions per exercise. |
Taxonomy
Exercises are tagged with three independent taxonomies. Each taxonomy is also dual-scoped (global + org):
Categories (Hierarchical)
Stretching
├── Static Stretching
├── Dynamic Stretching
└── PNF Stretching
Strengthening
├── Isometric
├── Isotonic
└── Plyometric
Balance & Proprioception
Mobility
Breathing & RelaxationBody Regions (Grouped by Area)
Upper Body
├── Shoulder
├── Elbow
├── Wrist / Hand
└── Cervical Spine
Core
├── Lumbar Spine
├── Thoracic Spine
└── Abdominals
Lower Body
├── Hip
├── Knee
├── Ankle / Foot
└── Glutes
Full BodyEquipment
No Equipment (bodyweight)
Resistance Band
Yoga Mat
Dumbbell
Swiss Ball
Foam Roller
Balance Board
TheraBandFiltering
The GET /v1/exercises endpoint supports multi-taxonomy filtering:
GET /v1/exercises?category_id=5&body_region_id=3&difficulty=beginner&equipment_id=2&status=published&q=plank&sort=-created_atVideo Storage
Exercises store video via a CDN-agnostic design:
video_url TEXT -- CDN URL (Bunny Stream, S3, etc.)
video_provider TEXT -- 'bunny_stream' | 's3'
video_thumbnail_url TEXT -- poster frame
video_duration_seconds INT -- cached durationWhy CDN-agnostic: The platform supports Bunny Stream (EU-first CDN with built-in HLS transcoding) or S3 + CloudFront. The video_provider field allows the upload/playback layer to adapt without schema changes.
See video-upload.md for the full upload flow and adaptive streaming design.
Instructions Model
Each exercise has ordered instruction steps with types:
Exercise: Shoulder External Rotation
├── [preparation] "Lie on your side with a towel roll under your arm"
├── [step] "Rotate your forearm upward, keeping elbow at 90°"
├── [form_cue] "Keep your elbow pinned to your side"
├── [breathing] "Exhale as you rotate up, inhale on return"
└── [safety] "Stop if you feel sharp pain in the shoulder joint"Instruction types: preparation, step, form_cue, breathing, safety
Each instruction can have an optional image (S3 upload) for visual demonstration.
Cloning
Org admins can clone exercises from the global library (or from their own library) to create customized variants:
POST /v1/exercises/{id}/cloneWhat gets cloned:
- All exercise fields (name, description, taxonomy, difficulty)
- All instructions (with images)
- All contraindications
- All tags
What changes:
- New UUID
organization_idset to current orgcloned_from_idset to source exercise IDstatusreset todraft
The clone is fully independent — editing the source does not affect the clone.
Soft Delete
Exercises use soft delete (deleted_at timestamp) because they may be referenced by active treatment plans. A soft-deleted exercise:
- Is hidden from library search/browse
- Remains visible in existing treatment plans (with a "discontinued" indicator)
- Cannot be added to new plans
- The
exercises.idFK intreatment_plan_session_exercisesusesON DELETE RESTRICTas a safety net
Exercise Status
draft → published → archived- draft: Only visible to admins/superadmins. Work in progress.
- published: Visible to all authorized users. Can be used in treatment plans.
- archived: Hidden from new plan creation but remains in existing plans.
Integration Points
With Treatment Plans Feature
- Exercises are added to
treatment_plan_session_exerciseswith per-plan configuration (sets, reps, duration, rest) - Exercise data (video, instructions) is always "live" — updates to an exercise are immediately visible in all plans
- Plan version snapshots capture exercise IDs (not exercise content), so the current exercise state is always shown
With Telemetry Service
- Video performance: When a patient watches an exercise video, the frontend sends the full media event lifecycle (
session_start,heartbeat,buffering_start/end,milestone,session_end) toPOST /v1/media/events. Stored in ClickHousemedia_sessions. See ../../telemetry/media-events.md for the event specification. Consent: Level 2+. - Pose tracking: If enabled, MediaPipe landmark frames are batched and sent to
POST /v1/pose/frames(separate endpoint). Stored in ClickHousepose_tracking_frames. Includes accuracy scores, rep counting, ROM degrees, and form feedback. Consent: Level 2+ (analytics) + biometric consent from patient. - Error reporting: Video playback errors reported via
POST /v1/errors/reportfor support troubleshooting. Consent: Level 1+.
With S3/CDN
- Exercise videos:
{org_id}/exercises/{exercise_id}/video/{filename}(org) orglobal/exercises/{exercise_id}/video/{filename}(global) - Instruction images:
{org_id}/exercises/{exercise_id}/instructions/{sort_order}/{filename} - Thumbnails:
{org_id}/exercises/{exercise_id}/thumbnail/{filename}
API Endpoints
See api.md for full API documentation.
Key endpoints:
GET /v1/exercises— Browse/search with taxonomy filtersPOST /v1/exercises— Create exercise (admin: org, superadmin: global)GET /v1/exercises/{id}— Full details with instructions, tags, contraindicationsPOST /v1/exercises/{id}/clone— Clone to org libraryPOST /v1/exercises/{id}/video— Upload video
Design Principles
- Dual-scope by design — Global library is platform-curated, org libraries are private. Both use the same tables with
organization_id IS NULLvsIS NOT NULL. - CDN-agnostic — Video storage abstracted behind
video_url+video_provider. No vendor lock-in. - Exercises are content, not configuration — No sets/reps/duration on exercises. That's treatment plan config.
- Mutable, not versioned — Exercises update in-place. If you need variants, clone them.
- Soft delete for safety — Referenced exercises can't be hard-deleted (RESTRICT FK + soft delete).
- Multi-tenant by design — All tables have org-scoped RLS. Global exercises get a special
organization_id IS NULLSELECT policy.