How to bring lifts, runs, and steps into one fitness app history

A fitness app can track a lifting session, a run, and a day of steps, yet still leave the user with three disconnected histories. If you are building that experience, the hard part is deciding what “one activity history” means before the first integration ships.
Building the app shell too? See the $99 Fitness Kit, a mobile Expo + Hono starter with workout tracking, activity rings, sign-in, and a Postgres-backed app foundation. Open the live demo. Health-data sync and payments are not included, so treat the kit as a starting point and plan those integrations separately.
Start with the user's question
A person opening a fitness app usually wants a useful answer, not a database browser: what did I do, when did I do it, and how does it fit with the rest of my week? A barbell session, a run recorded by another app, and steps captured by a phone are different kinds of records. Putting them on one screen does not make them the same kind of event.
A builder's first decision is whether the history is a timeline, a set of summaries, or both. A timeline answers “what happened and when?” Summaries answer “how much did I do over this period?” These views can share data, but they should not share a vague definition of activity.
A useful first release can show three distinct event types in chronological order. Each entry should keep its original type and source visible. A strength session can show its exercises and duration; a run can show distance and duration when those values are available; steps can show a daily total. The interface can unify navigation and date grouping without pretending that the underlying measurements are interchangeable.
Keep events separate from aggregates
Start with an event model that preserves the detail the app actually owns. For example, a manually logged workout might have a stable identifier, activity type, start and end times, time-zone offset, and the user who created it. Exercise sets can live as child records with their own repetitions, weight, and order. An imported run or step total should preserve its external source and source identifier when the integration provides them.
Then derive summaries for the screens that need them. A weekly “sessions completed” card can count workout sessions. A “distance this week” card can sum run records with compatible units. A step chart can aggregate steps by local calendar day. These are separate calculations with explicit input rules, rather than a single score that silently adds unlike values together.
This distinction helps with edits too. If someone corrects a manually entered workout, update that event and recompute the affected summaries. If an imported record is removed or changed by its source, process that change as an update to the imported record. Avoid copying every incoming value into a second, indistinguishable manual event.

One codebase. iOS, Android, and web.
The Fitness Kit ships with auth, a database, and a backend already connected — no setup. Live demo at fitness-preview.otf-kit.dev.
Record provenance before syncing
Once data can arrive from multiple places, provenance becomes part of the product. Store the origin for each imported event and retain whatever stable source ID the provider gives you. That gives the app a way to recognize an update instead of showing the same run twice after a later sync.
Do not deduplicate by matching only date and duration. Two workouts can happen on the same day and last the same amount of time. Prefer a provider's record identifier. When no stable identifier exists, define a cautious matching rule using several fields, keep the original payload available for debugging where privacy policy permits, and make the rule visible in code.
Also separate “recorded at” from “happened at.” A workout may be uploaded later, or a phone may cross a time zone between the workout and the sync. Store the event's start and end timestamps and preserve the relevant offset when available. Grouping by the user's local day is a display decision; changing the underlying timestamp to make a chart look neat can move an event into the wrong date.
Treat permissions and empty states as product flows
Health data is sensitive. Request access when the user tries a feature that needs it, explain the value in plain language, and handle denial without blocking the rest of the app. Users can revoke access later, so the app should have an explicit connected, not-connected, and permission-revoked state instead of treating a missing response as zero activity.
On Android, Health Connect exposes different record types for data such as steps and exercise sessions. Its documentation also describes the permissions and records developers need to account for; use the data types your feature requires rather than requesting everything by default. A permission grant does not guarantee that a source has supplied records, so distinguish “no data yet” from “we could not read data.”
The first screen matters most. A brand-new account may have no workouts, integrations, or step history. Give that user a clear first action: log a workout, connect a source, or explore a sample screen. Do not fill a real account with invented personal history. Sample content belongs in a visibly labeled demo state; real users should see an honest empty state with a useful next step.

Ship a narrow history before a health-data platform
A common trap is starting with a promise to aggregate every device and workout source. Each integration adds permission copy, data mapping, source-specific behavior, revocation handling, and support questions. Before doing that work, ship the part you can validate: a consistent activity list for the records your app creates itself.
A practical sequence is:
- Log one type of workout and show it in a history.
- Add a second type with its own fields and display.
- Add daily steps as a separate summary, not as a fake workout.
- Let users filter the history by type and date.
- Add one external source and test imports, updates, duplicates, and revocation.
- Add cross-source summaries only when units and time windows are well defined.
At each step, ask whether the product's main screen answers a real question faster. If a “total activity” number cannot explain what it includes, remove it until the definition is clear. If a chart changes after a sync, tell the user which source contributed the new data.
Use a starter for the app foundation, not for missing integrations
The OTF Fitness Kit is aimed at builders making mobile fitness and wellness apps: its audience fits this problem more closely than a SaaS dashboard or an arcade-game starter. The latest outside-visitor funnel figures available for the last 30 days showed Fitness 6, SaaS Dashboard 5, Arcade 1, and landing templates 12 combined. These counts are small, so they are directional context rather than proof of demand; the audience match is the reason for the recommendation.
The kit's live page shows workout tracking, activity rings, onboarding, sign-in, a Postgres-backed app, and Expo-based iOS, Android, and web output. It also states that health-data sync and payments are not included. That boundary matters for this article: a starter can reduce the work of building the app shell and workout experience, but you still need to implement and validate Health Connect or HealthKit access for your own product.
If that is the work you are planning, review the Fitness Kit and its $99 scope, then try the demo before deciding whether its existing screens are a useful base. For a broader build sequence, see how to build a fitness app with AI you actually own.