Fitness Apps: Workout Cards & Progress Images

Fitness Apps: Workout Cards & Progress Images

Every fitness app tracks workouts. Very few turn that data into workout cards worth sharing.

Strava figured this out early. Those orange-and-white activity cards you see flooding Instagram every Sunday morning? They drive massive organic growth. When a runner posts their 10K stats, every follower who sees it thinks about their own fitness, and some of them download Strava.

But most fitness apps just show raw numbers in their UI. No shareable workout card. No branded image. No viral loop. The data exists. The design is the missing piece.

I've helped two fitness startups build this exact feature. And the pattern is always the same: generate workout summary cards, progress milestones, and achievement graphics that your users will actually want to share. Here's how.

Why shareable fitness images matterWhy Shareable Fitness Images Matter

Fitness is inherently social. People want to show their progress. They want accountability from their friends. They want to celebrate PRs.

BehaviorStat
Users who share workouts retain better2x higher 30-day retention
Instagram Stories with fitness content1.5B+ posts under #fitness
Strava activity shares per monthTens of millions globally
Users who prefer image-based sharing78% over text-only posts

If your app doesn't give users a polished image to share, they'll screenshot your UI. That screenshot has no branding, no download link, no call to action. You're losing free marketing. New to image APIs? Our what is an image API explainer covers the basics.

Types of fitness images to generateTypes of Fitness Images to Generate

Workout summary cardsWorkout Summary Cards

The core format. Generated after every workout with the session's stats.

Dynamic fields:

  • User name and profile photo
  • Workout type (Running, Cycling, Weightlifting, Yoga, etc.)
  • Duration
  • Calories burned
  • Primary metric (distance for runs, volume for lifts, poses for yoga)
  • Secondary metrics (pace, heart rate, sets/reps)
  • Date and time
  • Personal record flag (if applicable)

Progress milestone imagesProgress Milestone Images

Triggered at key moments in a user's journey.

  • "First workout completed!"
  • "10 workouts this month"
  • "100-day streak 🔥"
  • "Lost 10 lbs since starting"
  • "New 5K personal record: 22:14"

These are the most shareable images. People love celebrating milestones.

Weeklymonthly recapsWeekly/Monthly Recaps

A summary of the user's activity over a period.

  • Total workouts, duration, calories
  • Comparison to previous period
  • Most active day
  • Longest workout
  • Streak count

Challenge completion badgesChallenge Completion Badges

For apps with challenges or programs:

  • "Completed 30-Day Ab Challenge"
  • "Couch to 5K: Finished!"
  • "January Running Challenge: 100 miles"

Designing workout card templatesDesigning Workout Card Templates

Template by workout typeTemplate by Workout Type

Different activities emphasize different metrics. Create a template per category.

Workout TypeKey MetricsTemplate Style
RunningDistance, pace, elevation, route mapEnergetic, outdoor feel
CyclingDistance, speed, elevation, powerDynamic, speed-focused
WeightliftingVolume, sets, reps, PRs brokenStrong, bold typography
YogaDuration, poses, caloriesCalm, minimal design
HIITDuration, calories, heart rate zonesIntense, high-contrast
SwimmingDistance, laps, stroke typeBlue tones, clean

Create each template in Imejis.io with dynamic layers for the metrics that matter for that activity type.

Design principles for fitness cardsDesign Principles for Fitness Cards

  • Bold, readable stats: The numbers are the hero. Make them big.
  • Your app's branding: Logo, colors, app name, visible but not overpowering.
  • Dark backgrounds work well: Fitness cards look better with dark themes (and they're easier to read on phone screens).
  • Size for Stories: 1080x1920px is the primary share format (Instagram/Facebook Stories).
  • Include a subtle CTA: Small text like "Tracked with [YourApp]" with a download link.

Generating workout cards via apiGenerating Workout Cards via API

When a user finishes a workout, generate their card:

curl -X POST 'https://render.imejis.io/v1/RUNNING_CARD_TEMPLATE' \
  -H 'dma-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "user_name": {
      "text": "Sarah M."
    },
    "user_avatar": {
      "image": "https://yourapp.com/avatars/user-5678.jpg"
    },
    "workout_type": {
      "text": "Morning Run"
    },
    "distance": {
      "text": "5.2 km"
    },
    "duration": {
      "text": "28:14"
    },
    "pace": {
      "text": "5:26 /km"
    },
    "calories": {
      "text": "412 cal"
    },
    "date": {
      "text": "Apr 13, 2026"
    },
    "pr_badge": {
      "visible": true
    }
  }'

Card generated in under 2 seconds. Show it to the user with a "Share to Instagram" button. For a step-by-step intro to making your first API call, see how to generate images with an API.

Handling multiple workout typesHandling Multiple Workout Types

Route the generation to the right template based on workout type:

const workoutTemplates = {
  running: "RUNNING_CARD_TEMPLATE",
  cycling: "CYCLING_CARD_TEMPLATE",
  weightlifting: "LIFTING_CARD_TEMPLATE",
  yoga: "YOGA_CARD_TEMPLATE",
  hiit: "HIIT_CARD_TEMPLATE",
  swimming: "SWIMMING_CARD_TEMPLATE",
}
 
async function generateWorkoutCard(workout, user) {
  const templateId =
    workoutTemplates[workout.type] || "DEFAULT_WORKOUT_TEMPLATE"
 
  const data = {
    user_name: { text: user.displayName },
    user_avatar: { image: user.avatarUrl },
    workout_type: { text: workout.label },
    duration: { text: formatDuration(workout.durationSeconds) },
    calories: { text: `${workout.calories} cal` },
    date: { text: formatDate(workout.completedAt) },
  }
 
  // Add type-specific metrics
  if (workout.type === "running" || workout.type === "cycling") {
    data.distance = { text: `${workout.distanceKm} km` }
    data.pace = { text: formatPace(workout.pacePerKm) }
  }
 
  if (workout.type === "weightlifting") {
    data.total_volume = {
      text: `${workout.totalVolumeLbs.toLocaleString()} lbs`,
    }
    data.sets_completed = { text: `${workout.setsCompleted} sets` }
  }
 
  // Show PR badge if personal record was broken
  if (workout.isPersonalRecord) {
    data.pr_badge = { visible: true }
  }
 
  return await generateImage(templateId, data)
}

Progress milestone cardsProgress Milestone Cards

Milestone images are triggered by events, not workouts. Set up listeners for key moments:

async function checkMilestones(userId) {
  const stats = await getUserStats(userId)
  const milestones = []
 
  if (stats.totalWorkouts === 1) milestones.push("first_workout")
  if (stats.totalWorkouts === 100) milestones.push("100_workouts")
  if (stats.currentStreak === 30) milestones.push("30_day_streak")
  if (stats.currentStreak === 100) milestones.push("100_day_streak")
  if (stats.newPersonalRecord) milestones.push("new_pr")
 
  for (const milestone of milestones) {
    const card = await generateMilestoneCard(userId, milestone)
    await notifyUser(userId, card)
  }
}

These milestone moments are the peak sharing opportunities. Make the images irresistible.

Weekly recap imagesWeekly Recap Images

Generate a weekly summary every Sunday (or whenever makes sense for your user base):

Template fields:

  • User name and avatar
  • Total workouts this week
  • Total duration
  • Total calories
  • Total distance (if applicable)
  • Comparison to last week (up/down arrows with percentages)
  • Streak count
  • "Best day" highlight

Run a cron job to generate recaps for all active users:

# Weekly recap generation - runs every Sunday at 8 AM
def generate_weekly_recaps():
    active_users = get_active_users_this_week()
 
    for user in active_users:
        stats = get_weekly_stats(user['id'])
        last_week = get_weekly_stats(user['id'], weeks_ago=1)
 
        image = generate_image('WEEKLY_RECAP_TEMPLATE', {
            'user_name': {'text': user['display_name']},
            'workouts': {'text': str(stats['count'])},
            'duration': {'text': format_duration(stats['total_duration'])},
            'calories': {'text': f"{stats['total_calories']:,}"},
            'vs_last_week': {'text': calc_change(stats, last_week)},
            'streak': {'text': f"{stats['streak']} days"},
        })
 
        send_push_notification(user['id'], image, "Your weekly recap is ready!")

Mobile integrationMobile Integration

Ios swiftiOS (Swift)

func generateWorkoutCard(workout: Workout, completion: @escaping (UIImage?) -> Void) {
    let url = URL(string: "https://render.imejis.io/v1/\(workout.templateId)")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("YOUR_API_KEY", forHTTPHeaderField: "dma-api-key")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
 
    let body: [String: Any] = [
        "user_name": ["text": workout.userName],
        "distance": ["text": "\(workout.distanceKm) km"],
        "duration": ["text": workout.formattedDuration],
        "calories": ["text": "\(workout.calories) cal"]
    ]
    request.httpBody = try? JSONSerialization.data(withJSONObject: body)
 
    URLSession.shared.dataTask(with: request) { data, _, _ in
        if let data = data, let image = UIImage(data: data) {
            completion(image)
        }
    }.resume()
}

React nativeReact Native

import Share from "react-native-share"
 
async function shareWorkoutCard(workout) {
  const imageUrl = await generateWorkoutCard(workout)
 
  await Share.open({
    url: imageUrl,
    type: "image/png",
    social: Share.Social.INSTAGRAM_STORIES,
  })
}

This same approach works for any mobile app that needs dynamic image generation.

The sharing loopThe Sharing Loop

Here's why this matters for growth:

  1. User completes workout → branded card generated
  2. User shares to Instagram Stories → their followers see your branding
  3. Follower asks "what app is that?" → organic download
  4. New user completes their first workout → shares their card
  5. Repeat

Every share is an ad you didn't pay for. Strava, Nike Run Club, and Peloton all figured this out. The fitness apps that grow fastest are the ones that make sharing effortless and visually appealing.

For more on building automated social sharing workflows, check our social media image automation guide.

FaqFAQ

What data should a workout summary card includeWhat data should a workout summary card include?

The essentials: workout type (run, lift, HIIT), duration, calories burned, distance or reps, date, and the user's name. Optional extras: heart rate zones, personal records broken, streak count, and a map of the route for outdoor activities.

Can i generate workout cards in real time after a session endsCan I generate workout cards in real time after a session ends?

Yes. The API returns images in under 2 seconds. When a user finishes a workout, send their session data to the API and display the generated card immediately. Users can share it before they've even left the gym.

How do fitness apps handle different workout typesHow do fitness apps handle different workout types?

Create separate templates for each workout category: running, cycling, weightlifting, yoga, HIIT. Each template highlights the metrics that matter for that activity. Running shows distance and pace. Weightlifting shows volume and PRs. The API picks the right template based on workout type.

Do shareable workout images actually drive app downloadsDo shareable workout images actually drive app downloads?

Yes. Strava reports that shared activities drive significant organic growth. When users post branded workout cards to Instagram Stories or Twitter, their followers see your app's branding and download link. It's word-of-mouth marketing at scale.

How much does workout image generation costHow much does workout image generation cost?

Imejis.io starts at $14.99/month for 1,000 images. A fitness app with 2,000 active users generating 3 workout cards per week needs about 24,000 images/month. The Pro tier at $24.99/month covers 10,000, and Enterprise handles higher volumes.

Turn every workout into a billboardTurn Every Workout Into a Billboard

Your users are already proud of their workouts. Give them a polished, branded image to prove it.

Every shared workout card puts your app in front of potential users. Every milestone image celebrates your user and promotes your brand. Every weekly recap keeps users engaged and coming back.

Design the templates. Wire up the generation. Let your users do the marketing for you. For a full cost breakdown across providers, see our image generation API pricing comparison.

Get started with Imejis.io →