PixlFIT

A local-first iOS training log, and the coaching platform that reads from it — so a client keeps the app they already use

Published Swift · SwiftUI · Supabase · Cloudflare Workers · Stripe

A training log for iOS that works with no account at all, and PixlFIT Coach — a platform that lets a coach read from it, with the client’s permission and only for as long as they give it.

The premise is one line: the client keeps their own app. Most coaching platforms hand the client a stripped-down companion nobody wants to open, then wonder why the data is thin. Here the coach reads the app people were already using.

pixlfit.co.uk · Coach · App Store


📱 The App

  • Works with no account. Install it, log a session, never sign in. Everything lives on the device.
  • Signing in is opt-in and adds sync and backup — it is not the price of entry.
  • Tags rather than a fixed exercise list. A pulldown is a machine, a brand and a grip, so Hammer Strength wide-grip keeps its own line and never gets averaged with the one on the other side of the gym.
  • Reads from Apple Health where you allow it — steps, sleep stages, heart rate, weight.
  • Watch app, widgets, and a posing/prep mode for anyone who competes.

🏋️ For Coaches

  • One roster, worst first. Everyone’s last fortnight, adherence and volume trend in a single table.
  • Flags you tune. Inactivity, adherence, volume, stalled lifts, weight projection — thresholds are the coach’s, not the platform’s.
  • Build and push programmes that land in the client’s app as real routines they can start.
  • Messaging, check-ins and progress photos, the last of which stay off until the client turns them on.
  • Five clients free. Paid plans add spaces and give the coach’s clients the full app at no cost to them.

🧑‍💻 How It Works

The device is the source of truth, and the server is a replica. That ordering is the whole design. A log written on a plane is not pending, not queued and not degraded — it is simply the log. Sync reconciles later, and the app never blocks on the network to record a set.

Access is enforced at the database, not in the interface. A coach reaches a client’s training only while an active link exists between them, and only the client can create that link — an invitation grants nothing until it is accepted on their phone. Revoking it cuts the data off at the same layer. The coach-facing web app is a reader with no privileged key; if the interface had a bug tomorrow, the answer to “what can it reach?” would not change.

The coach platform is one file that ships as two products. A public prototype runs the entire interface against a cast of invented clients, and the live app runs the same code against real data, with a single flag deciding which. There is no separate demo build to drift out of date — a change to the roster is a change to both, and the sample data has to survive every feature the real thing gets.

No build step on the web side. Plain HTML, CSS and JavaScript served as static assets from a Cloudflare Worker. Nothing to compile, nothing to invalidate, and the deployed thing is the thing in the repository.

Colours are a cross-platform contract. Heart-rate zones, macro splits and sleep stages are pinned to the same literal values on iOS and on the web. A chart that means one thing on a phone and another on a laptop is worse than no chart, and this is the sort of drift that only shows up in front of a customer.


🎯 Design Notes

  • A quiet week is ambiguous, and the platform says so. Local-first has a sharp edge: a client whose phone has not seen Wi-Fi looks exactly like a client who has stopped training. Getting that wrong means nudging someone who has been training all week. So absence and silence are two different states, drawn differently, and the flag that fires says which one it is.

  • Nothing is written to a client’s record to make the coaching work. Flags are computed from the log each time they are asked for, against thresholds the coach sets. Nothing is stored on the client’s data that says “off track” — the client’s log stays theirs, unannotated.

  • Consent is granular, revocable, and off by default. Progress photographs are the sharpest data in the system, so they are private storage reachable only by short-lived signed links, shared only when the client turns sharing on or attaches them to a check-in, and withdrawn the moment they change their mind.

  • Ending a relationship is not the same act as ending it in anger. When a link is revoked the client’s training, plans and photographs are cut immediately — but the conversation and the coach’s own records stay readable for a month, because a coach still has a final invoice to raise and a handover to write. The roster shows exactly when that month runs out, so the interface never claims to hold something the database has already stopped returning.

  • A demo full of “Client 14” tells you nothing. The prototype’s invented roster is a cast of characters with real training histories, awkward habits and contradictory data, because the questions worth asking of a coaching tool — who is drifting, who is lying to me, who is about to get hurt — do not arise from placeholder rows.

  • The billing screen has to distinguish what you have from what you can do. A lapsed subscription still has clients in it. Deriving both from one value produced sentences like “You’re on Free. 14 of 25 client spaces in use.” — technically assembled from true parts, and nonsense.


🌐 Live

pixlfit.co.uk — the app pixlfit.co.uk/coach — the coaching platform App Store — free, with an optional Pro tier