Overview
Implement a Hevy CSV to openweight converter as part of the converter architecture (#73).
Hevy is the second-most popular strength training app and has the richest CSV export of any competitor — it includes RPE, set types, supersets, and exercise notes. This makes it an excellent second converter to validate the architecture, exercising code paths that Strong's simpler format does not.
Hevy CSV Format
Known columns
| Column |
Type |
Maps to |
Notes |
title |
string |
WorkoutLog.name |
Workout name |
start_time |
ISO 8601 datetime |
WorkoutLog.date |
Workout start time |
end_time |
ISO 8601 datetime |
(derive durationSeconds) |
Workout end time |
description |
string |
WorkoutLog.notes |
Workout-level notes |
exercise_title |
string |
ExerciseLog.exercise.name |
Exercise name |
superset_id |
integer or empty |
ExerciseLog.supersetId |
Groups exercises into supersets |
exercise_notes |
string |
ExerciseLog.notes |
Per-exercise notes |
set_index |
integer |
SetLog ordering |
1-based set order within exercise |
set_type |
string |
SetLog.type |
See mapping below |
weight_lbs |
number |
SetLog.weight + unit conversion |
Always in lbs regardless of user setting |
reps |
integer |
SetLog.reps |
Rep count |
distance_miles |
number |
SetLog.distance + unit conversion |
Always in miles |
duration_seconds |
integer |
SetLog.durationSeconds |
For timed exercises |
rpe |
number |
SetLog.rpe |
0-10 scale |
Set type mapping
| Hevy value |
openweight SetLog.type |
Normal |
"working" |
Warm Up |
"warmup" |
Failure |
"failure" |
Drop Set |
"dropset" |
Known quirks
- Weight is always exported in lbs regardless of the user's in-app unit preference. Converter should offer
--unit kg to convert to kg on output.
- Distance is always in miles.
superset_id is empty string (not null) when not in a superset.
end_time minus start_time gives workout duration.
- Hevy can also import Strong CSV format, so its format is partially influenced by Strong's.
Implementation
Hevy-specific transformer (tools/converters/src/converters/hevy.ts)
const HEVY_COLUMNS: ColumnMap = {
"title": "workoutName",
"start_time": "date",
"end_time": "endTime",
"description": "workoutNotes",
"exercise_title": "exerciseName",
"superset_id": "supersetId",
"exercise_notes": "exerciseNotes",
"set_index": "setOrder",
"set_type": "setType",
"weight_lbs": "weight",
"reps": "reps",
"distance_miles": "distance",
"duration_seconds": "durationSeconds",
"rpe": "rpe",
};
What Hevy exercises that Strong does not
- Superset grouping (
supersetId mapping)
- RPE (direct mapping, no conversion needed)
- Set types (4 types vs Strong's none)
- Unit conversion (lbs-only export needs kg option)
- Duration calculation (end_time - start_time)
- Distance conversion (miles to m/km/ft/mi/yd)
Conversion report specifics
- Report should note that weights were converted from lbs if
--unit kg was used
- Report should note distance conversion from miles
- Report should flag any unrecognized set types
Test Plan
- Fixture-based tests with sample Hevy CSV data
- Verify superset grouping produces correct
supersetId values
- Verify RPE mapping
- Verify set type mapping for all 4 types
- Verify unit conversion (lbs to kg)
- Verify duration calculation from start/end times
- Verify distance conversion
- Roundtrip: converted output passes
validateWorkoutLog()
- Edge cases: workouts with no supersets, exercises with no RPE, timed-only exercises
Depends On
Part Of
Overview
Implement a Hevy CSV to openweight converter as part of the converter architecture (#73).
Hevy is the second-most popular strength training app and has the richest CSV export of any competitor — it includes RPE, set types, supersets, and exercise notes. This makes it an excellent second converter to validate the architecture, exercising code paths that Strong's simpler format does not.
Hevy CSV Format
Known columns
titleWorkoutLog.namestart_timeWorkoutLog.dateend_timedurationSeconds)descriptionWorkoutLog.notesexercise_titleExerciseLog.exercise.namesuperset_idExerciseLog.supersetIdexercise_notesExerciseLog.notesset_indexSetLogorderingset_typeSetLog.typeweight_lbsSetLog.weight+ unit conversionrepsSetLog.repsdistance_milesSetLog.distance+ unit conversionduration_secondsSetLog.durationSecondsrpeSetLog.rpeSet type mapping
SetLog.typeNormal"working"Warm Up"warmup"Failure"failure"Drop Set"dropset"Known quirks
--unit kgto convert to kg on output.superset_idis empty string (not null) when not in a superset.end_timeminusstart_timegives workout duration.Implementation
Hevy-specific transformer (
tools/converters/src/converters/hevy.ts)What Hevy exercises that Strong does not
supersetIdmapping)Conversion report specifics
--unit kgwas usedTest Plan
supersetIdvaluesvalidateWorkoutLog()Depends On
Part Of