Skip to main content

Overview

Exercise storage functions manage the user’s exercise library. Each exercise has a unique ID, a name, and optional notes. On first load, exercises are initialized from the default Rippler program.

Storage Key

@rippler/exercises
string
Stores the JSON-serialized array of Exercise objects

Functions

getExercises

Retrieves all exercises from storage. If no exercises exist, initializes with default exercises from the Rippler program.
async function getExercises(): Promise<Exercise[]>
return
Exercise[]
Array of all exercises, or empty array if an error occurs
This function automatically initializes exercises from ripplerProgram.exercises on first run, creating IDs and saving them to storage.
Example
import { getExercises } from '@/lib/storage';

const exercises = await getExercises();
console.log(exercises);
// [
//   { id: 'ex_0', name: 'Squat' },
//   { id: 'ex_1', name: 'Bench Press' },
//   { id: 'ex_2', name: 'Deadlift', notes: 'Focus on form' }
// ]
Source Code Reference See implementation at lib/storage.ts:13-31

saveExercises

Saves the complete array of exercises to storage, overwriting existing data.
async function saveExercises(exercises: Exercise[]): Promise<void>
exercises
Exercise[]
required
Complete array of exercises to save
This function overwrites all existing exercises. Ensure you’ve loaded current exercises with getExercises() before modifying and saving.
Example
import { getExercises, saveExercises } from '@/lib/storage';

// Load current exercises
const exercises = await getExercises();

// Modify array
exercises[0].notes = 'Updated notes';

// Save back to storage
await saveExercises(exercises);
Source Code Reference See implementation at lib/storage.ts:33-39

addExercise

Creates a new exercise and adds it to storage. Generates a unique timestamp-based ID.
async function addExercise(name: string, notes?: string): Promise<Exercise>
name
string
required
The name of the exercise (e.g., “Squat”, “Bench Press”)
notes
string
Optional notes about the exercise (form cues, variations, etc.)
return
Exercise
The newly created exercise object with generated ID
Example
import { addExercise } from '@/lib/storage';

const newExercise = await addExercise(
  'Romanian Deadlift',
  'Keep knees slightly bent'
);

console.log(newExercise);
// {
//   id: 'ex_1234567890',
//   name: 'Romanian Deadlift',
//   notes: 'Keep knees slightly bent'
// }
ID Generation Exercise IDs are generated using the pattern ex_${Date.now()}, ensuring uniqueness based on creation timestamp. Source Code Reference See implementation at lib/storage.ts:41-51

updateExercise

Updates specific fields of an existing exercise by ID. Uses partial updates to modify only the fields you specify.
async function updateExercise(
  id: string,
  updates: Partial<Exercise>
): Promise<void>
id
string
required
The unique ID of the exercise to update
updates
Partial<Exercise>
required
Object containing the fields to update (name, notes, etc.)
If the exercise ID is not found, the function completes silently without throwing an error.
Example
import { updateExercise } from '@/lib/storage';

// Update just the name
await updateExercise('ex_1234567890', {
  name: 'Front Squat'
});

// Update multiple fields
await updateExercise('ex_1234567890', {
  name: 'Front Squat',
  notes: 'Elbows high, core tight'
});
Source Code Reference See implementation at lib/storage.ts:53-63

deleteExercise

Removes an exercise from storage by ID.
async function deleteExercise(id: string): Promise<void>
id
string
required
The unique ID of the exercise to delete
This operation cannot be undone. Consider warning users before deletion, especially if the exercise is referenced in logged workouts or goal weights.
Example
import { deleteExercise } from '@/lib/storage';

await deleteExercise('ex_1234567890');
Source Code Reference See implementation at lib/storage.ts:65-69

Data Type

export interface Exercise {
  id: string;        // Unique identifier (e.g., 'ex_1234567890')
  name: string;      // Exercise name (e.g., 'Squat')
  notes?: string;    // Optional notes about form, variations, etc.
}

Common Patterns

Loading and Displaying Exercises

import { getExercises } from '@/lib/storage';
import { FlatList, Text } from 'react-native';

function ExerciseList() {
  const [exercises, setExercises] = useState<Exercise[]>([]);

  useEffect(() => {
    loadExercises();
  }, []);

  async function loadExercises() {
    const data = await getExercises();
    setExercises(data);
  }

  return (
    <FlatList
      data={exercises}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => <Text>{item.name}</Text>}
    />
  );
}

Creating an Exercise Form

import { addExercise } from '@/lib/storage';
import { useState } from 'react';

function AddExerciseForm({ onComplete }: { onComplete: () => void }) {
  const [name, setName] = useState('');
  const [notes, setNotes] = useState('');

  async function handleSubmit() {
    if (!name.trim()) return;
    
    await addExercise(name, notes || undefined);
    setName('');
    setNotes('');
    onComplete();
  }

  return (
    <View>
      <TextInput
        placeholder="Exercise name"
        value={name}
        onChangeText={setName}
      />
      <TextInput
        placeholder="Notes (optional)"
        value={notes}
        onChangeText={setNotes}
      />
      <Button title="Add Exercise" onPress={handleSubmit} />
    </View>
  );
}

Batch Updating Multiple Exercises

import { getExercises, saveExercises } from '@/lib/storage';

async function addNotesToAllSquats() {
  // Load all exercises
  const exercises = await getExercises();
  
  // Modify in memory
  const updated = exercises.map(ex => {
    if (ex.name.toLowerCase().includes('squat')) {
      return { ...ex, notes: 'Drive through heels' };
    }
    return ex;
  });
  
  // Single save operation
  await saveExercises(updated);
}

getGoalWeight

Get goal weight for an exercise by name

getLoggedWorkouts

View exercises logged in workouts

Build docs developers (and LLMs) love