Skip to main content

Overview

Track Better uses a streak system to motivate consistent workout habits. Your current streak is prominently displayed in the app header and settings page, providing immediate feedback on your consistency.
Streaks count consecutive days where you’ve logged at least one workout. Complete all exercises in a day’s workout to keep your streak alive.

How Streaks Work

The streak system counts backward from today, checking for completed workouts:
1

Start from today

The algorithm begins with the current date at midnight.
2

Check each day

It looks back day by day to see if workout data exists for that date.
3

Stop at first gap

The streak stops at the first day without logged exercises.
4

Display count

The final count appears as ”🔥 X day streak” in the header.

Streak Calculation Logic

The core calculation is implemented in App.jsx:46-65:
const calculateCurrentStreak = () => {
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  let streak = 0;
  let currentDate = new Date(today);

  for (let i = 0; i < 365; i++) {
    const dateKeyCheck = getLocalDateKey(currentDate);

    if (completedExercises[dateKeyCheck]) {
      streak++;
      currentDate.setDate(currentDate.getDate() - 1);
    } else {
      break;
    }
  }

  return streak;
};
The loop has a maximum of 365 iterations to prevent infinite loops while allowing for year-long streaks. It will exit early (via break) as soon as it finds a day without logged exercises, so it typically only runs a few iterations.

Key Implementation Details

Midnight Reset

setHours(0, 0, 0, 0) ensures calculations start at the beginning of the day, avoiding time-of-day issues.

Date Key Format

Uses YYYY-MM-DD format (e.g., “2026-03-07”) for consistent date lookups in localStorage.

Backward Iteration

Counts backward from today using currentDate.setDate(currentDate.getDate() - 1).

Early Exit

Breaks immediately upon finding a missing day, making the algorithm efficient.

Viewing Your Streak

Header Display

Your current streak appears in the app header: From App.jsx:214-219:
{currentStreak > 0 && (
  <p className="flex items-center gap-1 text-sm font-semibold text-orange-600 dark:text-orange-400">
    🔥 {currentStreak} day streak
  </p>
)}
The streak counter only appears when currentStreak > 0. If you haven’t logged any workouts, it won’t display.

Settings Page Display

The Settings tab shows your streak in a dedicated card: From SettingsTab.jsx:328-333:
<div className="rounded-lg border border-orange-200 bg-orange-50/70 p-3 dark:border-orange-800 dark:bg-zinc-800">
  <p className="text-xs text-slate-600 dark:text-zinc-400">🔥 Current Streak</p>
  <p className="text-2xl font-bold text-orange-600 dark:text-orange-400">
    {summary.currentStreak} day{summary.currentStreak !== 1 ? "s" : ""}
  </p>
</div>

What Counts Toward a Streak?

A day counts toward your streak if: At least one set is logged - Any exercise with logged sets counts ✅ Data exists in localStorage - The date key exists in completedExercisesNo gap in consecutive days - Every day between your streak must have logs
Even partial workouts count toward streaks. You don’t need to complete all exercises in a day to maintain your streak.

Storage Structure

The streak calculation checks for keys in this structure:
{
  "completedExercises": {
    "2026-03-07": {
      "exercise-1": [
        { "reps": 12, "loggedAt": "2026-03-07T10:30:00.000Z" }
      ]
    },
    "2026-03-06": {
      "exercise-2": [
        { "reps": 10, "loggedAt": "2026-03-06T11:00:00.000Z" }
      ]
    }
  }
}
If a date key exists with at least one exercise logged, it counts toward the streak.

Maintaining Your Streak

1

Log workouts daily

Complete at least one exercise every day. Even a single set counts.
2

Check your progress

View your streak in the header or Settings tab to stay motivated.
3

Don't reset by accident

Be careful with the “Reset Today’s Progress” button, as it can break your streak.
4

Plan for rest days

The app doesn’t account for scheduled rest days. Consider logging a light exercise to maintain your streak.
Set a daily reminder to log at least one set, even on light training days, to keep your streak alive.

Streak Reset Scenarios

Your streak will reset to 0 in these situations: Missed a day - No exercises logged for any date ❌ Hard reset - Using “Hard Reset All Data” in Settings ❌ Cleared localStorage - Manually clearing browser data ❌ Reset today before midnight - Deleting today’s logs ends your streak
The “Reset Today’s Progress” button will break your streak if you’ve already logged exercises for today and don’t re-log before midnight.

Longest Streak

Currently, the app only tracks your current streak. It does not calculate or store:
  • Longest streak ever
  • Total workout days (non-consecutive)
  • Average streak length
However, these could be added by analyzing the completedExercises data:
// Example: Calculate longest streak (not implemented)
const calculateLongestStreak = (completedExercises) => {
  const dates = Object.keys(completedExercises).sort();
  let longest = 0;
  let current = 0;
  
  for (let i = 0; i < dates.length; i++) {
    const today = new Date(dates[i]);
    const yesterday = new Date(dates[i - 1]);
    const dayDiff = (today - yesterday) / (1000 * 60 * 60 * 24);
    
    if (i === 0 || dayDiff === 1) {
      current++;
      longest = Math.max(longest, current);
    } else {
      current = 1;
    }
  }
  
  return longest;
};

Statistics in Settings

The Settings tab calculates and displays comprehensive statistics:

Summary Calculation

From SettingsTab.jsx:107-129:
const generateSummary = () => {
  let totalExercisesLogged = 0;
  let totalSets = 0;
  let completedDays = 0;

  Object.values(completedExercises).forEach((dayData) => {
    Object.values(dayData).forEach((exerciseLogs) => {
      if (Array.isArray(exerciseLogs)) {
        totalExercisesLogged += exerciseLogs.length;
        totalSets += exerciseLogs.length;
      }
    });
  });

  completedDays = Object.keys(completedExercises).length;
  const currentStreak = calculateCurrentStreak();

  return {
    totalDaysTracked: completedDays,
    totalSetsCompleted: totalSets,
    currentStreak: currentStreak,
  };
};

Displayed Metrics

Current Streak

Consecutive days with logged workouts.

Total Days Logged

Total number of dates with workout data (non-consecutive).

Sets Completed

All-time count of logged sets across all workouts.

Exporting Streak Data

When you export your data from Settings, it includes:
{
  "userName": "John Doe",
  "exportDate": "2026-03-07T12:00:00.000Z",
  "completedExercises": {
    // All workout logs...
  },
  "summary": {
    "totalDaysTracked": 45,
    "totalSetsCompleted": 234,
    "currentStreak": 7
  }
}
The summary object includes your current streak at the time of export.
Importing data from another device will restore your streak if the data includes consecutive days up to today.

Timezone Considerations

The app uses local device time for all calculations:
function getLocalDateKey(date = new Date()) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
}
Since the app uses new Date() without timezone conversion, it will use your device’s local time. If you log a workout at 11 PM in New York, then fly to London (5 hours ahead) and open the app at 3 AM local time (10 PM New York time), the app will consider it the same day in New York but the next day in London.This could potentially break your streak if you don’t log anything on the “London day.” For most users, this isn’t an issue since they stay in the same timezone.

Motivation and Gamification

Streaks are a powerful motivational tool:

Visual Feedback

The fire emoji 🔥 creates positive association with consistency.

Loss Aversion

Users don’t want to “lose” their streak, encouraging daily logging.

Progress Tracking

Seeing the number increase provides tangible progress feedback.

Social Proof

When sharing the app, users can show off their streak numbers.
Share your streak milestones (7 days, 30 days, 100 days) on social media to stay accountable and inspire others!

Build docs developers (and LLMs) love