Appearance
ProgramsAndExercise / YMove / free-exercise-db
CoachMe uses YMove for exercise metadata and videos, while local thumbnails come from free-exercise-db.
The V1 baseline integration keeps search fast and quota-safe by syncing YMove browse metadata without media fields, importing public-domain exercise images from yuhonas/free-exercise-db, and using reviewed mappings between the two datasets. YMove media is fetched only when a user opens an exercise video/demo and only after CoachMe confirms the current plan has enough remaining internal allowance.
Tags: YMove metadata, Local thumbnails, Signed media guarded, Manual review queue
Status
V1 baseline provider decision. YMove is the selected exercise content provider for metadata and videos. free-exercise-db is the primary thumbnail/image source for search results so the search screen does not consume YMove media quota.
V1 Baseline Decisions
These constraints keep the integration aligned with current YMove docs and the product goal of a fast searchable library.
Provider Roles
- YMove: source of exercise ids, names, taxonomy, instructions, metadata, and video/demo media.
- free-exercise-db: source of local thumbnail images used on the search screen and compact exercise cards.
- CoachMe: owns normalized catalog tables, coach-created custom exercises, custom media uploads, external video URL validation, Arabic/search synonyms, thumbnail mappings, media quota enforcement, and program snapshots.
- Coach-created custom exercises do not call YMove; they use the generic Exercise Library custom media and URL-validation contracts.
- YMove exercise type values are stored as Exercise Library taxonomy nodes with
taxonomy_type = exercise_type; provider-specific labels and ids are preserved instead of flattened into an application enum. - YMove signed thumbnail/video URLs are not stored in the database and are not used for normal search-result thumbnails.
Runtime Rules
- Search and browse read from CoachMe's local normalized catalog, not directly from YMove on every keystroke.
- Search thumbnails resolve only from approved
free-exercise-dbmappings or CoachMe-owned placeholders. - Video access calls YMove only after checking CoachMe's rolling 30-day unique media access count and monthly video-minute allowance.
- Program Builder stores exercise snapshots so existing programs render even if provider content or mappings change later.
Implementation Sequence
Build the integration in layers so search works before video playback and manual review can clean up image mappings.
1. Provider Setup
- Create a YMove provider integration row with plan settings, API base URL, secret reference, and enabled status.
- Store the YMove API key only in backend secret storage. Never expose it in web or Expo clients.
- Implement
YMoveExerciseProviderAdapterbehind the genericExerciseProviderPort. - Implement
GET /usagepolling so CoachMe can compare its local counters with YMove's account-level counters.
2. Metadata Bootstrap
- Fetch YMove exercises using browse mode with
includeVideos=false. - Fetch muscle groups and exercise types for taxonomy mapping.
- Normalize the results into
exercise_catalog_items, taxonomy tables, and search documents. - Store provider content hashes so future syncs update only changed rows.
3. Thumbnail Library Import
- Import
free-exercise-dbJSON exercises, image paths, and license provenance. - Copy or mirror images into CoachMe-controlled storage for stable thumbnails.
- Generate normalized matching features: name tokens, equipment, primary muscles, secondary muscles, category, and movement hints.
- Create generic fallback placeholders by muscle group/equipment for unmatched exercises.
4. Mapping Review
- Run deterministic matching first to produce top candidates for each YMove exercise.
- Use GPT only to rank ambiguous candidates from normalized fields and explain the score.
- Auto-approve only high-confidence matches with no equipment or muscle conflicts.
- Route low-confidence, conflicting, or missing matches to an admin review queue.
5. Search Runtime
- Program Builder calls CoachMe search APIs backed by local catalog indexes.
- Each result includes a local thumbnail asset URL when an approved mapping exists.
- Unmatched results show a CoachMe-owned placeholder instead of calling YMove for media.
- Selected exercises create snapshots for program drafts and assigned programs.
6. Video Runtime
- User opens the exercise detail video/demo action.
- CoachMe checks local plan counters before calling YMove with media enabled.
- If allowed, backend fetches fresh YMove exercise data with video fields and returns a short-lived media response.
- If blocked, backend returns a typed quota status and the UI shows a clear unavailable message.
Caching And Storage Policy
CoachMe should save what is safe and useful, while treating signed YMove media URLs as temporary runtime values.
| Data | Source | Storage Rule | Usage |
|---|---|---|---|
Exercise id, title, slug, description, instructions, important points, taxonomy, equipment, difficulty, provider type taxonomy node references, and flags such as hasVideo | YMove browse mode | Store normalized metadata in CoachMe DB. Optional raw import payload may be retained internally for audit/debug with access controls. Unknown provider type values are rejected from active search until mapped or reviewed. | Search, type filters, details, program snapshots, matching pipeline. |
| Muscle groups and exercise types | YMove taxonomy endpoints | Store normalized taxonomy with provider references and content hashes. | Program Builder filters, browse lists, Arabic synonym mapping. |
| Images and image paths | free-exercise-db | Store locally or in CoachMe-controlled object storage. Retain source repo, path, import version, and license provenance. | Search thumbnails and compact exercise cards. |
| GPT matching suggestions, scores, reasons, and candidate lists | Internal matching job | Store in review tables as internal workflow data. Do not use scores directly at runtime. | Manual mapping review and import audit. |
YMove videoUrl, videoHlsUrl, thumbnailUrl, videos, and signed CDN URLs | YMove media-enabled response | Do not store in DB. Do not cache long-term. Return only as a short-lived runtime media DTO or proxy response. | Video/demo playback after quota checks. |
| YMove video files or thumbnails as assets | YMove CDN | Do not download, mirror, or rehost for V1 baseline. | Not used for search thumbnails. Playback comes from fresh signed media access only. |
Note
YMove docs say video and thumbnail URLs are pre-signed and expire after 48 hours. Treat these URLs as runtime-only even if technically usable in browser tags.
Thumbnail Mapping Pipeline
The matching score is an internal review tool. The live app should only use approved mappings or placeholders.
Candidate Generation
- Normalize names by lowercasing, removing punctuation, expanding common abbreviations, and standardizing equipment terms.
- Generate candidates with exact name, token similarity, equipment match, primary muscle overlap, secondary muscle overlap, and category/type compatibility.
- Reject or penalize obvious conflicts: dumbbell vs barbell, cable vs machine, incline vs decline, unilateral vs bilateral, standing vs seated, and stretch vs strength.
- Keep the top 5 to 10 candidates for GPT review only when deterministic confidence is not enough.
GPT Review Input
- Send minimal normalized fields: exercise name, equipment, muscle groups, category/type, and short instruction summary when needed.
- Do not send API keys, signed media URLs, video URLs, raw full responses, or user/client data.
- Ask for a structured JSON result with candidate id, score, conflict flags, and a short reason.
- Using GPT here is classification/matching assistance, not model training.
| Score Band | Default Status | Rule |
|---|---|---|
>= 0.90 | APPROVED candidate | Auto-approve only if equipment, primary muscle, and movement pattern have no conflict flags. |
0.75 - 0.89 | NEEDS_REVIEW | Queue for quick manual verification. Reviewer can approve, reject, or pick another candidate. |
< 0.75 | UNMATCHED | Use placeholder until a reviewer manually maps an image. |
| Any score | NEEDS_REVIEW | Manual review is required when there is a hard equipment, muscle, movement, or body-position conflict. |
Mapping artifact shape
internal import output
json
{
"ymoveExerciseId": "ym_123",
"ymoveName": "Incline Dumbbell Curl",
"recommendedStatus": "NEEDS_REVIEW",
"candidates": [
{
"freeExerciseDbId": "Alternate_Incline_Dumbbell_Curl",
"score": 0.88,
"conflicts": ["alternating_variant"],
"reason": "Same equipment, primary muscle, and incline position. Variant differs because the local image exercise alternates arms."
}
]
}YMove Video Access And Quota Guard
CoachMe should block avoidable media calls before YMove does, then handle provider-side caps defensively.
Preflight Check
- Receive a video/demo request for one normalized exercise id.
- Resolve the YMove provider exercise id from the catalog item.
- Check whether this exercise already has a media access event inside the rolling 30-day window.
- If this would be a new unique media exercise and the local cap is reached, do not call YMove.
- If local video-minute allowance is near the configured cap, block or require an admin override depending on environment.
- Call YMove only when the request is allowed.
Provider Response Handling
- If YMove returns video fields, create a media access event with duration and whether it counted as a new rolling-window exercise.
- If video fields are missing because the provider cap is exceeded, record provider warning state and return
MEDIA_LIMIT_REACHED. - If the signed URL fails in the player, refetch exercise media once and update the runtime media response.
- Never write signed media URLs into persistent tables, logs, outbox payloads, analytics events, or client offline caches.
Suggested user message
"Video preview is unavailable on the current exercise media plan. The exercise details and program prescription are still available."
Data Model Additions
These tables extend the generic Exercise Library model with YMove-specific usage and thumbnail mapping needs.
| Table | Purpose | Important Columns |
|---|---|---|
exercise_provider_integrations | Generic provider row configured with provider_key = YMOVE. | credentials_ref, plan_key, media_unique_limit, video_minutes_limit, license_policy, last_usage_synced_at. |
exercise_catalog_items | Normalized YMove exercise metadata imported with media fields disabled. | provider_exercise_id, names, instructions, primary_muscle_ids, equipment_ids, difficulty, has_video, content_hash. |
free_exercise_db_items | Imported public-domain exercise records and available local image paths. | source_id, name, equipment, primary_muscles, secondary_muscles, category, source_payload, imported_at. |
free_exercise_db_assets | Local image asset records. | free_exercise_db_item_id, source_path, local_asset_key, width, height, sha256, license, source_url. |
exercise_thumbnail_mappings | Approved or rejected mapping from YMove exercise to local thumbnail asset. | exercise_catalog_item_id, free_exercise_db_item_id, asset_id, status, source, reviewed_by_user_id, reviewed_at. |
exercise_thumbnail_match_candidates | Internal matching suggestions and review evidence. | exercise_catalog_item_id, free_exercise_db_item_id, score, conflicts jsonb, reason, model, prompt_version, created_at. |
ymove_media_access_events | Append-only media access ledger for preflight caps, audits, and plan decisions. | exercise_catalog_item_id, ymove_exercise_id, actor_user_id, surface, accessed_at, video_duration_secs, counted_as_new_unique, provider_warning. |
ymove_usage_snapshots | YMove /usage snapshots for reconciliation. | provider_integration_id, monthly_exercises_used, monthly_exercise_limit, video_minutes_used, video_minutes_limit, captured_at. |
API Contracts
Frontend clients call CoachMe only. YMove credentials and provider response handling stay server-side.
| Endpoint | Purpose | Notes |
|---|---|---|
GET /api/v1/workspaces/{workspaceId}/exercise-library/search | Return local catalog search results. | Includes local thumbnailAssetUrl when an approved mapping exists. Does not trigger YMove media calls. When source=provider, results are limited to YMove-backed catalog items; custom exercises are handled by the generic Exercise Library plan. |
GET /api/v1/workspaces/{workspaceId}/exercise-library/exercises/{exerciseId} | Return normalized exercise detail. | Reads local cached metadata and approved local thumbnail. Can refresh metadata without media fields when stale. |
POST /api/v1/workspaces/{workspaceId}/exercise-library/exercises/{exerciseId}/media-session | Create a runtime video/demo media session. | Runs local quota guard, fetches fresh YMove media fields if allowed, and returns a short-lived media DTO. |
GET /api/v1/admin/exercise-library/thumbnail-matches | List mapping candidates needing review. | Filter by status, score band, conflict flag, muscle group, equipment, or missing mapping. |
PATCH /api/v1/admin/exercise-library/thumbnail-matches/{candidateId} | Approve, reject, or replace a mapping candidate. | Writes an approved runtime mapping or a rejected/unmatched audit state. |
GET /api/v1/admin/exercise-library/ymove-usage | Show local counters and latest YMove usage snapshot. | Used to tune internal plan caps before public testing. |
Jobs And Operational Controls
Most work is background import, sync, and review preparation. Runtime media access stays synchronous with a fast preflight.
Scheduled Jobs
ymove-catalog-bootstrap: imports all browse-mode exercises with media disabled.ymove-catalog-refresh: refreshes changed metadata, taxonomy, and content hashes.free-exercise-db-import: imports the public-domain dataset and copies images to local storage.thumbnail-match-generate: computes deterministic candidates and queues GPT ranking for ambiguous rows.ymove-usage-reconcile: stores YMove/usagesnapshots and compares them to local media events.
Admin Controls
- Plan settings: unique exercise cap, video-minute cap, warning threshold, hard-stop threshold, and environment override.
- Mapping review: approve, reject, mark unmatched, replace image, and bulk-accept safe high-confidence rows.
- Provider health: last sync, auth status, rate-limit errors, monthly cap warnings, and stale catalog age.
- Import provenance: source commit/version, image count, mapping coverage, and unresolved conflicts.
Test Scenarios
Tests should prove that search is local, thumbnails are local, and media calls are controlled.
Required Tests
- Catalog sync calls YMove with
includeVideos=falseand does not persist signed media fields. - Search returns approved
free-exercise-dbthumbnail assets without calling YMove media endpoints. - Unmatched search results show placeholders and remain selectable when metadata is valid.
- Media session blocks before YMove call when local rolling 30-day unique exercise cap is reached.
- Media session records a new access event when a previously unseen exercise is fetched with video fields.
- Expired or failed signed media URL retries fetch fresh exercise media once.
- Program snapshots render after thumbnail mappings are changed or removed.
Review Quality Checks
- High-confidence mapping cannot auto-approve when equipment conflicts are present.
- Manual approval replaces confidence with a runtime
APPROVEDmapping status. - Rejected mappings do not reappear as new suggestions without a prompt or normalization version change.
- Import report shows coverage percentage by muscle group, equipment, and exercise type.
External References
Checked for planning context in June 2026. Re-verify before implementation if vendor docs change.