Keep This Up - Fitness Motivation App
App Link: Keep This Up
To try it:
- On Settings tab put in an OpenRouter key (this will not be sent to a server other than OpenRouter… it’s locally saved only. Not sent to my server)
- On profile screen, fill in and save your profile.
- Upload a front/side view.
- Hit process and wait for it to finish.
- On Log tab, enter your weight/calories/etc for each day. Alternatively, to play with it, just manually change the 7-day average. And Save.
- See the prediction on the Predict tab.
Why / What
While realizing I’d triple my daily step count and calorie burn just by going on vacation, I wondered if there was an app that predicts what appearance changes you would have given Apple HealthKit trend. I couldn’t find it, so started making it. You give it today’s food, activity, and weight, and it projects forward: 3 months, 1 year, 5 years. It then generates images of what you’d probably look like at each point.
The app compares two scenarios side by side. One pretends every future day is like today. The other assumes the average of the last seven days.
Fitness apps record/report calories, steps, protein, workouts, and weight. But they don’t make the long-term result intuitive. That is all this app does, via images of your future self.
The prediction is not AI
The numeric projection is an energy/biological model. It handles:
- energy expenditure that changes as body weight changes
- calorie intake
- steps and exercise, with overlap discounting so they aren’t just added
- resistance training and protein, which affect the estimated split between fat and lean tissue
- long-term damping so projections don’t extend as a straight line forever
The outputs are still projections, but the math is transparent and it runs locally without hitting a server.
Weight is not enough to predict appearance
A future weight alone doesn’t say what somebody should look like. The same weight can correspond to different amounts of fat and lean mass. So the app tracks body composition separately and converts it into two indices:
- FMI, fat mass adjusted for height
- FFMI, fat-free mass adjusted for height
That gives a two-dimensional coordinate system instead of a single weight axis.
The visual prediction was the harder problem
The first naive approach was: take a current photo and stats, ask an image model to make the person look like the predicted future state. This didn’t work.
On top of normal image model drift, body weight alone is a poor visual instruction because two people at the same weight can look completely different depending on composition. Regenerating images every time the prediction changes is also expensive.
The reference-grid approach
The current pipeline works like this:
current photos → create normalized reference photos → create FFMI/FMI reference grid → calculate numeric future states → show nearest matching reference image
The app starts from front and side photographs. It generates normalized versions that are meant to keep pose, framing, clothing, identity, and body structure consistent. From those, it builds a personal matrix across several fat-mass and lean-mass combinations. The grid is pre-built from your own reference photos, so outputs are comparable because they come from the same personal reference system rather than unrelated generations.
The expensive operation is building the personal visual reference grid. Once that exists, ordinary numeric prediction is local. Changing calorie or activity assumptions doesn’t require another AI call. The existing body-composition grid can be reused until the baseline photos or body analysis change. That makes the architecture both cheaper and more consistent than generating a fresh image for every scenario. When the numeric model predicts a future FFMI/FMI pair, the app selects the nearest pre-generated cell.
Where OpenRouter fits
OpenRouter is only used for the parts that benefit from multimodal and image models. It does not determine the future weight. It is used for two things:
- Body analysis. A multimodal model inspects the front and side photos and estimates body-fat range, muscularity, frame proportions, and fat distribution.
- Image editing. A separate image-capable model normalizes the original photographs and generates the FFMI/FMI reference images.
The actual models are configurable because image quality, cost, and provider support change over time. The implementation plan treats pricing and model capability as dynamic rather than permanent constants.
OpenRouter is used for practical reasons:
- one API surface for multiple model providers;
- analysis and image models can be selected independently;
- easier to test new models as image-edit quality changes;
- current pricing and model capability can be queried rather than hardcoded.
I don’t want to redesign the application around one model while models are changing fast. Worst case OpenRouter goes under, and then I need to manually point at an API and get new keys.
Predictions
If you unhide the reference photo grid and click on a body type, it will manually adjust calories, protein, exercise, etc to predict getting there in 5 years. Figuring out how to get to low fat / high muscle required staging (building muscle and cutting intermitently). I modeled that as cutting while doing resistance training, with the model assuming once you’ve cut to low BF %, you’ll naturally increase your calories to build. So the numbers it pts into ‘manual’ will have your cutting calories and building resistance training minutes, assuming that your calorie intake will increase once body fat % is low.
Privacy
The app has no backend. The production application is currently one self-contained file.
The user supplies their own OpenRouter key. Numeric predictions stay local. OpenRouter analysis requests can be set for zero-data-retention routing. That ZDR option doesn’t apply to image gen though.
Improvements Needed
- Cost: It currently takes about $4 to generate the 34 images; partially due to retries. Should be able to do this cheaper. Eventually models would make this cheaper.
- Blending: Investigate if there’s an efficient way to blend images without AI, for when values are between the 16 pre-rendered views.
Other models tested on reference photo gen
https://openrouter.ai/google/gemini-3.1-flash-image?output_modalities=image#playground - $0.04611 - fast; good output - best yet , but throttling seems to kick in MAKE THIS THE DEFAULT?
https://openrouter.ai/black-forest-labs/flux.2-klein-4b?output_modalities=image#playground - $0.017/run - doesn’t maintain identity
https://openrouter.ai/qwen/qwen-image-3?output_modalities=image#playground - $0.036/run - very long generation time, but maintains identity. Seems to cache the request/return.
https://openrouter.ai/krea/krea-2-medium?output_modalities=image#playground - $0.03 - only accepts a single image as input. Made a white male into a black woman.
https://openrouter.ai/black-forest-labs/flux.2-pro?output_modalities=image#playground - $0.075 - doesn’t give option of image size (looks like 1K output); output was OK
https://openrouter.ai/bytedance-seed/seedream-5-0-lite?output_modalities=image#playground - $0.035 - very long generation time. Output not good.
https://openrouter.ai/bytedance-seed/seedream-4.5?output_modalities=image#playground - $0.04 - Won’t do 9:16 at 1K; need to do 2K. Output is OK.
https://openrouter.ai/bytedance-seed/seedream-5-0-pro?output_modalities=image#playground - $0.048 - OK generation time. Good output - maintains identity better than ‘x-ai/grok-imagine-image-quality’