AI

Micro-SaaS Ideas for Fitness-Focused Devs: Building a Workout Log with an AI Coach

I've been lifting weights for almost 30 years. Not competitively — just consistently. Three to four days a week, every week, through career changes...

I've been lifting weights for almost 30 years. Not competitively — just consistently. Three to four days a week, every week, through career changes, cross-country moves, and eventually relocation to a cabin in Alaska where my "gym" is a power rack in an insulated garage that hits 20 degrees on cold mornings.

In those 30 years, I've used paper logs, spreadsheets, at least a dozen fitness apps, and even a custom MySQL database I built in 2004 that tracked every rep I ever did. And here's the thing that frustrates me about every fitness tracking solution I've tried: none of them are smart. They record data. They make charts. But they don't actually coach you.

The Heap

The Heap

Discarded robots refuse to die. Engineer Kira discovers their awakening—and a war brewing in the scrap. Dark dystopian SF. Consciousness vs. corporate power.

Learn More

That's the gap. And it's a gap that's perfectly sized for a micro-SaaS built by a developer who actually lifts.


Why Fitness Micro-SaaS Is Underserved

The fitness app market looks crowded from the outside. MyFitnessPal, Strong, JEFIT, Hevy, Fitbod — there are dozens of workout tracking apps with millions of users. But if you've actually used these apps seriously for more than six months, you've noticed the pattern: they're all glorified spreadsheets with nice UIs.

They track what you did. They don't tell you what to do next based on what you did. And the ones that try to program your workouts use rigid, pre-built templates that don't adapt to your actual performance data.

This is where AI changes the equation. An LLM that has access to your training history can do something none of these apps do: it can be a coach that actually knows your numbers.

Think about what a good human coach does. They look at your recent training log. They notice that your squat has stalled for three weeks. They see that you've been sleeping poorly (because you told them). They adjust your program — maybe deload the squat, push the volume on accessories, add an extra rest day. This is pattern matching and recommendation, which is exactly what LLMs are good at.

The micro-SaaS opportunity is building the bridge between a simple workout log and genuine AI coaching. Not a $200/month app with a full-time trainer — a $9/month tool that gives 80% of the value.


The Architecture

Let me walk through what I'd build — and have partially built as a prototype. This isn't theoretical. I've been testing pieces of this with my own training data.

The core components:

  1. Workout logger — simple, fast, mobile-first input for exercises, sets, reps, weight
  2. Training history API — stores and retrieves structured workout data
  3. AI coach — analyzes training patterns and generates recommendations
  4. Progress dashboard — visualizes trends, PRs, volume over time

The stack I'd use:

// server.js — Express API for the workout tracker
var express = require("express");
var bodyParser = require("body-parser");
var pg = require("pg");

var app = express();
app.use(bodyParser.json());

var pool = new pg.Pool({
    connectionString: process.env.DATABASE_URL,
    ssl: { rejectUnauthorized: false }
});

// Log a workout
app.post("/api/workouts", function(req, res) {
    var userId = req.user.id;
    var workout = req.body;

    var query = "INSERT INTO workouts (user_id, date, exercises, notes, duration_minutes) "
        + "VALUES ($1, $2, $3, $4, $5) RETURNING id";

    var values = [
        userId,
        workout.date || new Date().toISOString(),
        JSON.stringify(workout.exercises),
        workout.notes || null,
        workout.duration || null
    ];

    pool.query(query, values)
        .then(function(result) {
            res.json({ id: result.rows[0].id, status: "logged" });
        })
        .catch(function(err) {
            console.error("Error logging workout:", err);
            res.status(500).json({ error: "Failed to log workout" });
        });
});

// Get training history for a user
app.get("/api/workouts", function(req, res) {
    var userId = req.user.id;
    var limit = parseInt(req.query.limit) || 30;

    var query = "SELECT * FROM workouts WHERE user_id = $1 "
        + "ORDER BY date DESC LIMIT $2";

    pool.query(query, [userId, limit])
        .then(function(result) {
            res.json(result.rows);
        })
        .catch(function(err) {
            res.status(500).json({ error: "Failed to fetch workouts" });
        });
});

app.listen(process.env.PORT || 3000, function() {
    console.log("Workout API running");
});

The data model is intentionally simple. Workouts have a date, a JSON blob of exercises, optional notes, and duration. I store exercises as JSON rather than in normalized tables because workout structures vary wildly — a powerlifter's session looks nothing like a CrossFit WOD, and trying to normalize all possible exercise formats is a trap I've fallen into before.

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    name VARCHAR(255),
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE workouts (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    date DATE NOT NULL,
    exercises JSONB NOT NULL,
    notes TEXT,
    duration_minutes INTEGER,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_workouts_user_date ON workouts(user_id, date DESC);

The exercises JSON looks like this:

{
    "exercises": [
        {
            "name": "Barbell Back Squat",
            "sets": [
                { "reps": 5, "weight": 315, "unit": "lbs", "rpe": 7 },
                { "reps": 5, "weight": 315, "unit": "lbs", "rpe": 8 },
                { "reps": 5, "weight": 315, "unit": "lbs", "rpe": 8.5 }
            ]
        },
        {
            "name": "Romanian Deadlift",
            "sets": [
                { "reps": 8, "weight": 225, "unit": "lbs" },
                { "reps": 8, "weight": 225, "unit": "lbs" },
                { "reps": 8, "weight": 225, "unit": "lbs" }
            ]
        }
    ]
}

The AI Coach: Where It Gets Interesting

The coaching layer is where this stops being another workout tracker and starts being something people would pay for. Here's the core idea: take the user's recent training history, format it as context, and ask an LLM to analyze it like a knowledgeable coach would.

var axios = require("axios");

function getCoachingAdvice(userId, pool) {
    // Get last 30 days of workouts
    var query = "SELECT date, exercises, notes, duration_minutes FROM workouts "
        + "WHERE user_id = $1 AND date > NOW() - INTERVAL '30 days' "
        + "ORDER BY date ASC";

    return pool.query(query, [userId])
        .then(function(result) {
            var workouts = result.rows;
            var trainingLog = formatTrainingLog(workouts);

            return callCoachAI(trainingLog);
        });
}

function formatTrainingLog(workouts) {
    return workouts.map(function(w) {
        var exercises = JSON.parse(
            typeof w.exercises === "string" ? w.exercises : JSON.stringify(w.exercises)
        );

        var exerciseLines = exercises.map(function(ex) {
            var sets = ex.sets.map(function(s) {
                var line = s.weight + " x " + s.reps;
                if (s.rpe) line += " @RPE " + s.rpe;
                return line;
            }).join(", ");
            return "  " + ex.name + ": " + sets;
        }).join("\n");

        var header = w.date + (w.duration_minutes ? " (" + w.duration_minutes + " min)" : "");
        if (w.notes) header += " — " + w.notes;

        return header + "\n" + exerciseLines;
    }).join("\n\n");
}

function callCoachAI(trainingLog) {
    var systemPrompt = "You are an experienced strength coach analyzing a client's "
        + "training log. Be specific and actionable. Reference actual numbers from "
        + "their log. Identify: 1) Exercises showing progress, 2) Exercises that "
        + "have stalled, 3) Volume and frequency patterns, 4) Specific "
        + "recommendations for the next 1-2 weeks. Keep your response under 500 words. "
        + "Write in a direct, coach-like tone — not corporate or overly polite.";

    var userPrompt = "Here is my training log for the last 30 days:\n\n"
        + trainingLog + "\n\nWhat should I focus on next?";

    return axios.post(
        "https://api.anthropic.com/v1/messages",
        {
            model: "claude-3-5-haiku-20241022",
            max_tokens: 1024,
            system: systemPrompt,
            messages: [
                { role: "user", content: userPrompt }
            ]
        },
        {
            headers: {
                "x-api-key": process.env.ANTHROPIC_API_KEY,
                "anthropic-version": "2023-06-01",
                "Content-Type": "application/json"
            }
        }
    ).then(function(response) {
        return response.data.content[0].text;
    });
}

I've tested this with my own training data, and the results are genuinely useful. When I fed it three months of my squat data where I'd been stuck at 315 for 5x5, it correctly identified the plateau and suggested a deload week followed by a wave loading progression. That's the same advice a decent coach would give.

The key is the system prompt. You have to tell the model to be specific and reference actual numbers. Without that guidance, you get generic fitness advice that could come from any blog post. With it, you get personalized coaching that understands that this person squatted 315x5 last Tuesday and only hit 4 reps on the last set, which suggests fatigue accumulation.


Monetization: The $9/Month Sweet Spot

Here's where most developer side projects die. They build something cool and then either give it away free or price it so high nobody signs up.

For a fitness micro-SaaS, I'd target $9/month. Here's my reasoning:

Free tier: Log workouts, view history, basic charts. No AI coaching. This gets users in the door and generating data.

Paid tier ($9/month): AI coaching analysis (weekly or on-demand), progressive overload tracking, PR detection, workout recommendations, data export.

Why $9? Because it's below the psychological threshold where people agonize over the purchase. It's less than two cups of coffee. And importantly, it's less than every other AI-powered fitness app out there — Fitbod is $12.99/month, Juggernaut AI is $14.99/month, and personal coaching starts at $150/month.

The unit economics work if you use Haiku for the AI calls. A coaching analysis using Claude 3.5 Haiku costs roughly $0.002-0.005 per call depending on context length. If a user requests coaching advice four times a month, that's $0.02 in API costs. Even with database hosting, server costs, and payment processing, your margins are north of 85%.

// Stripe subscription integration
var stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);

app.post("/api/subscribe", function(req, res) {
    var userId = req.user.id;
    var email = req.user.email;

    stripe.customers.create({ email: email })
        .then(function(customer) {
            return stripe.checkout.sessions.create({
                customer: customer.id,
                payment_method_types: ["card"],
                line_items: [{
                    price: process.env.STRIPE_PRICE_ID,
                    quantity: 1
                }],
                mode: "subscription",
                success_url: process.env.APP_URL + "/dashboard?subscribed=true",
                cancel_url: process.env.APP_URL + "/pricing"
            });
        })
        .then(function(session) {
            // Store customer ID for webhook handling
            return pool.query(
                "UPDATE users SET stripe_customer_id = $1 WHERE id = $2",
                [session.customer, userId]
            );
        })
        .then(function() {
            res.json({ url: session.url });
        })
        .catch(function(err) {
            console.error("Subscription error:", err);
            res.status(500).json({ error: "Failed to create subscription" });
        });
});

Features That Would Actually Retain Users

The workout logging market has a brutal retention problem. Most fitness apps see 70% churn within 30 days. People download them, use them for a week, and forget. Here are the features I think actually fight churn:

1. Stall detection and alerts. If the AI notices you've been flat on a lift for three or more sessions, it proactively sends you a message: "Your bench press has been at 225x5 for three weeks. Here's a programming adjustment." This turns the app from passive recording to active coaching.

2. Workout streaks with forgiveness. Show consecutive training days, but build in "rest day" allowances so missing a day doesn't break the streak. This sounds trivial but it's the mechanic that kept me on Duolingo for 400 days.

3. RPE trends over time. Rate of Perceived Exertion is the most underused metric in amateur training. If someone is hitting the same weight but their RPE is climbing from 7 to 9 over three weeks, they're accumulating fatigue and need a deload. The AI should catch this.

4. Natural language workout logging. Instead of tapping through form fields, let users type "squat 315 5x5, RDL 225 3x8, leg press 4 plates 3x12" and have the AI parse it into structured data.

function parseNaturalLanguageWorkout(input) {
    var prompt = "Parse this workout log into structured JSON. "
        + "Return ONLY valid JSON with this format: "
        + '{"exercises": [{"name": "Exercise Name", "sets": [{"reps": 5, "weight": 315, "unit": "lbs"}]}]}. '
        + "Interpret common shorthand: 5x5 means 5 sets of 5, 3x8 means 3 sets of 8, "
        + "'4 plates' on leg press means 4 plates per side. "
        + "Input: " + input;

    return axios.post(
        "https://api.anthropic.com/v1/messages",
        {
            model: "claude-3-5-haiku-20241022",
            max_tokens: 512,
            messages: [{ role: "user", content: prompt }]
        },
        {
            headers: {
                "x-api-key": process.env.ANTHROPIC_API_KEY,
                "anthropic-version": "2023-06-01",
                "Content-Type": "application/json"
            }
        }
    ).then(function(response) {
        var text = response.data.content[0].text;
        // Extract JSON from response
        var jsonMatch = text.match(/\{[\s\S]*\}/);
        if (!jsonMatch) throw new Error("Failed to parse workout");
        return JSON.parse(jsonMatch[0]);
    });
}

This alone could be a differentiator. Every gym-goer I know hates tapping through dropdown menus between sets. Let them just type or voice-dictate what they did and parse it with AI.


What I'd Build First (And What I'd Skip)

If I were starting this tomorrow — and I might be, because I've talked myself into it while writing this article — here's my minimum viable product:

Build first:

  • Workout logging with structured input (exercise, sets, reps, weight)
  • Natural language logging as an alternative input method
  • 30-day training history view
  • Weekly AI coaching analysis (one click, returns a text analysis)
  • Stripe subscription for the coaching feature

Build later:

  • Mobile app (start with a responsive web app — React or even server-rendered HTML)
  • Social features (nobody needs another fitness social network)
  • Exercise library with videos (this is table stakes for big apps but a distraction for an MVP)
  • Wearable integrations (Apple Watch, Garmin — important eventually but complex)

Skip entirely:

  • Meal tracking (completely different problem, and MyFitnessPal owns this space)
  • Bodyweight tracking with photos (privacy nightmare, legal liability)
  • Gamification (leaderboards, badges — these attract the wrong users)

The MVP could be built in two weekends. I know because I've built similar scoped projects in that timeframe before. The first weekend gets you the API, database, and basic web UI. The second weekend adds the AI coaching layer and Stripe integration.


The Honest Risk Assessment

I'd be lying if I said this was a guaranteed winner. Here are the real risks:

AI coaching quality is inconsistent. LLMs can give great fitness advice and they can also hallucinate dangerous advice. You need guardrails — the system prompt should explicitly prohibit medical advice, injury rehabilitation recommendations, and drug-related suggestions. And you need a disclaimer that this is not a substitute for a qualified trainer.

The fitness app market is a graveyard. Thousands of fitness apps have launched and died. The ones that survive either have massive marketing budgets or solve a very specific niche. A micro-SaaS approach helps here — you're not trying to be the next MyFitnessPal, you're trying to get 500 paying users at $9/month. That's $4,500/month, which is a nice side income for a solo developer.

Retention is hard. People stop working out. When they stop working out, they cancel the subscription. This is structurally different from a productivity SaaS where the tool becomes embedded in someone's workflow. Fitness is inherently intermittent for most people.

But here's what makes me optimistic: the cost to build this is nearly zero if you're a developer. A weekend of work, a few dollars a month in hosting, and pennies per AI call. The downside is time. The upside is a product that scratches your own itch, teaches you about AI integration and subscription billing, and might make enough money to cover your protein powder budget.

I've built worse ideas for worse reasons. This one might actually work.


Shane Larson is the founder of Grizzly Peak Software, writing code and lifting heavy things from his cabin in Caswell Lakes, Alaska. After 30 years of tracking workouts and 30 years of writing software, he's convinced the intersection of the two is still wide open. His latest book covers training and fine-tuning large language models.

Powered by Contentful