Skip to content

Onboarding and backfill UX

When a user signs up for an app built on SweatStack, three things have to happen before the app is useful: account creation, wearable connection, and historical data backfill. The first two are fast (tens of seconds, total). Backfill can take a bit longer: typically 1 minute per 50-100 hours of activity history. For apps that rely on historical data being available, how you handle the waiting during backfill shapes the first impression of the app.

This guide is opinionated about what works in production. The short version: let users in immediately and show progress; don't gate the first session on a complete backfill.

What you'll build

A first-session UX flow that:

  • Authenticates and connects a wearable in one combined step (via SweatStack Connect)
  • Lets the user into the app immediately while backfill runs in the background
  • Shows clear progress so the user understands "more data is on the way"
  • Reconciles correctly when backfill finishes

The flow has three temporal phases:

   Sign up        Authorize         Backfill running        Backfill complete
   |              |                 |                       |
   v              v                 v                       v
+------+  +-------------+  +-------------------+  +-----------------------+
|      |  |  SweatStack |  |  First session:   |  |  Steady state:        |
| Your |  |  Connect    |  |  partial data,    |  |  full history,        |
| app  |  |  (auth +    |  |  progress shown   |  |  push-driven updates  |
|      |  |   wearable  |  |                   |  |                       |
|      |  |   link)     |  |                   |  |                       |
+------+  +-------------+  +-------------------+  +-----------------------+
            ~30 seconds       ~1-10 minutes               ongoing

Phase 1: sign up + connect wearable

Use SweatStack Connect so the user authenticates once, via their wearable account. SweatStack provisions the SweatStack account in the background, and the OAuth2 flow returns to your app with an access token. From the user's perspective it's a single tap.

Recommended button copy: "Connect with SweatStack". See the Connect docs for brand-kit guidance.

Phase 2: backfill, while the user explores

The moment Connect completes, SweatStack starts ingesting from the wearable. Expect 50-100 hours of activity data processed in the first minute. Backfill processing starts with most recent activities first, working backward.

Within minutes after the user first lands in your app, most of the data they'll ever care about is already there. Do not block the first session on completion.

What to show in the first session

Pull whatever's available immediately and render it. The longitudinal-data and activities endpoints work regardless of backfill progress; they return what's been ingested so far.

Show a small, persistent indicator that more data is on the way. Something like:

Importing your training history...

Use the backfill status endpoint to monitor the user's backfill.

Reconciling when more data arrives

Two reasonable patterns:

  • Pull on focus. Every time the app foregrounds, re-query the activity list.
  • Push on event. Subscribe to webhooks for activity_created events and refresh the relevant view in real time. See the native mobile app guide for the webhook-to-push gateway pattern, or refresh server-side state directly if you have a backend.

Both work. Pull-on-focus is simpler and is enough for most apps; webhook-driven is smoother for an always-foreground experience.

Phase 3: steady state

Once backfill is complete, new activities arrive within seconds of being synced from the wearable. The same activity_created webhook fires for every new activity from then on; the patterns above continue to apply unchanged. There's no separate "live" mode to switch to.

Common mistakes

  • Gating the first session on full backfill. Adds 5-10 minutes of "loading" before the user sees anything useful. By that time many will have closed the app.
  • Waiting for "all activities" before rendering. "All" is a moving target during backfill. Render whatever you have; reconcile as it grows.

Next steps